Flint2 (empty) → 0.1.0.0
raw patch · 348 files changed
+91557/−0 lines, 348 filesdep +Flint2dep +QuickCheckdep +basesetup-changedbinary-added
Dependencies added: Flint2, QuickCheck, base, groups
Files
- ChangeLog.md +3/−0
- Flint2.cabal +418/−0
- LICENSE +502/−0
- README.md +75/−0
- Setup.hs +2/−0
- csrc/acb/get_str.c +23/−0
- csrc/acb/get_strd.c +23/−0
- csrc/acb/get_strn.c +23/−0
- csrc/acb_mat/entry.c +5/−0
- csrc/acb_mat/fprintn.c +21/−0
- csrc/acb_mat/get_strd.c +24/−0
- csrc/acb_mat/get_strn.c +24/−0
- csrc/acb_modular/get_str.c +16/−0
- csrc/acb_modular/inlines.c +81/−0
- csrc/acb_poly/get_strd.c +23/−0
- csrc/aprcl/fprint.c +12/−0
- csrc/aprcl/get_str.c +19/−0
- csrc/arb/get_str_.c +23/−0
- csrc/arb/get_strd.c +23/−0
- csrc/arb/get_strn.c +23/−0
- csrc/arb/midref.c +12/−0
- csrc/arb_calc/get_strd.c +22/−0
- csrc/arb_calc/inlines.c +59/−0
- csrc/arb_fpwrap/fpwrap.c +798/−0
- csrc/arb_mat/entry.c +5/−0
- csrc/arb_mat/fprintn.c +21/−0
- csrc/arb_mat/get_strd.c +24/−0
- csrc/arb_mat/get_strn.c +24/−0
- csrc/arb_poly/get_strd.c +23/−0
- csrc/arf/inlines.c +745/−0
- csrc/bool_mat/get_str.c +18/−0
- csrc/d_mat/entry.c +5/−0
- csrc/d_mat/io.c +32/−0
- csrc/dlog/inlines.c +5/−0
- csrc/double_interval/fprint.c +9/−0
- csrc/double_interval/get_str.c +24/−0
- csrc/fmpq/cfrac_st.c +59/−0
- csrc/fmpq/get_fmpz_frac.c +6/−0
- csrc/fmpq/mediant.c +20/−0
- csrc/fmpq_mat/fprint.c +23/−0
- csrc/fmpq_mat/get_str.c +24/−0
- csrc/fmpq_poly/io_as_series.c +82/−0
- csrc/fmpq_poly/monien.c +62/−0
- csrc/fmpq_vec/get_str.c +24/−0
- csrc/fmpz/clear.c +11/−0
- csrc/fmpz/init.c +11/−0
- csrc/fmpz_factor/clear.c +12/−0
- csrc/fmpz_factor/fprint.c +40/−0
- csrc/fmpz_factor/get_str.c +24/−0
- csrc/fmpz_factor/init.c +12/−0
- csrc/fmpz_mat/get_str.c +24/−0
- csrc/fmpz_mat/get_str_pretty.c +24/−0
- csrc/fmpz_mod_poly_factor/fprint.c +20/−0
- csrc/fmpz_mod_poly_factor/fprint_pretty.c +20/−0
- csrc/fmpz_mod_poly_factor/get_str.c +24/−0
- csrc/fmpz_mod_poly_factor/get_str_pretty.c +25/−0
- csrc/fmpz_mpoly_q/fprint.c +37/−0
- csrc/fmpz_mpoly_q/get_str_pretty.c +24/−0
- csrc/fmpz_poly_mat/fprint.c +39/−0
- csrc/fmpz_poly_mat/get_str.c +24/−0
- csrc/fmpz_vec/get_str.c +24/−0
- csrc/fmpzi/fprint.c +18/−0
- csrc/fmpzi/get_str.c +23/−0
- csrc/fq/ctx_get_str.c +23/−0
- csrc/fq_mat/get_str.c +24/−0
- csrc/fq_mat/get_str_pretty.c +24/−0
- csrc/fq_nmod/ctx_get_str.c +23/−0
- csrc/fq_nmod_mat/get_str.c +24/−0
- csrc/fq_nmod_mat/get_str_pretty.c +24/−0
- csrc/fq_zech/ctx_get_str.c +23/−0
- csrc/fq_zech_mat/get_str.c +24/−0
- csrc/fq_zech_mat/get_str_pretty.c +24/−0
- csrc/mag/get_str.c +23/−0
- csrc/mpfr_mat/swap_entrywise.c +14/−0
- csrc/nmod_poly_factor/fprint.c +29/−0
- csrc/nmod_poly_factor/fprint_pretty.c +25/−0
- csrc/nmod_poly_factor/get_str.c +23/−0
- csrc/nmod_poly_factor/get_str_pretty.c +23/−0
- csrc/nmod_poly_mat/fprint.c +29/−0
- csrc/nmod_poly_mat/get_str.c +24/−0
- csrc/padic_mat/get_str.c +24/−0
- csrc/padic_mat/get_str_pretty.c +24/−0
- csrc/padic_poly/get_str.c +16/−0
- csrc/padic_poly/get_str_pretty.c +16/−0
- csrc/perm/mat.c +11/−0
- csrc/perm/order.c +38/−0
- csrc/perm/power.c +26/−0
- csrc/perm/print_pretty.c +82/−0
- csrc/psl2z/word_problem.c +301/−0
- csrc/qadic/get_str_pretty.c +15/−0
- csrc/qfb/fprint.c +26/−0
- csrc/qfb/get_str.c +22/−0
- csrc/qqbar/fprint.c +34/−0
- csrc/qqbar/fprintn.c +39/−0
- csrc/qqbar/get_str.c +22/−0
- csrc/qqbar/get_strn.c +37/−0
- docs/out.png binary
- src/Data/Number/Flint.hs +342/−0
- src/Data/Number/Flint/APRCL.hs +6/−0
- src/Data/Number/Flint/APRCL/FFI.hsc +759/−0
- src/Data/Number/Flint/Acb.hs +33/−0
- src/Data/Number/Flint/Acb/Acf.hs +5/−0
- src/Data/Number/Flint/Acb/Acf/FFI.hsc +179/−0
- src/Data/Number/Flint/Acb/Calc.hs +10/−0
- src/Data/Number/Flint/Acb/Calc/FFI.hsc +284/−0
- src/Data/Number/Flint/Acb/ComplexField.hs +286/−0
- src/Data/Number/Flint/Acb/DFT.hs +24/−0
- src/Data/Number/Flint/Acb/DFT/FFI.hsc +619/−0
- src/Data/Number/Flint/Acb/Dirichlet.hs +21/−0
- src/Data/Number/Flint/Acb/Dirichlet/FFI.hsc +1159/−0
- src/Data/Number/Flint/Acb/Elliptic.hs +23/−0
- src/Data/Number/Flint/Acb/Elliptic/FFI.hsc +422/−0
- src/Data/Number/Flint/Acb/FFI.hsc +1903/−0
- src/Data/Number/Flint/Acb/Hypgeom.hs +5/−0
- src/Data/Number/Flint/Acb/Hypgeom/FFI.hsc +1736/−0
- src/Data/Number/Flint/Acb/Instances.hs +17/−0
- src/Data/Number/Flint/Acb/Mat.hs +14/−0
- src/Data/Number/Flint/Acb/Mat/FFI.hsc +1162/−0
- src/Data/Number/Flint/Acb/Mat/Instances.hs +16/−0
- src/Data/Number/Flint/Acb/Modular.hs +26/−0
- src/Data/Number/Flint/Acb/Modular/FFI.hsc +907/−0
- src/Data/Number/Flint/Acb/Modular/Instances.hs +57/−0
- src/Data/Number/Flint/Acb/Poly.hs +16/−0
- src/Data/Number/Flint/Acb/Poly/FFI.hsc +1839/−0
- src/Data/Number/Flint/Acb/Poly/Instances.hs +64/−0
- src/Data/Number/Flint/Acb/Types.hs +6/−0
- src/Data/Number/Flint/Acb/Types/FFI.hsc +30/−0
- src/Data/Number/Flint/Arb.hs +53/−0
- src/Data/Number/Flint/Arb/Arf.hs +26/−0
- src/Data/Number/Flint/Arb/Arf/FFI.hsc +1270/−0
- src/Data/Number/Flint/Arb/Calc.hs +16/−0
- src/Data/Number/Flint/Arb/Calc/FFI.hsc +280/−0
- src/Data/Number/Flint/Arb/FFI.hsc +2868/−0
- src/Data/Number/Flint/Arb/Fmpz/Poly.hs +20/−0
- src/Data/Number/Flint/Arb/Fmpz/Poly/FFI.hsc +214/−0
- src/Data/Number/Flint/Arb/FpWrap.hs +59/−0
- src/Data/Number/Flint/Arb/FpWrap/FFI.hsc +1146/−0
- src/Data/Number/Flint/Arb/Hypgeom.hs +17/−0
- src/Data/Number/Flint/Arb/Hypgeom/FFI.hsc +1063/−0
- src/Data/Number/Flint/Arb/Instances.hs +18/−0
- src/Data/Number/Flint/Arb/Mag.hs +41/−0
- src/Data/Number/Flint/Arb/Mag/FFI.hsc +859/−0
- src/Data/Number/Flint/Arb/Mat.hs +13/−0
- src/Data/Number/Flint/Arb/Mat/FFI.hsc +1133/−0
- src/Data/Number/Flint/Arb/Mat/Instances.hs +19/−0
- src/Data/Number/Flint/Arb/Poly.hs +16/−0
- src/Data/Number/Flint/Arb/Poly/FFI.hsc +1981/−0
- src/Data/Number/Flint/Arb/Poly/Instances.hs +64/−0
- src/Data/Number/Flint/Arb/RealField.hs +327/−0
- src/Data/Number/Flint/Arb/Types.hs +6/−0
- src/Data/Number/Flint/Arb/Types/FFI.hsc +141/−0
- src/Data/Number/Flint/Bernoulli.hs +25/−0
- src/Data/Number/Flint/Bernoulli/FFI.hsc +179/−0
- src/Data/Number/Flint/FFT.hs +12/−0
- src/Data/Number/Flint/FFT/FFI.hsc +711/−0
- src/Data/Number/Flint/Flint.hs +17/−0
- src/Data/Number/Flint/Flint/External.hs +9/−0
- src/Data/Number/Flint/Flint/External/GMP/FFI.hsc +54/−0
- src/Data/Number/Flint/Flint/External/Mpfr/FFI.hsc +33/−0
- src/Data/Number/Flint/Flint/FFI.hsc +191/−0
- src/Data/Number/Flint/Flint/Internal.hs +7/−0
- src/Data/Number/Flint/Flint/Internal/FFI.hsc +53/−0
- src/Data/Number/Flint/Fmpq.hs +12/−0
- src/Data/Number/Flint/Fmpq/FFI.hsc +1189/−0
- src/Data/Number/Flint/Fmpq/Instances.hs +133/−0
- src/Data/Number/Flint/Fmpq/MPoly.hs +5/−0
- src/Data/Number/Flint/Fmpq/MPoly/FFI.hsc +1207/−0
- src/Data/Number/Flint/Fmpq/MPoly/Factor.hs +5/−0
- src/Data/Number/Flint/Fmpq/MPoly/Factor/FFI.hsc +179/−0
- src/Data/Number/Flint/Fmpq/Mat.hs +5/−0
- src/Data/Number/Flint/Fmpq/Mat/FFI.hsc +876/−0
- src/Data/Number/Flint/Fmpq/Mat/Instances.hs +73/−0
- src/Data/Number/Flint/Fmpq/Poly.hs +5/−0
- src/Data/Number/Flint/Fmpq/Poly/FFI.hsc +2484/−0
- src/Data/Number/Flint/Fmpq/Poly/Instances.hs +63/−0
- src/Data/Number/Flint/Fmpq/Vec.hs +5/−0
- src/Data/Number/Flint/Fmpq/Vec/FFI.hsc +135/−0
- src/Data/Number/Flint/Fmpz.hs +69/−0
- src/Data/Number/Flint/Fmpz/Arith.hs +5/−0
- src/Data/Number/Flint/Fmpz/Arith/FFI.hsc +726/−0
- src/Data/Number/Flint/Fmpz/FFI.hsc +2380/−0
- src/Data/Number/Flint/Fmpz/Factor.hs +5/−0
- src/Data/Number/Flint/Fmpz/Factor/FFI.hsc +451/−0
- src/Data/Number/Flint/Fmpz/Instances.hs +139/−0
- src/Data/Number/Flint/Fmpz/LLL.hs +5/−0
- src/Data/Number/Flint/Fmpz/LLL/FFI.hsc +496/−0
- src/Data/Number/Flint/Fmpz/MPoly.hs +5/−0
- src/Data/Number/Flint/Fmpz/MPoly/FFI.hsc +1568/−0
- src/Data/Number/Flint/Fmpz/MPoly/Factor.hs +5/−0
- src/Data/Number/Flint/Fmpz/MPoly/Factor/FFI.hsc +160/−0
- src/Data/Number/Flint/Fmpz/MPoly/Q.hs +23/−0
- src/Data/Number/Flint/Fmpz/MPoly/Q/FFI.hsc +306/−0
- src/Data/Number/Flint/Fmpz/Mat.hs +34/−0
- src/Data/Number/Flint/Fmpz/Mat/FFI.hsc +1833/−0
- src/Data/Number/Flint/Fmpz/Mat/Instances.hs +60/−0
- src/Data/Number/Flint/Fmpz/Mod.hs +5/−0
- src/Data/Number/Flint/Fmpz/Mod/FFI.hsc +283/−0
- src/Data/Number/Flint/Fmpz/Mod/MPoly.hs +5/−0
- src/Data/Number/Flint/Fmpz/Mod/MPoly/FFI.hsc +1192/−0
- src/Data/Number/Flint/Fmpz/Mod/MPoly/Factor.hs +5/−0
- src/Data/Number/Flint/Fmpz/Mod/MPoly/Factor/FFI.hsc +159/−0
- src/Data/Number/Flint/Fmpz/Mod/Mat.hs +5/−0
- src/Data/Number/Flint/Fmpz/Mod/Mat/FFI.hsc +588/−0
- src/Data/Number/Flint/Fmpz/Mod/Poly.hs +5/−0
- src/Data/Number/Flint/Fmpz/Mod/Poly/FFI.hsc +2981/−0
- src/Data/Number/Flint/Fmpz/Mod/Poly/Factor.hs +5/−0
- src/Data/Number/Flint/Fmpz/Mod/Poly/Factor/FFI.hsc +365/−0
- src/Data/Number/Flint/Fmpz/Mod/Vec.hs +5/−0
- src/Data/Number/Flint/Fmpz/Mod/Vec/FFI.hsc +106/−0
- src/Data/Number/Flint/Fmpz/Poly.hs +37/−0
- src/Data/Number/Flint/Fmpz/Poly/FFI.hsc +4517/−0
- src/Data/Number/Flint/Fmpz/Poly/Factor.hs +5/−0
- src/Data/Number/Flint/Fmpz/Poly/Factor/FFI.hsc +247/−0
- src/Data/Number/Flint/Fmpz/Poly/Instances.hs +167/−0
- src/Data/Number/Flint/Fmpz/Poly/Mat.hs +5/−0
- src/Data/Number/Flint/Fmpz/Poly/Mat/FFI.hsc +642/−0
- src/Data/Number/Flint/Fmpz/Poly/Q.hs +5/−0
- src/Data/Number/Flint/Fmpz/Poly/Q/FFI.hsc +425/−0
- src/Data/Number/Flint/Fmpz/Poly/Q/Instances.hs +96/−0
- src/Data/Number/Flint/Fmpz/Vec.hs +5/−0
- src/Data/Number/Flint/Fmpz/Vec/FFI.hsc +609/−0
- src/Data/Number/Flint/Fq.hs +49/−0
- src/Data/Number/Flint/Fq/Embed.hs +6/−0
- src/Data/Number/Flint/Fq/Embed/FFI.hsc +153/−0
- src/Data/Number/Flint/Fq/FFI.hsc +864/−0
- src/Data/Number/Flint/Fq/Mat.hs +16/−0
- src/Data/Number/Flint/Fq/Mat/FFI.hsc +773/−0
- src/Data/Number/Flint/Fq/NMod.hs +12/−0
- src/Data/Number/Flint/Fq/NMod/Embed.hs +12/−0
- src/Data/Number/Flint/Fq/NMod/Embed/FFI.hsc +159/−0
- src/Data/Number/Flint/Fq/NMod/FFI.hsc +840/−0
- src/Data/Number/Flint/Fq/NMod/MPoly.hs +5/−0
- src/Data/Number/Flint/Fq/NMod/MPoly/FFI.hsc +1028/−0
- src/Data/Number/Flint/Fq/NMod/MPoly/Factor.hs +5/−0
- src/Data/Number/Flint/Fq/NMod/MPoly/Factor/FFI.hsc +167/−0
- src/Data/Number/Flint/Fq/NMod/Mat.hs +16/−0
- src/Data/Number/Flint/Fq/NMod/Mat/FFI.hsc +757/−0
- src/Data/Number/Flint/Fq/NMod/Poly.hs +5/−0
- src/Data/Number/Flint/Fq/NMod/Poly/FFI.hsc +1951/−0
- src/Data/Number/Flint/Fq/NMod/Poly/Factor.hs +5/−0
- src/Data/Number/Flint/Fq/NMod/Poly/Factor/FFI.hsc +387/−0
- src/Data/Number/Flint/Fq/NMod/Types.hs +6/−0
- src/Data/Number/Flint/Fq/NMod/Types/FFI.hsc +48/−0
- src/Data/Number/Flint/Fq/NMod/Vec.hs +12/−0
- src/Data/Number/Flint/Fq/NMod/Vec/FFI.hsc +180/−0
- src/Data/Number/Flint/Fq/Poly.hs +16/−0
- src/Data/Number/Flint/Fq/Poly/FFI.hsc +1992/−0
- src/Data/Number/Flint/Fq/Poly/Factor.hs +5/−0
- src/Data/Number/Flint/Fq/Poly/Factor/FFI.hsc +388/−0
- src/Data/Number/Flint/Fq/Types.hs +6/−0
- src/Data/Number/Flint/Fq/Types/FFI.hsc +28/−0
- src/Data/Number/Flint/Fq/Vec.hs +12/−0
- src/Data/Number/Flint/Fq/Vec/FFI.hsc +166/−0
- src/Data/Number/Flint/Fq/Zech.hs +12/−0
- src/Data/Number/Flint/Fq/Zech/Embed.hs +12/−0
- src/Data/Number/Flint/Fq/Zech/Embed/FFI.hsc +159/−0
- src/Data/Number/Flint/Fq/Zech/FFI.hsc +894/−0
- src/Data/Number/Flint/Fq/Zech/Mat.hs +12/−0
- src/Data/Number/Flint/Fq/Zech/Mat/FFI.hsc +726/−0
- src/Data/Number/Flint/Fq/Zech/Poly.hs +12/−0
- src/Data/Number/Flint/Fq/Zech/Poly/FFI.hsc +1916/−0
- src/Data/Number/Flint/Fq/Zech/Poly/Factor.hs +5/−0
- src/Data/Number/Flint/Fq/Zech/Poly/Factor/FFI.hsc +389/−0
- src/Data/Number/Flint/Fq/Zech/Types.hs +13/−0
- src/Data/Number/Flint/Fq/Zech/Types/FFI.hsc +39/−0
- src/Data/Number/Flint/Fq/Zech/Vec.hs +12/−0
- src/Data/Number/Flint/Fq/Zech/Vec/FFI.hsc +180/−0
- src/Data/Number/Flint/Groups/Bool/Mat.hs +45/−0
- src/Data/Number/Flint/Groups/Bool/Mat/FFI.hsc +427/−0
- src/Data/Number/Flint/Groups/Bool/Mat/Instances.hs +14/−0
- src/Data/Number/Flint/Groups/DLog.hs +32/−0
- src/Data/Number/Flint/Groups/DLog/FFI.hsc +271/−0
- src/Data/Number/Flint/Groups/Dirichlet.hs +46/−0
- src/Data/Number/Flint/Groups/Dirichlet/FFI.hsc +464/−0
- src/Data/Number/Flint/Groups/Perm.hs +13/−0
- src/Data/Number/Flint/Groups/Perm/FFI.hsc +158/−0
- src/Data/Number/Flint/Groups/Qfb.hs +13/−0
- src/Data/Number/Flint/Groups/Qfb/FFI.hsc +383/−0
- src/Data/Number/Flint/Groups/Qfb/Instances.hs +16/−0
- src/Data/Number/Flint/Hypgeom.hs +125/−0
- src/Data/Number/Flint/Hypgeom/FFI.hsc +143/−0
- src/Data/Number/Flint/MPoly.hs +13/−0
- src/Data/Number/Flint/MPoly/FFI.hsc +611/−0
- src/Data/Number/Flint/NF.hs +13/−0
- src/Data/Number/Flint/NF/Elem.hs +6/−0
- src/Data/Number/Flint/NF/Elem/FFI.hsc +616/−0
- src/Data/Number/Flint/NF/FFI.hsc +72/−0
- src/Data/Number/Flint/NF/Fmpzi.hs +10/−0
- src/Data/Number/Flint/NF/Fmpzi/FFI.hsc +273/−0
- src/Data/Number/Flint/NF/Fmpzi/Instances.hs +50/−0
- src/Data/Number/Flint/NF/QQbar.hs +31/−0
- src/Data/Number/Flint/NF/QQbar/FFI.hsc +1511/−0
- src/Data/Number/Flint/NF/QQbar/Instances.hs +50/−0
- src/Data/Number/Flint/NMod.hs +12/−0
- src/Data/Number/Flint/NMod/FFI.hsc +214/−0
- src/Data/Number/Flint/NMod/MPoly.hs +5/−0
- src/Data/Number/Flint/NMod/MPoly/FFI.hsc +1161/−0
- src/Data/Number/Flint/NMod/MPoly/Factor.hs +5/−0
- src/Data/Number/Flint/NMod/MPoly/Factor/FFI.hsc +163/−0
- src/Data/Number/Flint/NMod/Mat.hs +5/−0
- src/Data/Number/Flint/NMod/Mat/FFI.hsc +915/−0
- src/Data/Number/Flint/NMod/Poly.hs +5/−0
- src/Data/Number/Flint/NMod/Poly/FFI.hsc +3412/−0
- src/Data/Number/Flint/NMod/Poly/Factor.hs +5/−0
- src/Data/Number/Flint/NMod/Poly/Factor/FFI.hsc +374/−0
- src/Data/Number/Flint/NMod/Poly/Instances.hs +120/−0
- src/Data/Number/Flint/NMod/Poly/Mat.hs +5/−0
- src/Data/Number/Flint/NMod/Poly/Mat/FFI.hsc +589/−0
- src/Data/Number/Flint/NMod/Types.hs +7/−0
- src/Data/Number/Flint/NMod/Types/FFI.hsc +86/−0
- src/Data/Number/Flint/NMod/Vec.hs +5/−0
- src/Data/Number/Flint/NMod/Vec/FFI.hsc +193/−0
- src/Data/Number/Flint/Padic.hs +60/−0
- src/Data/Number/Flint/Padic/FFI.hsc +936/−0
- src/Data/Number/Flint/Padic/Mat.hs +5/−0
- src/Data/Number/Flint/Padic/Mat/FFI.hsc +477/−0
- src/Data/Number/Flint/Padic/Poly.hs +25/−0
- src/Data/Number/Flint/Padic/Poly/FFI.hsc +778/−0
- src/Data/Number/Flint/Partitions.hs +28/−0
- src/Data/Number/Flint/Partitions/FFI.hsc +102/−0
- src/Data/Number/Flint/QSieve.hs +13/−0
- src/Data/Number/Flint/QSieve/FFI.hsc +356/−0
- src/Data/Number/Flint/Qadic.hs +85/−0
- src/Data/Number/Flint/Qadic/FFI.hsc +878/−0
- src/Data/Number/Flint/Quotient.hs +27/−0
- src/Data/Number/Flint/Support/D/Extras.hs +5/−0
- src/Data/Number/Flint/Support/D/Extras/FFI.hsc +94/−0
- src/Data/Number/Flint/Support/D/Interval.hs +9/−0
- src/Data/Number/Flint/Support/D/Interval/FFI.hsc +257/−0
- src/Data/Number/Flint/Support/D/Mat.hs +5/−0
- src/Data/Number/Flint/Support/D/Mat/FFI.hsc +302/−0
- src/Data/Number/Flint/Support/D/Mat/Instances.hs +16/−0
- src/Data/Number/Flint/Support/D/Vec.hs +5/−0
- src/Data/Number/Flint/Support/D/Vec/FFI.hsc +154/−0
- src/Data/Number/Flint/Support/Mpf/Mat.hs +5/−0
- src/Data/Number/Flint/Support/Mpf/Mat/FFI.hsc +241/−0
- src/Data/Number/Flint/Support/Mpf/Vec.hs +5/−0
- src/Data/Number/Flint/Support/Mpf/Vec/FFI.hsc +175/−0
- src/Data/Number/Flint/Support/Mpfr/Mat.hs +5/−0
- src/Data/Number/Flint/Support/Mpfr/Mat/FFI.hsc +151/−0
- src/Data/Number/Flint/Support/Mpfr/Vec.hs +5/−0
- src/Data/Number/Flint/Support/Mpfr/Vec/FFI.hsc +84/−0
- src/Data/Number/Flint/Support/ULong/Extras.hs +5/−0
- src/Data/Number/Flint/Support/ULong/Extras/FFI.hsc +1870/−0
- src/Data/Number/Flint/ThreadPool.hs +13/−0
- src/Data/Number/Flint/ThreadPool/FFI.hsc +131/−0
- src/Data/Number/Flint/UFD.hs +24/−0
- test/Spec.hs +2/−0
+ ChangeLog.md view
@@ -0,0 +1,3 @@+# Changelog for Flint2++## Unreleased changes
+ Flint2.cabal view
@@ -0,0 +1,418 @@+cabal-version: 1.18++-- This file has been generated from package.yaml by hpack version 0.35.1.+--+-- see: https://github.com/sol/hpack++name: Flint2+version: 0.1.0.0+synopsis: Haskell bindings for the flint library for number theory+description: Please see the README on GitHub at <https://github.com/monien/Flint2#readme>+category: Math+homepage: https://github.com/monien/Flint2#readme+bug-reports: https://github.com/monien/Flint2/issues+author: Hartmut Monien+maintainer: hmonien@uni-bonn.de+copyright: Copyright (c) 2022 Hartmut Monien+license: BSD3+license-file: LICENSE+build-type: Simple+extra-source-files:+ README.md+ ChangeLog.md+extra-doc-files:+ docs/out.png++source-repository head+ type: git+ location: https://github.com/monien/Flint2++library+ exposed-modules:+ Data.Number.Flint+ Data.Number.Flint.Flint+ Data.Number.Flint.Flint.External+ Data.Number.Flint.Flint.Internal+ Data.Number.Flint.MPoly+ Data.Number.Flint.UFD+ Data.Number.Flint.Quotient+ Data.Number.Flint.Fmpz+ Data.Number.Flint.Fmpz.Instances+ Data.Number.Flint.Fmpz.Arith+ Data.Number.Flint.Fmpz.Factor+ Data.Number.Flint.Fmpz.Mat+ Data.Number.Flint.Fmpz.Mat.Instances+ Data.Number.Flint.Fmpz.Vec+ Data.Number.Flint.Fmpz.Poly+ Data.Number.Flint.Fmpz.Poly.Instances+ Data.Number.Flint.Fmpz.Poly.Factor+ Data.Number.Flint.Fmpz.Poly.Mat+ Data.Number.Flint.Fmpz.Poly.Q+ Data.Number.Flint.Fmpz.Poly.Q.Instances+ Data.Number.Flint.Fmpz.MPoly+ Data.Number.Flint.Fmpz.MPoly.Factor+ Data.Number.Flint.Fmpz.MPoly.Q+ Data.Number.Flint.Fmpz.LLL+ Data.Number.Flint.Fmpz.Mod+ Data.Number.Flint.Fmpz.Mod.Poly+ Data.Number.Flint.Fmpz.Mod.Poly.Factor+ Data.Number.Flint.Fmpz.Mod.MPoly+ Data.Number.Flint.Fmpz.Mod.MPoly.Factor+ Data.Number.Flint.Fmpz.Mod.Mat+ Data.Number.Flint.Fmpz.Mod.Vec+ Data.Number.Flint.Fmpq+ Data.Number.Flint.Fmpq.Instances+ Data.Number.Flint.Fmpq.Mat+ Data.Number.Flint.Fmpq.Mat.Instances+ Data.Number.Flint.Fmpq.Vec+ Data.Number.Flint.Fmpq.Poly+ Data.Number.Flint.Fmpq.Poly.Instances+ Data.Number.Flint.Fmpq.MPoly+ Data.Number.Flint.Fmpq.MPoly.Factor+ Data.Number.Flint.NMod.Types+ Data.Number.Flint.NMod+ Data.Number.Flint.NMod.Poly+ Data.Number.Flint.NMod.Poly.Instances+ Data.Number.Flint.NMod.Poly.Factor+ Data.Number.Flint.NMod.Poly.Mat+ Data.Number.Flint.NMod.MPoly+ Data.Number.Flint.NMod.MPoly.Factor+ Data.Number.Flint.NMod.Mat+ Data.Number.Flint.NMod.Vec+ Data.Number.Flint.Groups.Perm+ Data.Number.Flint.Groups.Qfb+ Data.Number.Flint.Groups.Qfb.Instances+ Data.Number.Flint.Groups.Dirichlet+ Data.Number.Flint.Groups.DLog+ Data.Number.Flint.Groups.Bool.Mat+ Data.Number.Flint.Groups.Bool.Mat.Instances+ Data.Number.Flint.APRCL+ Data.Number.Flint.FFT+ Data.Number.Flint.QSieve+ Data.Number.Flint.Fq.Types+ Data.Number.Flint.Fq+ Data.Number.Flint.Fq.Embed+ Data.Number.Flint.Fq.Poly+ Data.Number.Flint.Fq.Poly.Factor+ Data.Number.Flint.Fq.Mat+ Data.Number.Flint.Fq.Vec+ Data.Number.Flint.Fq.NMod.Types+ Data.Number.Flint.Fq.NMod+ Data.Number.Flint.Fq.NMod.Embed+ Data.Number.Flint.Fq.NMod.Poly+ Data.Number.Flint.Fq.NMod.Poly.Factor+ Data.Number.Flint.Fq.NMod.MPoly+ Data.Number.Flint.Fq.NMod.MPoly.Factor+ Data.Number.Flint.Fq.NMod.Mat+ Data.Number.Flint.Fq.NMod.Vec+ Data.Number.Flint.Fq.Zech.Types+ Data.Number.Flint.Fq.Zech+ Data.Number.Flint.Fq.Zech.Embed+ Data.Number.Flint.Fq.Zech.Poly+ Data.Number.Flint.Fq.Zech.Poly.Factor+ Data.Number.Flint.Fq.Zech.Vec+ Data.Number.Flint.Fq.Zech.Mat+ Data.Number.Flint.Padic+ Data.Number.Flint.Padic.Poly+ Data.Number.Flint.Padic.Mat+ Data.Number.Flint.Qadic+ Data.Number.Flint.Support.ULong.Extras+ Data.Number.Flint.Support.D.Extras+ Data.Number.Flint.Support.D.Interval+ Data.Number.Flint.Support.D.Mat+ Data.Number.Flint.Support.D.Mat.Instances+ Data.Number.Flint.Support.D.Vec+ Data.Number.Flint.Support.Mpf.Mat+ Data.Number.Flint.Support.Mpf.Vec+ Data.Number.Flint.Support.Mpfr.Mat+ Data.Number.Flint.Support.Mpfr.Vec+ Data.Number.Flint.ThreadPool+ Data.Number.Flint.Arb.Types+ Data.Number.Flint.Arb+ Data.Number.Flint.Arb.Instances+ Data.Number.Flint.Arb.Mag+ Data.Number.Flint.Arb.Arf+ Data.Number.Flint.Arb.Poly+ Data.Number.Flint.Arb.Poly.Instances+ Data.Number.Flint.Arb.Fmpz.Poly+ Data.Number.Flint.Arb.Mat+ Data.Number.Flint.Arb.Mat.Instances+ Data.Number.Flint.Arb.Hypgeom+ Data.Number.Flint.Arb.RealField+ Data.Number.Flint.Arb.Calc+ Data.Number.Flint.Arb.FpWrap+ Data.Number.Flint.Acb.Types+ Data.Number.Flint.Acb+ Data.Number.Flint.Acb.Instances+ Data.Number.Flint.Acb.Acf+ Data.Number.Flint.Acb.Poly+ Data.Number.Flint.Acb.Poly.Instances+ Data.Number.Flint.Acb.Mat+ Data.Number.Flint.Acb.Mat.Instances+ Data.Number.Flint.Acb.Hypgeom+ Data.Number.Flint.Acb.Elliptic+ Data.Number.Flint.Acb.Modular+ Data.Number.Flint.Acb.Modular.Instances+ Data.Number.Flint.Acb.Dirichlet+ Data.Number.Flint.Acb.DFT+ Data.Number.Flint.Acb.ComplexField+ Data.Number.Flint.Acb.Calc+ Data.Number.Flint.Bernoulli+ Data.Number.Flint.Partitions+ Data.Number.Flint.Hypgeom+ Data.Number.Flint.NF+ Data.Number.Flint.NF.Elem+ Data.Number.Flint.NF.Fmpzi+ Data.Number.Flint.NF.Fmpzi.Instances+ Data.Number.Flint.NF.QQbar+ Data.Number.Flint.NF.QQbar.Instances+ other-modules:+ Data.Number.Flint.Flint.FFI+ Data.Number.Flint.Flint.External.GMP.FFI+ Data.Number.Flint.Flint.External.Mpfr.FFI+ Data.Number.Flint.Flint.Internal.FFI+ Data.Number.Flint.MPoly.FFI+ Data.Number.Flint.Fmpz.FFI+ Data.Number.Flint.Fmpz.Arith.FFI+ Data.Number.Flint.Fmpz.Factor.FFI+ Data.Number.Flint.Fmpz.Mat.FFI+ Data.Number.Flint.Fmpz.Vec.FFI+ Data.Number.Flint.Fmpz.Poly.FFI+ Data.Number.Flint.Fmpz.Poly.Factor.FFI+ Data.Number.Flint.Fmpz.Poly.Mat.FFI+ Data.Number.Flint.Fmpz.Poly.Q.FFI+ Data.Number.Flint.Fmpz.MPoly.FFI+ Data.Number.Flint.Fmpz.MPoly.Factor.FFI+ Data.Number.Flint.Fmpz.MPoly.Q.FFI+ Data.Number.Flint.Fmpz.LLL.FFI+ Data.Number.Flint.Fmpz.Mod.FFI+ Data.Number.Flint.Fmpz.Mod.Poly.FFI+ Data.Number.Flint.Fmpz.Mod.Poly.Factor.FFI+ Data.Number.Flint.Fmpz.Mod.MPoly.FFI+ Data.Number.Flint.Fmpz.Mod.MPoly.Factor.FFI+ Data.Number.Flint.Fmpz.Mod.Mat.FFI+ Data.Number.Flint.Fmpz.Mod.Vec.FFI+ Data.Number.Flint.Fmpq.FFI+ Data.Number.Flint.Fmpq.Mat.FFI+ Data.Number.Flint.Fmpq.Vec.FFI+ Data.Number.Flint.Fmpq.Poly.FFI+ Data.Number.Flint.Fmpq.MPoly.FFI+ Data.Number.Flint.Fmpq.MPoly.Factor.FFI+ Data.Number.Flint.NMod.Types.FFI+ Data.Number.Flint.NMod.FFI+ Data.Number.Flint.NMod.Poly.FFI+ Data.Number.Flint.NMod.Poly.Factor.FFI+ Data.Number.Flint.NMod.Poly.Mat.FFI+ Data.Number.Flint.NMod.MPoly.FFI+ Data.Number.Flint.NMod.MPoly.Factor.FFI+ Data.Number.Flint.NMod.Mat.FFI+ Data.Number.Flint.NMod.Vec.FFI+ Data.Number.Flint.Groups.Perm.FFI+ Data.Number.Flint.Groups.Qfb.FFI+ Data.Number.Flint.Groups.Dirichlet.FFI+ Data.Number.Flint.Groups.DLog.FFI+ Data.Number.Flint.Groups.Bool.Mat.FFI+ Data.Number.Flint.APRCL.FFI+ Data.Number.Flint.FFT.FFI+ Data.Number.Flint.QSieve.FFI+ Data.Number.Flint.Fq.FFI+ Data.Number.Flint.Fq.Types.FFI+ Data.Number.Flint.Fq.Embed.FFI+ Data.Number.Flint.Fq.Poly.FFI+ Data.Number.Flint.Fq.Poly.Factor.FFI+ Data.Number.Flint.Fq.Mat.FFI+ Data.Number.Flint.Fq.Vec.FFI+ Data.Number.Flint.Fq.NMod.FFI+ Data.Number.Flint.Fq.NMod.Embed.FFI+ Data.Number.Flint.Fq.NMod.Types.FFI+ Data.Number.Flint.Fq.NMod.Poly.FFI+ Data.Number.Flint.Fq.NMod.Poly.Factor.FFI+ Data.Number.Flint.Fq.NMod.MPoly.FFI+ Data.Number.Flint.Fq.NMod.MPoly.Factor.FFI+ Data.Number.Flint.Fq.NMod.Mat.FFI+ Data.Number.Flint.Fq.NMod.Vec.FFI+ Data.Number.Flint.Fq.Zech.FFI+ Data.Number.Flint.Fq.Zech.Embed.FFI+ Data.Number.Flint.Fq.Zech.Types.FFI+ Data.Number.Flint.Fq.Zech.Poly.FFI+ Data.Number.Flint.Fq.Zech.Poly.Factor.FFI+ Data.Number.Flint.Fq.Zech.Vec.FFI+ Data.Number.Flint.Fq.Zech.Mat.FFI+ Data.Number.Flint.Padic.FFI+ Data.Number.Flint.Padic.Poly.FFI+ Data.Number.Flint.Padic.Mat.FFI+ Data.Number.Flint.Qadic.FFI+ Data.Number.Flint.Support.ULong.Extras.FFI+ Data.Number.Flint.Support.D.Extras.FFI+ Data.Number.Flint.Support.D.Interval.FFI+ Data.Number.Flint.Support.D.Mat.FFI+ Data.Number.Flint.Support.D.Vec.FFI+ Data.Number.Flint.Support.Mpf.Mat.FFI+ Data.Number.Flint.Support.Mpf.Vec.FFI+ Data.Number.Flint.Support.Mpfr.Mat.FFI+ Data.Number.Flint.Support.Mpfr.Vec.FFI+ Data.Number.Flint.ThreadPool.FFI+ Data.Number.Flint.Arb.Types.FFI+ Data.Number.Flint.Arb.FFI+ Data.Number.Flint.Arb.Mag.FFI+ Data.Number.Flint.Arb.Arf.FFI+ Data.Number.Flint.Arb.Poly.FFI+ Data.Number.Flint.Arb.Fmpz.Poly.FFI+ Data.Number.Flint.Arb.Mat.FFI+ Data.Number.Flint.Arb.Hypgeom.FFI+ Data.Number.Flint.Arb.Calc.FFI+ Data.Number.Flint.Arb.FpWrap.FFI+ Data.Number.Flint.Acb.Types.FFI+ Data.Number.Flint.Acb.FFI+ Data.Number.Flint.Acb.Acf.FFI+ Data.Number.Flint.Acb.Poly.FFI+ Data.Number.Flint.Acb.Mat.FFI+ Data.Number.Flint.Acb.Hypgeom.FFI+ Data.Number.Flint.Acb.Elliptic.FFI+ Data.Number.Flint.Acb.Modular.FFI+ Data.Number.Flint.Acb.Dirichlet.FFI+ Data.Number.Flint.Acb.DFT.FFI+ Data.Number.Flint.Acb.Calc.FFI+ Data.Number.Flint.Bernoulli.FFI+ Data.Number.Flint.Partitions.FFI+ Data.Number.Flint.Hypgeom.FFI+ Data.Number.Flint.NF.FFI+ Data.Number.Flint.NF.Elem.FFI+ Data.Number.Flint.NF.Fmpzi.FFI+ Data.Number.Flint.NF.QQbar.FFI+ hs-source-dirs:+ src+ default-extensions:+ CApiFFI+ ForeignFunctionInterface+ FlexibleInstances+ TupleSections+ RankNTypes+ ScopedTypeVariables+ GADTs+ DataKinds+ TypeFamilies+ TypeOperators+ TypeSynonymInstances+ TypeFamilies+ KindSignatures+ MultiParamTypeClasses+ FunctionalDependencies+ include-dirs:+ csrc+ c-sources:+ csrc/fmpz/init.c+ csrc/fmpz/clear.c+ csrc/fmpz_factor/init.c+ csrc/fmpz_factor/clear.c+ csrc/fmpz_factor/fprint.c+ csrc/fmpz_poly_mat/fprint.c+ csrc/fmpz_poly_mat/get_str.c+ csrc/fmpz_factor/get_str.c+ csrc/fmpz_mpoly_q/fprint.c+ csrc/fmpz_mpoly_q/get_str_pretty.c+ csrc/fmpz_vec/get_str.c+ csrc/fmpz_mat/get_str.c+ csrc/fmpz_mat/get_str_pretty.c+ csrc/fmpz_mod_poly_factor/fprint.c+ csrc/fmpz_mod_poly_factor/fprint_pretty.c+ csrc/fmpz_mod_poly_factor/get_str.c+ csrc/fmpz_mod_poly_factor/get_str_pretty.c+ csrc/fmpq/mediant.c+ csrc/fmpq/get_fmpz_frac.c+ csrc/fmpq/cfrac_st.c+ csrc/fmpq_mat/get_str.c+ csrc/fmpq_mat/fprint.c+ csrc/fmpq_vec/get_str.c+ csrc/fmpq_poly/io_as_series.c+ csrc/fmpq_poly/monien.c+ csrc/nmod_poly_factor/get_str.c+ csrc/nmod_poly_factor/get_str_pretty.c+ csrc/nmod_poly_factor/fprint.c+ csrc/nmod_poly_factor/fprint_pretty.c+ csrc/nmod_poly_mat/fprint.c+ csrc/nmod_poly_mat/get_str.c+ csrc/aprcl/fprint.c+ csrc/aprcl/get_str.c+ csrc/bool_mat/get_str.c+ csrc/qfb/get_str.c+ csrc/qfb/fprint.c+ csrc/qqbar/fprint.c+ csrc/qqbar/fprintn.c+ csrc/qqbar/get_str.c+ csrc/qqbar/get_strn.c+ csrc/dlog/inlines.c+ csrc/fmpzi/fprint.c+ csrc/fmpzi/get_str.c+ csrc/fq/ctx_get_str.c+ csrc/fq_mat/get_str.c+ csrc/fq_mat/get_str_pretty.c+ csrc/fq_nmod/ctx_get_str.c+ csrc/fq_nmod_mat/get_str.c+ csrc/fq_nmod_mat/get_str_pretty.c+ csrc/fq_zech/ctx_get_str.c+ csrc/fq_zech_mat/get_str.c+ csrc/fq_zech_mat/get_str_pretty.c+ csrc/padic_poly/get_str.c+ csrc/padic_poly/get_str_pretty.c+ csrc/padic_mat/get_str.c+ csrc/padic_mat/get_str_pretty.c+ csrc/qadic/get_str_pretty.c+ csrc/double_interval/fprint.c+ csrc/double_interval/get_str.c+ csrc/d_mat/entry.c+ csrc/d_mat/io.c+ csrc/arb/midref.c+ csrc/arf/inlines.c+ csrc/mag/get_str.c+ csrc/arb/get_strd.c+ csrc/arb/get_strn.c+ csrc/arb/get_str_.c+ csrc/arb_mat/get_strd.c+ csrc/arb_mat/get_strn.c+ csrc/arb_mat/fprintn.c+ csrc/arb_mat/entry.c+ csrc/arb_poly/get_strd.c+ csrc/arb_calc/get_strd.c+ csrc/arb_calc/inlines.c+ csrc/arb_fpwrap/fpwrap.c+ csrc/acb/get_str.c+ csrc/acb/get_strd.c+ csrc/acb/get_strn.c+ csrc/acb_poly/get_strd.c+ csrc/acb_mat/get_strd.c+ csrc/acb_mat/get_strn.c+ csrc/acb_mat/fprintn.c+ csrc/acb_mat/entry.c+ csrc/acb_modular/inlines.c+ csrc/acb_modular/get_str.c+ csrc/mpfr_mat/swap_entrywise.c+ csrc/psl2z/word_problem.c+ csrc/perm/order.c+ csrc/perm/print_pretty.c+ csrc/perm/power.c+ csrc/perm/mat.c+ extra-libraries:+ flint, gmp+ pkgconfig-depends:+ flint >= 2.9, gmp+ build-tools:+ hsc2hs+ build-depends:+ QuickCheck+ , base >=4.7 && <5+ , groups+ default-language: Haskell2010++test-suite Flint2-test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ other-modules:+ Paths_Flint2+ hs-source-dirs:+ test+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ Flint2+ , base >=4.7 && <5+ default-language: Haskell2010
+ LICENSE view
@@ -0,0 +1,502 @@+ GNU LESSER GENERAL PUBLIC LICENSE+ Version 2.1, February 1999++ Copyright (C) 1991, 1999 Free Software Foundation, Inc.+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++[This is the first released version of the Lesser GPL. It also counts+ as the successor of the GNU Library Public License, version 2, hence+ the version number 2.1.]++ Preamble++ The licenses for most software are designed to take away your+freedom to share and change it. By contrast, the GNU General Public+Licenses are intended to guarantee your freedom to share and change+free software--to make sure the software is free for all its users.++ This license, the Lesser General Public License, applies to some+specially designated software packages--typically libraries--of the+Free Software Foundation and other authors who decide to use it. You+can use it too, but we suggest you first think carefully about whether+this license or the ordinary General Public License is the better+strategy to use in any particular case, based on the explanations below.++ When we speak of free software, we are referring to freedom of use,+not price. Our General Public Licenses are designed to make sure that+you have the freedom to distribute copies of free software (and charge+for this service if you wish); that you receive source code or can get+it if you want it; that you can change the software and use pieces of+it in new free programs; and that you are informed that you can do+these things.++ To protect your rights, we need to make restrictions that forbid+distributors to deny you these rights or to ask you to surrender these+rights. These restrictions translate to certain responsibilities for+you if you distribute copies of the library or if you modify it.++ For example, if you distribute copies of the library, whether gratis+or for a fee, you must give the recipients all the rights that we gave+you. You must make sure that they, too, receive or can get the source+code. If you link other code with the library, you must provide+complete object files to the recipients, so that they can relink them+with the library after making changes to the library and recompiling+it. And you must show them these terms so they know their rights.++ We protect your rights with a two-step method: (1) we copyright the+library, and (2) we offer you this license, which gives you legal+permission to copy, distribute and/or modify the library.++ To protect each distributor, we want to make it very clear that+there is no warranty for the free library. Also, if the library is+modified by someone else and passed on, the recipients should know+that what they have is not the original version, so that the original+author's reputation will not be affected by problems that might be+introduced by others.++ Finally, software patents pose a constant threat to the existence of+any free program. We wish to make sure that a company cannot+effectively restrict the users of a free program by obtaining a+restrictive license from a patent holder. Therefore, we insist that+any patent license obtained for a version of the library must be+consistent with the full freedom of use specified in this license.++ Most GNU software, including some libraries, is covered by the+ordinary GNU General Public License. This license, the GNU Lesser+General Public License, applies to certain designated libraries, and+is quite different from the ordinary General Public License. We use+this license for certain libraries in order to permit linking those+libraries into non-free programs.++ When a program is linked with a library, whether statically or using+a shared library, the combination of the two is legally speaking a+combined work, a derivative of the original library. The ordinary+General Public License therefore permits such linking only if the+entire combination fits its criteria of freedom. The Lesser General+Public License permits more lax criteria for linking other code with+the library.++ We call this license the "Lesser" General Public License because it+does Less to protect the user's freedom than the ordinary General+Public License. It also provides other free software developers Less+of an advantage over competing non-free programs. These disadvantages+are the reason we use the ordinary General Public License for many+libraries. However, the Lesser license provides advantages in certain+special circumstances.++ For example, on rare occasions, there may be a special need to+encourage the widest possible use of a certain library, so that it becomes+a de-facto standard. To achieve this, non-free programs must be+allowed to use the library. A more frequent case is that a free+library does the same job as widely used non-free libraries. In this+case, there is little to gain by limiting the free library to free+software only, so we use the Lesser General Public License.++ In other cases, permission to use a particular library in non-free+programs enables a greater number of people to use a large body of+free software. For example, permission to use the GNU C Library in+non-free programs enables many more people to use the whole GNU+operating system, as well as its variant, the GNU/Linux operating+system.++ Although the Lesser General Public License is Less protective of the+users' freedom, it does ensure that the user of a program that is+linked with the Library has the freedom and the wherewithal to run+that program using a modified version of the Library.++ The precise terms and conditions for copying, distribution and+modification follow. Pay close attention to the difference between a+"work based on the library" and a "work that uses the library". The+former contains code derived from the library, whereas the latter must+be combined with the library in order to run.++ GNU LESSER GENERAL PUBLIC LICENSE+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION++ 0. This License Agreement applies to any software library or other+program which contains a notice placed by the copyright holder or+other authorized party saying it may be distributed under the terms of+this Lesser General Public License (also called "this License").+Each licensee is addressed as "you".++ A "library" means a collection of software functions and/or data+prepared so as to be conveniently linked with application programs+(which use some of those functions and data) to form executables.++ The "Library", below, refers to any such software library or work+which has been distributed under these terms. A "work based on the+Library" means either the Library or any derivative work under+copyright law: that is to say, a work containing the Library or a+portion of it, either verbatim or with modifications and/or translated+straightforwardly into another language. (Hereinafter, translation is+included without limitation in the term "modification".)++ "Source code" for a work means the preferred form of the work for+making modifications to it. For a library, complete source code means+all the source code for all modules it contains, plus any associated+interface definition files, plus the scripts used to control compilation+and installation of the library.++ Activities other than copying, distribution and modification are not+covered by this License; they are outside its scope. The act of+running a program using the Library is not restricted, and output from+such a program is covered only if its contents constitute a work based+on the Library (independent of the use of the Library in a tool for+writing it). Whether that is true depends on what the Library does+and what the program that uses the Library does.++ 1. You may copy and distribute verbatim copies of the Library's+complete source code as you receive it, in any medium, provided that+you conspicuously and appropriately publish on each copy an+appropriate copyright notice and disclaimer of warranty; keep intact+all the notices that refer to this License and to the absence of any+warranty; and distribute a copy of this License along with the+Library.++ You may charge a fee for the physical act of transferring a copy,+and you may at your option offer warranty protection in exchange for a+fee.++ 2. You may modify your copy or copies of the Library or any portion+of it, thus forming a work based on the Library, and copy and+distribute such modifications or work under the terms of Section 1+above, provided that you also meet all of these conditions:++ a) The modified work must itself be a software library.++ b) You must cause the files modified to carry prominent notices+ stating that you changed the files and the date of any change.++ c) You must cause the whole of the work to be licensed at no+ charge to all third parties under the terms of this License.++ d) If a facility in the modified Library refers to a function or a+ table of data to be supplied by an application program that uses+ the facility, other than as an argument passed when the facility+ is invoked, then you must make a good faith effort to ensure that,+ in the event an application does not supply such function or+ table, the facility still operates, and performs whatever part of+ its purpose remains meaningful.++ (For example, a function in a library to compute square roots has+ a purpose that is entirely well-defined independent of the+ application. Therefore, Subsection 2d requires that any+ application-supplied function or table used by this function must+ be optional: if the application does not supply it, the square+ root function must still compute square roots.)++These requirements apply to the modified work as a whole. If+identifiable sections of that work are not derived from the Library,+and can be reasonably considered independent and separate works in+themselves, then this License, and its terms, do not apply to those+sections when you distribute them as separate works. But when you+distribute the same sections as part of a whole which is a work based+on the Library, the distribution of the whole must be on the terms of+this License, whose permissions for other licensees extend to the+entire whole, and thus to each and every part regardless of who wrote+it.++Thus, it is not the intent of this section to claim rights or contest+your rights to work written entirely by you; rather, the intent is to+exercise the right to control the distribution of derivative or+collective works based on the Library.++In addition, mere aggregation of another work not based on the Library+with the Library (or with a work based on the Library) on a volume of+a storage or distribution medium does not bring the other work under+the scope of this License.++ 3. You may opt to apply the terms of the ordinary GNU General Public+License instead of this License to a given copy of the Library. To do+this, you must alter all the notices that refer to this License, so+that they refer to the ordinary GNU General Public License, version 2,+instead of to this License. (If a newer version than version 2 of the+ordinary GNU General Public License has appeared, then you can specify+that version instead if you wish.) Do not make any other change in+these notices.++ Once this change is made in a given copy, it is irreversible for+that copy, so the ordinary GNU General Public License applies to all+subsequent copies and derivative works made from that copy.++ This option is useful when you wish to copy part of the code of+the Library into a program that is not a library.++ 4. You may copy and distribute the Library (or a portion or+derivative of it, under Section 2) in object code or executable form+under the terms of Sections 1 and 2 above provided that you accompany+it with the complete corresponding machine-readable source code, which+must be distributed under the terms of Sections 1 and 2 above on a+medium customarily used for software interchange.++ If distribution of object code is made by offering access to copy+from a designated place, then offering equivalent access to copy the+source code from the same place satisfies the requirement to+distribute the source code, even though third parties are not+compelled to copy the source along with the object code.++ 5. A program that contains no derivative of any portion of the+Library, but is designed to work with the Library by being compiled or+linked with it, is called a "work that uses the Library". Such a+work, in isolation, is not a derivative work of the Library, and+therefore falls outside the scope of this License.++ However, linking a "work that uses the Library" with the Library+creates an executable that is a derivative of the Library (because it+contains portions of the Library), rather than a "work that uses the+library". The executable is therefore covered by this License.+Section 6 states terms for distribution of such executables.++ When a "work that uses the Library" uses material from a header file+that is part of the Library, the object code for the work may be a+derivative work of the Library even though the source code is not.+Whether this is true is especially significant if the work can be+linked without the Library, or if the work is itself a library. The+threshold for this to be true is not precisely defined by law.++ If such an object file uses only numerical parameters, data+structure layouts and accessors, and small macros and small inline+functions (ten lines or less in length), then the use of the object+file is unrestricted, regardless of whether it is legally a derivative+work. (Executables containing this object code plus portions of the+Library will still fall under Section 6.)++ Otherwise, if the work is a derivative of the Library, you may+distribute the object code for the work under the terms of Section 6.+Any executables containing that work also fall under Section 6,+whether or not they are linked directly with the Library itself.++ 6. As an exception to the Sections above, you may also combine or+link a "work that uses the Library" with the Library to produce a+work containing portions of the Library, and distribute that work+under terms of your choice, provided that the terms permit+modification of the work for the customer's own use and reverse+engineering for debugging such modifications.++ You must give prominent notice with each copy of the work that the+Library is used in it and that the Library and its use are covered by+this License. You must supply a copy of this License. If the work+during execution displays copyright notices, you must include the+copyright notice for the Library among them, as well as a reference+directing the user to the copy of this License. Also, you must do one+of these things:++ a) Accompany the work with the complete corresponding+ machine-readable source code for the Library including whatever+ changes were used in the work (which must be distributed under+ Sections 1 and 2 above); and, if the work is an executable linked+ with the Library, with the complete machine-readable "work that+ uses the Library", as object code and/or source code, so that the+ user can modify the Library and then relink to produce a modified+ executable containing the modified Library. (It is understood+ that the user who changes the contents of definitions files in the+ Library will not necessarily be able to recompile the application+ to use the modified definitions.)++ b) Use a suitable shared library mechanism for linking with the+ Library. A suitable mechanism is one that (1) uses at run time a+ copy of the library already present on the user's computer system,+ rather than copying library functions into the executable, and (2)+ will operate properly with a modified version of the library, if+ the user installs one, as long as the modified version is+ interface-compatible with the version that the work was made with.++ c) Accompany the work with a written offer, valid for at+ least three years, to give the same user the materials+ specified in Subsection 6a, above, for a charge no more+ than the cost of performing this distribution.++ d) If distribution of the work is made by offering access to copy+ from a designated place, offer equivalent access to copy the above+ specified materials from the same place.++ e) Verify that the user has already received a copy of these+ materials or that you have already sent this user a copy.++ For an executable, the required form of the "work that uses the+Library" must include any data and utility programs needed for+reproducing the executable from it. However, as a special exception,+the materials to be distributed need not include anything that is+normally distributed (in either source or binary form) with the major+components (compiler, kernel, and so on) of the operating system on+which the executable runs, unless that component itself accompanies+the executable.++ It may happen that this requirement contradicts the license+restrictions of other proprietary libraries that do not normally+accompany the operating system. Such a contradiction means you cannot+use both them and the Library together in an executable that you+distribute.++ 7. You may place library facilities that are a work based on the+Library side-by-side in a single library together with other library+facilities not covered by this License, and distribute such a combined+library, provided that the separate distribution of the work based on+the Library and of the other library facilities is otherwise+permitted, and provided that you do these two things:++ a) Accompany the combined library with a copy of the same work+ based on the Library, uncombined with any other library+ facilities. This must be distributed under the terms of the+ Sections above.++ b) Give prominent notice with the combined library of the fact+ that part of it is a work based on the Library, and explaining+ where to find the accompanying uncombined form of the same work.++ 8. You may not copy, modify, sublicense, link with, or distribute+the Library except as expressly provided under this License. Any+attempt otherwise to copy, modify, sublicense, link with, or+distribute the Library is void, and will automatically terminate your+rights under this License. However, parties who have received copies,+or rights, from you under this License will not have their licenses+terminated so long as such parties remain in full compliance.++ 9. You are not required to accept this License, since you have not+signed it. However, nothing else grants you permission to modify or+distribute the Library or its derivative works. These actions are+prohibited by law if you do not accept this License. Therefore, by+modifying or distributing the Library (or any work based on the+Library), you indicate your acceptance of this License to do so, and+all its terms and conditions for copying, distributing or modifying+the Library or works based on it.++ 10. Each time you redistribute the Library (or any work based on the+Library), the recipient automatically receives a license from the+original licensor to copy, distribute, link with or modify the Library+subject to these terms and conditions. You may not impose any further+restrictions on the recipients' exercise of the rights granted herein.+You are not responsible for enforcing compliance by third parties with+this License.++ 11. If, as a consequence of a court judgment or allegation of patent+infringement or for any other reason (not limited to patent issues),+conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License. If you cannot+distribute so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you+may not distribute the Library at all. For example, if a patent+license would not permit royalty-free redistribution of the Library by+all those who receive copies directly or indirectly through you, then+the only way you could satisfy both it and this License would be to+refrain entirely from distribution of the Library.++If any portion of this section is held invalid or unenforceable under any+particular circumstance, the balance of the section is intended to apply,+and the section as a whole is intended to apply in other circumstances.++It is not the purpose of this section to induce you to infringe any+patents or other property right claims or to contest validity of any+such claims; this section has the sole purpose of protecting the+integrity of the free software distribution system which is+implemented by public license practices. Many people have made+generous contributions to the wide range of software distributed+through that system in reliance on consistent application of that+system; it is up to the author/donor to decide if he or she is willing+to distribute software through any other system and a licensee cannot+impose that choice.++This section is intended to make thoroughly clear what is believed to+be a consequence of the rest of this License.++ 12. If the distribution and/or use of the Library is restricted in+certain countries either by patents or by copyrighted interfaces, the+original copyright holder who places the Library under this License may add+an explicit geographical distribution limitation excluding those countries,+so that distribution is permitted only in or among countries not thus+excluded. In such case, this License incorporates the limitation as if+written in the body of this License.++ 13. The Free Software Foundation may publish revised and/or new+versions of the Lesser General Public License from time to time.+Such new versions will be similar in spirit to the present version,+but may differ in detail to address new problems or concerns.++Each version is given a distinguishing version number. If the Library+specifies a version number of this License which applies to it and+"any later version", you have the option of following the terms and+conditions either of that version or of any later version published by+the Free Software Foundation. If the Library does not specify a+license version number, you may choose any version ever published by+the Free Software Foundation.++ 14. If you wish to incorporate parts of the Library into other free+programs whose distribution conditions are incompatible with these,+write to the author to ask for permission. For software which is+copyrighted by the Free Software Foundation, write to the Free+Software Foundation; we sometimes make exceptions for this. Our+decision will be guided by the two goals of preserving the free status+of all derivatives of our free software and of promoting the sharing+and reuse of software generally.++ NO WARRANTY++ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.++ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH+DAMAGES.++ END OF TERMS AND CONDITIONS++ How to Apply These Terms to Your New Libraries++ If you develop a new library, and you want it to be of the greatest+possible use to the public, we recommend making it free software that+everyone can redistribute and change. You can do so by permitting+redistribution under these terms (or, alternatively, under the terms of the+ordinary General Public License).++ To apply these terms, attach the following notices to the library. It is+safest to attach them to the start of each source file to most effectively+convey the exclusion of warranty; and each file should have at least the+"copyright" line and a pointer to where the full notice is found.++ <one line to give the library's name and a brief idea of what it does.>+ Copyright (C) <year> <name of author>++ This library is free software; you can redistribute it and/or+ modify it under the terms of the GNU Lesser General Public+ License as published by the Free Software Foundation; either+ version 2.1 of the License, or (at your option) any later version.++ This library is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU+ Lesser General Public License for more details.++ You should have received a copy of the GNU Lesser General Public+ License along with this library; if not, write to the Free Software+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA++Also add information on how to contact you by electronic and paper mail.++You should also get your employer (if you work as a programmer) or your+school, if any, to sign a "copyright disclaimer" for the library, if+necessary. Here is a sample; alter the names:++ Yoyodyne, Inc., hereby disclaims all copyright interest in the+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.++ <signature of Ty Coon>, 1 April 1990+ Ty Coon, President of Vice++That's all there is to it!
+ README.md view
@@ -0,0 +1,75 @@+# Flint2+**Flint2** provides a thin Haskell wrapper for [Flint](https://flintlib.org) C-library. ++## Installation++Clone it with++```bash+git clone https://github.com/monien/Flint2.git+```++then goto to the Flint2 directory and use++```bash+stack install+stack haddock+```++Have a look at the **Main.hs** in the **app** directory first and then use+As long as Flint2 is not available from Stackage (Hackage) this requires specification of+the location of Flint2 in the global stack.yaml file which might be either a local directory+or github commit. See the [stack](https://docs.haskellstack.org/en/stable/GUIDE/) documentation for details.++```bash+stack install Flint2+stack haddock Flint2+```++This will install a binary **flint_test** in **~/.local/bin** which is just shows the basic functionality of the current Flint2 wrapper.++```bash+stack ghci+```+for Flint2 in a haskell shell. ++## Quick Start++A simple program using the thin wrapper would be++```haskell+import Data.Number.Flint++main = do + x <- newFmpz+ y <- newFmpz+ withFmpz x $ \x -> do+ withFmpz y $ \y -> do+ fmpz_set_ui x 7+ fmpz_set_ui y 6+ fmpz_mul x x y+ fmpz_print x +```++which will print the numerical value 42.++In the app directory more practical information on how to use the thin wrapper can be found. +The above example simplifies to ++```haskell+include Fmpz++main = do+ let x = 7 :: Fmpz + y = 6 :: Fmpz+ print $ x*y+ print $ factor (42 :: Fmpz)+ +```++which prints ++```+42 +[(2,1),(3,1),(7,1)]+```
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ csrc/acb/get_str.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/arb.h>++#include "../acb.h"++char*+acb_get_str(const acb_t x)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ acb_fprint(out, x);++ fclose(out);++ return buffer;+}
+ csrc/acb/get_strd.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/arb.h>++#include "../acb.h"++char*+acb_get_strd(const acb_t x, slong digits)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ acb_fprintd(out, x, digits);++ fclose(out);++ return buffer;+}
+ csrc/acb/get_strn.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/arb.h>++#include "../acb.h"++char*+acb_get_strn(const acb_t x, slong digits, ulong flags)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ acb_fprintn(out, x, digits, flags);++ fclose(out);++ return buffer;+}
+ csrc/acb_mat/entry.c view
@@ -0,0 +1,5 @@+#include <flint/acb_mat.h>++acb_ptr acb_mat_entry_(acb_mat_t mat, slong i, slong j) {+ return mat->rows[i] + j;+}
+ csrc/acb_mat/fprintn.c view
@@ -0,0 +1,21 @@+#include <flint/acb.h>+#include <flint/acb_mat.h>++#include "../acb_mat.h"++void+acb_mat_fprintn(FILE * file, const acb_mat_t mat, slong digits, ulong options) {+ slong i, j;+ + for (i = 0; i < acb_mat_nrows(mat); i++) {+ flint_fprintf(file, "[");+ + for (j = 0; j < acb_mat_ncols(mat); j++) {+ acb_fprintn(file, acb_mat_entry(mat, i, j), digits, options);+ + if (j < acb_mat_ncols(mat) - 1) flint_fprintf(file, ", ");+ }+ + flint_fprintf(file, "]\n");+ }+}
+ csrc/acb_mat/get_strd.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/acb.h>+#include <flint/acb_mat.h>++#include "../acb_mat.h"++char*+acb_mat_get_strd(const acb_mat_t mat, slong digits)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ acb_mat_fprintd(out, mat, digits);++ fclose(out);++ return buffer;+}
+ csrc/acb_mat/get_strn.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/acb.h>+#include <flint/acb_mat.h>++#include "../acb_mat.h"++char*+acb_mat_get_strn(const acb_mat_t mat, slong digits, ulong options)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ acb_mat_fprintn(out, mat, digits, options);++ fclose(out);++ return buffer;+}
+ csrc/acb_modular/get_str.c view
@@ -0,0 +1,16 @@+#include <stdio.h>+#include <flint/acb_modular.h>++char * psl2z_get_str(const psl2z_t x)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ psl2z_fprint(out, x);++ fclose(out);++ return buffer;+}
+ csrc/acb_modular/inlines.c view
@@ -0,0 +1,81 @@+/*+ Copyright (C) 2014 Fredrik Johansson++ This file is part of Arb.++ Arb is free software: you can redistribute it and/or modify it under+ the terms of the GNU Lesser General Public License (LGPL) as published+ by the Free Software Foundation; either version 2.1 of the License, or+ (at your option) any later version. See <http://www.gnu.org/licenses/>.+*/++#include <flint/fmpz.h>+#include <flint/acb_types.h>+#+#include <flint/acb_modular.h>++void+psl2z_init_(psl2z_t g)+{+ fmpz_init(&g->a);+ fmpz_init(&g->b);+ fmpz_init(&g->c);+ fmpz_init(&g->d);+ fmpz_one(&g->a);+ fmpz_one(&g->d);+}++void+psl2z_clear_(psl2z_t g)+{+ fmpz_clear(&g->a);+ fmpz_clear(&g->b);+ fmpz_clear(&g->c);+ fmpz_clear(&g->d);+}++void+psl2z_swap_(psl2z_t f, psl2z_t g)+{+ psl2z_struct h = *f;+ *f = *g;+ *g = h;+}++void+psl2z_set_(psl2z_t h, const psl2z_t g)+{+ fmpz_set(&h->a, &g->a);+ fmpz_set(&h->b, &g->b);+ fmpz_set(&h->c, &g->c);+ fmpz_set(&h->d, &g->d);+}++void+psl2z_one_(psl2z_t g)+{+ fmpz_one(&g->a);+ fmpz_zero(&g->b);+ fmpz_zero(&g->c);+ fmpz_one(&g->d);+}++int+psl2z_equal_(const psl2z_t f, const psl2z_t g)+{+ return fmpz_equal(&f->a, &g->a)+ && fmpz_equal(&f->b, &g->b)+ && fmpz_equal(&f->c, &g->c)+ && fmpz_equal(&f->d, &g->d);+}++int+psl2z_is_one_(const psl2z_t f)+{+ return+ fmpz_is_one(&f->a)+ && fmpz_is_zero(&f->b)+ && fmpz_is_zero(&f->c)+ && fmpz_is_one(&f->d);+}+
+ csrc/acb_poly/get_strd.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/acb_poly.h>++#include "../acb_poly.h"++char*+acb_poly_get_strd(const acb_poly_t x, slong digits)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ acb_poly_fprintd(out, x, digits);++ fclose(out);++ return buffer;+}
+ csrc/aprcl/fprint.c view
@@ -0,0 +1,12 @@+#include <flint/fmpz_mod_poly.h>+#include <flint/aprcl.h>++#include "../aprcl.h"++void+unity_zp_fprint(FILE * file, const unity_zp f)+{+ flint_fprintf(file, "p = %wu; exp = %wu\n", f->p, f->exp);+ fmpz_mod_poly_fprint(file, f->poly, f->ctx);+ flint_fprintf(file, "\n");+}
+ csrc/aprcl/get_str.c view
@@ -0,0 +1,19 @@+#include <flint/fmpz_mod_poly.h>+#include <flint/aprcl.h>++#include "../aprcl.h"++char*+unity_zp_get_str(const unity_zp z)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ unity_zp_fprint(out, z);++ fclose(out);++ return buffer;+}
+ csrc/arb/get_str_.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/arb.h>++#include "../arb.h"++char*+arb_get_str_(const arb_t x)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ arb_fprint(out, x);++ fclose(out);++ return buffer;+}
+ csrc/arb/get_strd.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/arb.h>++#include "../arb.h"++char*+arb_get_strd(const arb_t x, slong digits)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ arb_fprintd(out, x, digits);++ fclose(out);++ return buffer;+}
+ csrc/arb/get_strn.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/arb.h>++#include "../arb.h"++char*+arb_get_strn(const arb_t x, slong digits, ulong options)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ arb_fprintn(out, x, digits, options);++ fclose(out);++ return buffer;+}
+ csrc/arb/midref.c view
@@ -0,0 +1,12 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/arb.h>++#include "../arb.h"++arf_struct * arb_midref_(arb_t x) {+ return &(x->mid);+}
+ csrc/arb_calc/get_strd.c view
@@ -0,0 +1,22 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/arb_calc.h>++#include "../arb_calc.h"++char * arf_interval_get_strd(const arf_interval_t u, const slong digits)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ arf_interval_fprintd(out, u, digits);++ fclose(out);++ return buffer;+}
+ csrc/arb_calc/inlines.c view
@@ -0,0 +1,59 @@+#include <flint/arb_calc.h>++#include "../arb_calc.h"++void+arf_interval_init_(arf_interval_t v)+{+ arf_init(&v->a);+ arf_init(&v->b);+}++void+arf_interval_clear_(arf_interval_t v)+{+ arf_clear(&v->a);+ arf_clear(&v->b);+}++arf_interval_ptr+_arf_interval_vec_init_(slong n)+{+ slong i;+ arf_interval_ptr v =+ (arf_interval_ptr) flint_malloc(sizeof(arf_interval_struct) * n);++ for (i = 0; i < n; i++)+ arf_interval_init(v + i);++ return v;+}++void+_arf_interval_vec_clear_(arf_interval_ptr v, slong n)+{+ slong i;+ for (i = 0; i < n; i++)+ arf_interval_clear(v + i);+ flint_free(v);+}++void+arf_interval_set_(arf_interval_t v, const arf_interval_t u)+{+ arf_set(&v->a, &u->a);+ arf_set(&v->b, &u->b);+}++void+arf_interval_swap_(arf_interval_t v, arf_interval_t u)+{+ arf_swap(&v->a, &u->a);+ arf_swap(&v->b, &u->b);+}++void+arf_interval_get_arb_(arb_t x, const arf_interval_t v, slong prec)+{+ arb_set_interval_arf(x, &v->a, &v->b, prec);+}
+ csrc/arb_fpwrap/fpwrap.c view
@@ -0,0 +1,798 @@+#include <flint/arb_fpwrap.h>++// Haskell does not allow call by value for structure+//+// changed argument: complex_double -> complex_value *++int arb_fpwrap_double_exp_(double * res, double x, int flags) {+ return arb_fpwrap_double_exp(res, x, flags);+};++int arb_fpwrap_cdouble_exp_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_exp(res, *x, flags);+};++int arb_fpwrap_double_expm1_(double * res, double x, int flags) {+ return arb_fpwrap_double_expm1(res, x, flags);+};++int arb_fpwrap_cdouble_expm1_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_expm1(res, *x, flags);+};++int arb_fpwrap_double_log_(double * res, double x, int flags) {+ return arb_fpwrap_double_log(res, x, flags);+};++int arb_fpwrap_cdouble_log_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_log(res, *x, flags);+};++int arb_fpwrap_double_log1p_(double * res, double x, int flags) {+ return arb_fpwrap_double_log1p(res, x, flags);+};++int arb_fpwrap_cdouble_log1p_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_log1p(res, *x, flags);+};++int arb_fpwrap_double_pow_(double * res, double x, double y, int flags) {+ return arb_fpwrap_double_pow(res, x, y, flags);+};++int arb_fpwrap_cdouble_pow_(complex_double * res, complex_double * x, complex_double * y, int flags) {+ return arb_fpwrap_cdouble_pow(res, *x, *y, flags);+};++int arb_fpwrap_double_sqrt_(double * res, double x, int flags) {+ return arb_fpwrap_double_sqrt(res, x, flags);+};++int arb_fpwrap_cdouble_sqrt_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_sqrt(res, *x, flags);+};++int arb_fpwrap_double_rsqrt_(double * res, double x, int flags) {+ return arb_fpwrap_double_rsqrt(res, x, flags);+};++int arb_fpwrap_cdouble_rsqrt_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_rsqrt(res, *x, flags);+};++int arb_fpwrap_double_cbrt_(double * res, double x, int flags) {+ return arb_fpwrap_double_cbrt(res, x, flags);+};++int arb_fpwrap_cdouble_cbrt_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_cbrt(res, *x, flags);+};++int arb_fpwrap_double_sin_(double * res, double x, int flags) {+ return arb_fpwrap_double_sin(res, x, flags);+};++int arb_fpwrap_cdouble_sin_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_sin(res, *x, flags);+};++int arb_fpwrap_double_cos_(double * res, double x, int flags) {+ return arb_fpwrap_double_cos(res, x, flags);+};++int arb_fpwrap_cdouble_cos_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_cos(res, *x, flags);+};++int arb_fpwrap_double_tan_(double * res, double x, int flags) {+ return arb_fpwrap_double_tan(res, x, flags);+};++int arb_fpwrap_cdouble_tan_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_tan(res, *x, flags);+};++int arb_fpwrap_double_cot_(double * res, double x, int flags) {+ return arb_fpwrap_double_cot(res, x, flags);+};++int arb_fpwrap_cdouble_cot_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_cot(res, *x, flags);+};++int arb_fpwrap_double_sec_(double * res, double x, int flags) {+ return arb_fpwrap_double_sec(res, x, flags);+};++int arb_fpwrap_cdouble_sec_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_sec(res, *x, flags);+};++int arb_fpwrap_double_csc_(double * res, double x, int flags) {+ return arb_fpwrap_double_csc(res, x, flags);+};++int arb_fpwrap_cdouble_csc_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_csc(res, *x, flags);+};++int arb_fpwrap_double_sinc_(double * res, double x, int flags) {+ return arb_fpwrap_double_sinc(res, x, flags);+};++int arb_fpwrap_cdouble_sinc_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_sinc(res, *x, flags);+};++int arb_fpwrap_double_sin_pi_(double * res, double x, int flags) {+ return arb_fpwrap_double_sin_pi(res, x, flags);+};++int arb_fpwrap_cdouble_sin_pi_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_sin_pi(res, *x, flags);+};++int arb_fpwrap_double_cos_pi_(double * res, double x, int flags) {+ return arb_fpwrap_double_cos_pi(res, x, flags);+};++int arb_fpwrap_cdouble_cos_pi_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_cos_pi(res, *x, flags);+};++int arb_fpwrap_double_tan_pi_(double * res, double x, int flags) {+ return arb_fpwrap_double_tan_pi(res, x, flags);+};++int arb_fpwrap_cdouble_tan_pi_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_tan_pi(res, *x, flags);+};++int arb_fpwrap_double_cot_pi_(double * res, double x, int flags) {+ return arb_fpwrap_double_cot_pi(res, x, flags);+};++int arb_fpwrap_cdouble_cot_pi_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_cot_pi(res, *x, flags);+};++int arb_fpwrap_double_sinc_pi_(double * res, double x, int flags) {+ return arb_fpwrap_double_sinc_pi(res, x, flags);+};++int arb_fpwrap_cdouble_sinc_pi_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_sinc_pi(res, *x, flags);+};++int arb_fpwrap_double_asin_(double * res, double x, int flags) {+ return arb_fpwrap_double_asin(res, x, flags);+};++int arb_fpwrap_cdouble_asin_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_asin(res, *x, flags);+};++int arb_fpwrap_double_acos_(double * res, double x, int flags) {+ return arb_fpwrap_double_acos(res, x, flags);+};++int arb_fpwrap_cdouble_acos_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_acos(res, *x, flags);+};++int arb_fpwrap_double_atan_(double * res, double x, int flags) {+ return arb_fpwrap_double_atan(res, x, flags);+};++int arb_fpwrap_cdouble_atan_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_atan(res, *x, flags);+};++int arb_fpwrap_double_atan2_(double * res, double x1, double x2, int flags) {+ return arb_fpwrap_double_atan2(res, x1, x2, flags);+};++int arb_fpwrap_double_asinh_(double * res, double x, int flags) {+ return arb_fpwrap_double_asinh(res, x, flags);+};++int arb_fpwrap_cdouble_asinh_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_asinh(res, *x, flags);+};++int arb_fpwrap_double_acosh_(double * res, double x, int flags) {+ return arb_fpwrap_double_acosh(res, x, flags);+};++int arb_fpwrap_cdouble_acosh_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_acosh(res, *x, flags);+};++int arb_fpwrap_double_atanh_(double * res, double x, int flags) {+ return arb_fpwrap_double_atanh(res, x, flags);+};++int arb_fpwrap_cdouble_atanh_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_atanh(res, *x, flags);+};++int arb_fpwrap_double_lambertw_(double * res, double x, slong branch, int flags) {+ return arb_fpwrap_double_lambertw(res, x, branch, flags);+};++int arb_fpwrap_cdouble_lambertw_(complex_double * res, complex_double * x, slong branch, int flags) {+ return arb_fpwrap_cdouble_lambertw(res, *x, branch, flags);+};++int arb_fpwrap_double_rising_(double * res, double x, double n, int flags) {+ return arb_fpwrap_double_rising(res, x, n, flags);+};++int arb_fpwrap_cdouble_rising_(complex_double * res, complex_double * x, complex_double * n, int flags) {+ return arb_fpwrap_cdouble_rising(res, *x, *n, flags);+};++int arb_fpwrap_double_gamma_(double * res, double x, int flags) {+ return arb_fpwrap_double_gamma(res, x, flags);+};++int arb_fpwrap_cdouble_gamma_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_gamma(res, *x, flags);+};++int arb_fpwrap_double_rgamma_(double * res, double x, int flags) {+ return arb_fpwrap_double_rgamma(res, x, flags);+};++int arb_fpwrap_cdouble_rgamma_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_rgamma(res, *x, flags);+};++int arb_fpwrap_double_lgamma_(double * res, double x, int flags) {+ return arb_fpwrap_double_lgamma(res, x, flags);+};++int arb_fpwrap_cdouble_lgamma_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_lgamma(res, *x, flags);+};++int arb_fpwrap_double_digamma_(double * res, double x, int flags) {+ return arb_fpwrap_double_digamma(res, x, flags);+};++int arb_fpwrap_cdouble_digamma_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_digamma(res, *x, flags);+};++int arb_fpwrap_double_zeta_(double * res, double x, int flags) {+ return arb_fpwrap_double_zeta(res, x, flags);+};++int arb_fpwrap_cdouble_zeta_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_zeta(res, *x, flags);+};++int arb_fpwrap_double_hurwitz_zeta_(double * res, double s, double z, int flags) {+ return arb_fpwrap_double_hurwitz_zeta(res, s, z, flags);+};++int arb_fpwrap_cdouble_hurwitz_zeta_(complex_double * res, complex_double * s, complex_double * z, int flags) {+ return arb_fpwrap_cdouble_hurwitz_zeta(res, *s, *z, flags);+};++int arb_fpwrap_double_lerch_phi_(double * res, double z, double s, double a, int flags) {+ return arb_fpwrap_double_lerch_phi(res, z, s, a, flags);+};++int arb_fpwrap_cdouble_lerch_phi_(complex_double * res, complex_double * z, complex_double * s, complex_double * a, int flags) {+ return arb_fpwrap_cdouble_lerch_phi(res, *z, *s, *a, flags);+};++int arb_fpwrap_double_barnes_g_(double * res, double x, int flags) {+ return arb_fpwrap_double_barnes_g(res, x, flags);+};++int arb_fpwrap_cdouble_barnes_g_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_barnes_g(res, *x, flags);+};++int arb_fpwrap_double_log_barnes_g_(double * res, double x, int flags) {+ return arb_fpwrap_double_log_barnes_g(res, x, flags);+};++int arb_fpwrap_cdouble_log_barnes_g_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_log_barnes_g(res, *x, flags);+};++int arb_fpwrap_double_polygamma_(double * res, double s, double z, int flags) {+ return arb_fpwrap_double_polygamma(res, s, z, flags);+};++int arb_fpwrap_cdouble_polygamma_(complex_double * res, complex_double * s, complex_double * z, int flags) {+ return arb_fpwrap_cdouble_polygamma(res, *s, *z, flags);+};++int arb_fpwrap_double_polylog_(double * res, double s, double z, int flags) {+ return arb_fpwrap_double_polylog(res, s, z, flags);+};++int arb_fpwrap_cdouble_polylog_(complex_double * res, complex_double * s, complex_double * z, int flags) {+ return arb_fpwrap_cdouble_polylog(res, *s, *z, flags);+};++int arb_fpwrap_cdouble_dirichlet_eta_(complex_double * res, complex_double * s, int flags) {+ return arb_fpwrap_cdouble_dirichlet_eta(res, *s, flags);+};++int arb_fpwrap_cdouble_riemann_xi_(complex_double * res, complex_double * s, int flags) {+ return arb_fpwrap_cdouble_riemann_xi(res, *s, flags);+};++int arb_fpwrap_cdouble_hardy_theta_(complex_double * res, complex_double * z, int flags) {+ return arb_fpwrap_cdouble_hardy_theta(res, *z, flags);+};++int arb_fpwrap_cdouble_hardy_z_(complex_double * res, complex_double * z, int flags) {+ return arb_fpwrap_cdouble_hardy_z(res, *z, flags);+};++int arb_fpwrap_cdouble_zeta_zero_(complex_double * res, ulong n, int flags) {+ return arb_fpwrap_cdouble_zeta_zero(res, n, flags);+};++int arb_fpwrap_double_erf_(double * res, double x, int flags) {+ return arb_fpwrap_double_erf(res, x, flags);+};++int arb_fpwrap_cdouble_erf_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_erf(res, *x, flags);+};++int arb_fpwrap_double_erfc_(double * res, double x, int flags) {+ return arb_fpwrap_double_erfc(res, x, flags);+};++int arb_fpwrap_cdouble_erfc_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_erfc(res, *x, flags);+};++int arb_fpwrap_double_erfi_(double * res, double x, int flags) {+ return arb_fpwrap_double_erfi(res, x, flags);+};++int arb_fpwrap_cdouble_erfi_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_erfi(res, *x, flags);+};++int arb_fpwrap_double_erfinv_(double * res, double x, int flags) {+ return arb_fpwrap_double_erfinv(res, x, flags);+};++int arb_fpwrap_double_erfcinv_(double * res, double x, int flags) {+ return arb_fpwrap_double_erfcinv(res, x, flags);+};++int arb_fpwrap_double_fresnel_s_(double * res, double x, int normalized, int flags) {+ return arb_fpwrap_double_fresnel_s(res, x, normalized, flags);+};++int arb_fpwrap_cdouble_fresnel_s_(complex_double * res, complex_double * x, int normalized, int flags) {+ return arb_fpwrap_cdouble_fresnel_s(res, *x, normalized, flags);+};++int arb_fpwrap_double_fresnel_c_(double * res, double x, int normalized, int flags) {+ return arb_fpwrap_double_fresnel_c(res, x, normalized, flags);+};++int arb_fpwrap_cdouble_fresnel_c_(complex_double * res, complex_double * x, int normalized, int flags) {+ return arb_fpwrap_cdouble_fresnel_c(res, *x, normalized, flags);+};++int arb_fpwrap_double_gamma_upper_(double * res, double s, double z, int regularized, int flags) {+ return arb_fpwrap_double_gamma_upper(res, s, z, regularized, flags);+};++int arb_fpwrap_cdouble_gamma_upper_(complex_double * res, complex_double * s, complex_double * z, int regularized, int flags) {+ return arb_fpwrap_cdouble_gamma_upper(res, *s, *z, regularized, flags);+};++int arb_fpwrap_double_gamma_lower_(double * res, double s, double z, int regularized, int flags) {+ return arb_fpwrap_double_gamma_lower(res, s, z, regularized, flags);+};++int arb_fpwrap_cdouble_gamma_lower_(complex_double * res, complex_double * s, complex_double * z, int regularized, int flags) {+ return arb_fpwrap_cdouble_gamma_lower(res, *s, *z, regularized, flags);+};++int arb_fpwrap_double_beta_lower_(double * res, double a, double b, double z, int regularized, int flags) {+ return arb_fpwrap_double_beta_lower(res, a, b, z, regularized, flags);+};++int arb_fpwrap_cdouble_beta_lower_(complex_double * res, complex_double * a, complex_double * b, complex_double * z, int regularized, int flags) {+ return arb_fpwrap_cdouble_beta_lower(res, *a, *b, *z, regularized, flags);+};++int arb_fpwrap_double_exp_integral_e_(double * res, double s, double z, int flags) {+ return arb_fpwrap_double_exp_integral_e(res, s, z, flags);+};++int arb_fpwrap_cdouble_exp_integral_e_(complex_double * res, complex_double * s, complex_double * z, int flags) {+ return arb_fpwrap_cdouble_exp_integral_e(res, *s, *z, flags);+};++int arb_fpwrap_double_exp_integral_ei_(double * res, double x, int flags) {+ return arb_fpwrap_double_exp_integral_ei(res, x, flags);+};++int arb_fpwrap_cdouble_exp_integral_ei_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_exp_integral_ei(res, *x, flags);+};++int arb_fpwrap_double_sin_integral_(double * res, double x, int flags) {+ return arb_fpwrap_double_sin_integral(res, x, flags);+};++int arb_fpwrap_cdouble_sin_integral_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_sin_integral(res, *x, flags);+};++int arb_fpwrap_double_cos_integral_(double * res, double x, int flags) {+ return arb_fpwrap_double_cos_integral(res, x, flags);+};++int arb_fpwrap_cdouble_cos_integral_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_cos_integral(res, *x, flags);+};++int arb_fpwrap_double_sinh_integral_(double * res, double x, int flags) {+ return arb_fpwrap_double_sinh_integral(res, x, flags);+};++int arb_fpwrap_cdouble_sinh_integral_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_sinh_integral(res, *x, flags);+};++int arb_fpwrap_double_cosh_integral_(double * res, double x, int flags) {+ return arb_fpwrap_double_cosh_integral(res, x, flags);+};++int arb_fpwrap_cdouble_cosh_integral_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_cosh_integral(res, *x, flags);+};++int arb_fpwrap_double_log_integral_(double * res, double x, int offset, int flags) {+ return arb_fpwrap_double_log_integral(res, x, offset, flags);+};++int arb_fpwrap_cdouble_log_integral_(complex_double * res, complex_double * x, int offset, int flags) {+ return arb_fpwrap_cdouble_log_integral(res, *x, offset, flags);+};++int arb_fpwrap_double_dilog_(double * res, double x, int flags) {+ return arb_fpwrap_double_dilog(res, x, flags);+};++int arb_fpwrap_cdouble_dilog_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_dilog(res, *x, flags);+};++int arb_fpwrap_double_bessel_j_(double * res, double nu, double x, int flags) {+ return arb_fpwrap_double_bessel_j(res, nu, x, flags);+};++int arb_fpwrap_cdouble_bessel_j_(complex_double * res, complex_double * nu, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_bessel_j(res, *nu, *x, flags);+};++int arb_fpwrap_double_bessel_y_(double * res, double nu, double x, int flags) {+ return arb_fpwrap_double_bessel_y(res, nu, x, flags);+};++int arb_fpwrap_cdouble_bessel_y_(complex_double * res, complex_double * nu, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_bessel_y(res, *nu, *x, flags);+};++int arb_fpwrap_double_bessel_i_(double * res, double nu, double x, int flags) {+ return arb_fpwrap_double_bessel_i(res, nu, x, flags);+};++int arb_fpwrap_cdouble_bessel_i_(complex_double * res, complex_double * nu, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_bessel_i(res, *nu, *x, flags);+};++int arb_fpwrap_double_bessel_k_(double * res, double nu, double x, int flags) {+ return arb_fpwrap_double_bessel_k(res, nu, x, flags);+};++int arb_fpwrap_cdouble_bessel_k_(complex_double * res, complex_double * nu, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_bessel_k(res, *nu, *x, flags);+};++int arb_fpwrap_double_bessel_k_scaled_(double * res, double nu, double x, int flags) {+ return arb_fpwrap_double_bessel_k_scaled(res, nu, x, flags);+};++int arb_fpwrap_cdouble_bessel_k_scaled_(complex_double * res, complex_double * nu, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_bessel_k_scaled(res, *nu, *x, flags);+};++int arb_fpwrap_double_airy_ai_(double * res, double x, int flags) {+ return arb_fpwrap_double_airy_ai(res, x, flags);+};++int arb_fpwrap_cdouble_airy_ai_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_airy_ai(res, *x, flags);+};++int arb_fpwrap_double_airy_ai_prime_(double * res, double x, int flags) {+ return arb_fpwrap_double_airy_ai_prime(res, x, flags);+};++int arb_fpwrap_cdouble_airy_ai_prime_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_airy_ai_prime(res, *x, flags);+};++int arb_fpwrap_double_airy_bi_(double * res, double x, int flags) {+ return arb_fpwrap_double_airy_bi(res, x, flags);+};++int arb_fpwrap_cdouble_airy_bi_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_airy_bi(res, *x, flags);+};++int arb_fpwrap_double_airy_bi_prime_(double * res, double x, int flags) {+ return arb_fpwrap_double_airy_bi_prime(res, x, flags);+};++int arb_fpwrap_cdouble_airy_bi_prime_(complex_double * res, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_airy_bi_prime(res, *x, flags);+};++int arb_fpwrap_double_airy_ai_zero_(double * res, ulong n, int flags) {+ return arb_fpwrap_double_airy_ai_zero(res, n, flags);+};++int arb_fpwrap_double_airy_ai_prime_zero_(double * res, ulong n, int flags) {+ return arb_fpwrap_double_airy_ai_prime_zero(res, n, flags);+};++int arb_fpwrap_double_airy_bi_zero_(double * res, ulong n, int flags) {+ return arb_fpwrap_double_airy_bi_zero(res, n, flags);+};++int arb_fpwrap_double_airy_bi_prime_zero_(double * res, ulong n, int flags) {+ return arb_fpwrap_double_airy_bi_prime_zero(res, n, flags);+};++int arb_fpwrap_double_coulomb_f_(double * res, double l, double eta, double x, int flags) {+ return arb_fpwrap_double_coulomb_f(res, l, eta, x, flags);+};++int arb_fpwrap_cdouble_coulomb_f_(complex_double * res, complex_double * l, complex_double * eta, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_coulomb_f(res, *l, *eta, *x, flags);+};++int arb_fpwrap_double_coulomb_g_(double * res, double l, double eta, double x, int flags) {+ return arb_fpwrap_double_coulomb_g(res, l, eta, x, flags);+};++int arb_fpwrap_cdouble_coulomb_g_(complex_double * res, complex_double * l, complex_double * eta, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_coulomb_g(res, *l, *eta, *x, flags);+};++int arb_fpwrap_cdouble_coulomb_hpos_(complex_double * res, complex_double * l, complex_double * eta, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_coulomb_hpos(res, *l, *eta, *x, flags);+};++int arb_fpwrap_cdouble_coulomb_hneg_(complex_double * res, complex_double * l, complex_double * eta, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_coulomb_hneg(res, *l, *eta, *x, flags);+};++int arb_fpwrap_double_chebyshev_t_(double * res, double n, double x, int flags) {+ return arb_fpwrap_double_chebyshev_t(res, n, x, flags);+};++int arb_fpwrap_cdouble_chebyshev_t_(complex_double * res, complex_double * n, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_chebyshev_t(res, *n, *x, flags);+};++int arb_fpwrap_double_chebyshev_u_(double * res, double n, double x, int flags) {+ return arb_fpwrap_double_chebyshev_u(res, n, x, flags);+};++int arb_fpwrap_cdouble_chebyshev_u_(complex_double * res, complex_double * n, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_chebyshev_u(res, *n, *x, flags);+};++int arb_fpwrap_double_jacobi_p_(double * res, double n, double a, double b, double x, int flags) {+ return arb_fpwrap_double_jacobi_p(res, n, a, b, x, flags);+};++int arb_fpwrap_cdouble_jacobi_p_(complex_double * res, complex_double * n, complex_double * a, complex_double * b, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_jacobi_p(res, *n, *a, *b, *x, flags);+};++int arb_fpwrap_double_gegenbauer_c_(double * res, double n, double m, double x, int flags) {+ return arb_fpwrap_double_gegenbauer_c(res, n, m, x, flags);+};++int arb_fpwrap_cdouble_gegenbauer_c_(complex_double * res, complex_double * n, complex_double * m, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_gegenbauer_c(res, *n, *m, *x, flags);+};++int arb_fpwrap_double_laguerre_l_(double * res, double n, double m, double x, int flags) {+ return arb_fpwrap_double_laguerre_l(res, n, m, x, flags);+};++int arb_fpwrap_cdouble_laguerre_l_(complex_double * res, complex_double * n, complex_double * m, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_laguerre_l(res, *n, *m, *x, flags);+};++int arb_fpwrap_double_hermite_h_(double * res, double n, double x, int flags) {+ return arb_fpwrap_double_hermite_h(res, n, x, flags);+};++int arb_fpwrap_cdouble_hermite_h_(complex_double * res, complex_double * n, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_hermite_h(res, *n, *x, flags);+};++int arb_fpwrap_double_legendre_p_(double * res, double n, double m, double x, int type, int flags) {+ return arb_fpwrap_double_legendre_p(res, n, m, x, type, flags);+};++int arb_fpwrap_cdouble_legendre_p_(complex_double * res, complex_double * n, complex_double * m, complex_double * x, int type, int flags) {+ return arb_fpwrap_cdouble_legendre_p(res, *n, *m, *x, type, flags);+};++int arb_fpwrap_double_legendre_q_(double * res, double n, double m, double x, int type, int flags) {+ return arb_fpwrap_double_legendre_q(res, n, m, x, type, flags);+};++int arb_fpwrap_cdouble_legendre_q_(complex_double * res, complex_double * n, complex_double * m, complex_double * x, int type, int flags) {+ return arb_fpwrap_cdouble_legendre_q(res, *n, *m, *x, type, flags);+};++int arb_fpwrap_double_legendre_root_(double * res1, double * res2, ulong n, ulong k, int flags) {+ return arb_fpwrap_double_legendre_root(res1, res2, n, k, flags);+};++int arb_fpwrap_cdouble_spherical_y_(complex_double * res, slong n, slong m, complex_double * x1, complex_double * x2, int flags) {+ return arb_fpwrap_cdouble_spherical_y(res, n, m, *x1, *x2, flags);+};++int arb_fpwrap_double_hypgeom_0f1_(double * res, double a, double x, int regularized, int flags) {+ return arb_fpwrap_double_hypgeom_0f1(res, a, x, regularized, flags);+};++int arb_fpwrap_cdouble_hypgeom_0f1_(complex_double * res, complex_double * a, complex_double * x, int regularized, int flags) {+ return arb_fpwrap_cdouble_hypgeom_0f1(res, *a, *x, regularized, flags);+};++int arb_fpwrap_double_hypgeom_1f1_(double * res, double a, double b, double x, int regularized, int flags) {+ return arb_fpwrap_double_hypgeom_1f1(res, a, b, x, regularized, flags);+};++int arb_fpwrap_cdouble_hypgeom_1f1_(complex_double * res, complex_double * a, complex_double * b, complex_double * x, int regularized, int flags) {+ return arb_fpwrap_cdouble_hypgeom_1f1(res, *a, *b, *x, regularized, flags);+};++int arb_fpwrap_double_hypgeom_u_(double * res, double a, double b, double x, int flags) {+ return arb_fpwrap_double_hypgeom_u(res, a, b, x, flags);+};++int arb_fpwrap_cdouble_hypgeom_u_(complex_double * res, complex_double * a, complex_double * b, complex_double * x, int flags) {+ return arb_fpwrap_cdouble_hypgeom_u(res, *a, *b, *x, flags);+};++int arb_fpwrap_double_hypgeom_2f1_(double * res, double a, double b, double c, double x, int regularized, int flags) {+ return arb_fpwrap_double_hypgeom_2f1(res, a, b, c, x, regularized, flags);+};++int arb_fpwrap_cdouble_hypgeom_2f1_(complex_double * res, complex_double * a, complex_double * b, complex_double * c, complex_double * x, int regularized, int flags) {+ return arb_fpwrap_cdouble_hypgeom_2f1(res, *a, *b, *c, *x, regularized, flags);+};++int arb_fpwrap_double_hypgeom_pfq_(double * res, const double * a, slong p, const double * b, slong q, double z, int regularized, int flags) {+ return arb_fpwrap_double_hypgeom_pfq(res, a, p, b, q, z, regularized, flags);+};++int arb_fpwrap_cdouble_hypgeom_pfq_(complex_double * res, const complex_double * a, slong p, const complex_double * b, slong q, complex_double * z, int regularized, int flags) {+ return arb_fpwrap_cdouble_hypgeom_pfq(res, a, p, b, q, *z, regularized, flags);+};++int arb_fpwrap_double_agm_(double * res, double x, double y, int flags) {+ return arb_fpwrap_double_agm(res, x, y, flags);+};++int arb_fpwrap_cdouble_agm_(complex_double * res, complex_double * x, complex_double * y, int flags) {+ return arb_fpwrap_cdouble_agm(res, *x, *y, flags);+};++int arb_fpwrap_cdouble_elliptic_k_(complex_double * res, complex_double * m, int flags) {+ return arb_fpwrap_cdouble_elliptic_k(res, *m, flags);+};++int arb_fpwrap_cdouble_elliptic_e_(complex_double * res, complex_double * m, int flags) {+ return arb_fpwrap_cdouble_elliptic_e(res, *m, flags);+};++int arb_fpwrap_cdouble_elliptic_pi_(complex_double * res, complex_double * n, complex_double * m, int flags) {+ return arb_fpwrap_cdouble_elliptic_pi(res, *n, *m, flags);+};++int arb_fpwrap_cdouble_elliptic_f_(complex_double * res, complex_double * phi, complex_double * m, int pi, int flags) {+ return arb_fpwrap_cdouble_elliptic_f(res, *phi, *m, pi, flags);+};++int arb_fpwrap_cdouble_elliptic_e_inc_(complex_double * res, complex_double * phi, complex_double * m, int pi, int flags) {+ return arb_fpwrap_cdouble_elliptic_e_inc(res, *phi, *m, pi, flags);+};++int arb_fpwrap_cdouble_elliptic_pi_inc_(complex_double * res, complex_double * n, complex_double * phi, complex_double * m, int pi, int flags) {+ return arb_fpwrap_cdouble_elliptic_pi_inc(res, *n, *phi, *m, pi, flags);+};++int arb_fpwrap_cdouble_elliptic_rf_(complex_double * res, complex_double * x, complex_double * y, complex_double * z, int option, int flags) {+ return arb_fpwrap_cdouble_elliptic_rf(res, *x, *y, *z, option, flags);+};++int arb_fpwrap_cdouble_elliptic_rg_(complex_double * res, complex_double * x, complex_double * y, complex_double * z, int option, int flags) {+ return arb_fpwrap_cdouble_elliptic_rg(res, *x, *y, *z, option, flags);+};++int arb_fpwrap_cdouble_elliptic_rj_(complex_double * res, complex_double * x, complex_double * y, complex_double * z, complex_double * w, int option, int flags) {+ return arb_fpwrap_cdouble_elliptic_rj(res, *x, *y, *z, *w, option, flags);+};++int arb_fpwrap_cdouble_elliptic_p_(complex_double * res, complex_double * z, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_elliptic_p(res, *z, *tau, flags);+};++int arb_fpwrap_cdouble_elliptic_p_prime_(complex_double * res, complex_double * z, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_elliptic_p_prime(res, *z, *tau, flags);+};++int arb_fpwrap_cdouble_elliptic_inv_p_(complex_double * res, complex_double * z, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_elliptic_inv_p(res, *z, *tau, flags);+};++int arb_fpwrap_cdouble_elliptic_zeta_(complex_double * res, complex_double * z, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_elliptic_zeta(res, *z, *tau, flags);+};++int arb_fpwrap_cdouble_elliptic_sigma_(complex_double * res, complex_double * z, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_elliptic_sigma(res, *z, *tau, flags);+};++int arb_fpwrap_cdouble_jacobi_theta_1_(complex_double * res, complex_double * z, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_jacobi_theta_1(res, *z, *tau, flags);+};++int arb_fpwrap_cdouble_jacobi_theta_2_(complex_double * res, complex_double * z, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_jacobi_theta_2(res, *z, *tau, flags);+};++int arb_fpwrap_cdouble_jacobi_theta_3_(complex_double * res, complex_double * z, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_jacobi_theta_3(res, *z, *tau, flags);+};++int arb_fpwrap_cdouble_jacobi_theta_4_(complex_double * res, complex_double * z, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_jacobi_theta_4(res, *z, *tau, flags);+};++int arb_fpwrap_cdouble_dedekind_eta_(complex_double * res, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_dedekind_eta(res, *tau, flags);+};++int arb_fpwrap_cdouble_modular_j_(complex_double * res, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_modular_j(res, *tau, flags);+};++int arb_fpwrap_cdouble_modular_lambda_(complex_double * res, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_modular_lambda(res, *tau, flags);+};++int arb_fpwrap_cdouble_modular_delta_(complex_double * res, complex_double * tau, int flags) {+ return arb_fpwrap_cdouble_modular_delta(res, *tau, flags);+};+
+ csrc/arb_mat/entry.c view
@@ -0,0 +1,5 @@+#include <flint/arb_mat.h>++arb_ptr arb_mat_entry_(arb_mat_t mat, slong i, slong j) {+ return mat->rows[i] + j;+}
+ csrc/arb_mat/fprintn.c view
@@ -0,0 +1,21 @@+#include <flint/arb.h>+#include <flint/arb_mat.h>++#include "../arb_mat.h"++void+arb_mat_fprintn(FILE * file, const arb_mat_t mat, slong digits, ulong options) {+ slong i, j;+ + for (i = 0; i < arb_mat_nrows(mat); i++) {+ flint_fprintf(file, "[");+ + for (j = 0; j < arb_mat_ncols(mat); j++) {+ arb_fprintn(file, arb_mat_entry(mat, i, j), digits, options);+ + if (j < arb_mat_ncols(mat) - 1) flint_fprintf(file, ", ");+ }+ + flint_fprintf(file, "]\n");+ }+}
+ csrc/arb_mat/get_strd.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/arb.h>+#include <flint/arb_mat.h>++#include "../arb_mat.h"++char*+arb_mat_get_strd(const arb_mat_t mat, slong digits)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ arb_mat_fprintd(out, mat, digits);++ fclose(out);++ return buffer;+}
+ csrc/arb_mat/get_strn.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/arb.h>+#include <flint/arb_mat.h>++#include "../arb_mat.h"++char*+arb_mat_get_strn(const arb_mat_t mat, slong digits, ulong options)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ arb_mat_fprintn(out, mat, digits, options);++ fclose(out);++ return buffer;+}
+ csrc/arb_poly/get_strd.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/arb_poly.h>++#include "../arb.h"++char*+arb_poly_get_strd(const arb_poly_t x, slong digits)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ arb_poly_fprintd(out, x, digits);++ fclose(out);++ return buffer;+}
+ csrc/arf/inlines.c view
@@ -0,0 +1,745 @@+#include <flint/flint.h>+#include <flint/mag.h>+#include <flint/arf.h>+#include <mpfr.h>++int+arf_rounds_down_(arf_rnd_t rnd, int sgnbit)+{+ if (rnd == ARF_RND_DOWN) return 1;+ if (rnd == ARF_RND_UP) return 0;+ if (rnd == ARF_RND_FLOOR) return !sgnbit;+ return sgnbit;+}++int+arf_rounds_up_(arf_rnd_t rnd, int sgnbit)+{+ if (rnd == ARF_RND_DOWN) return 0;+ if (rnd == ARF_RND_UP) return 1;+ if (rnd == ARF_RND_FLOOR) return sgnbit;+ return !sgnbit;+}++mpfr_rnd_t+arf_rnd_to_mpfr_(arf_rnd_t rnd)+{+ if (rnd == ARF_RND_DOWN) return MPFR_RNDZ;+ else if (rnd == ARF_RND_UP) return MPFR_RNDA;+ else if (rnd == ARF_RND_FLOOR) return MPFR_RNDD;+ else if (rnd == ARF_RND_CEIL) return MPFR_RNDU;+ else return MPFR_RNDN;+}++void+arf_init_(arf_t x)+{+ fmpz_init(ARF_EXPREF(x));+ ARF_XSIZE(x) = 0;+}++void+arf_zero_(arf_t x)+{+ ARF_MAKE_SPECIAL(x);+ ARF_EXP(x) = ARF_EXP_ZERO;+}++void+arf_pos_inf_(arf_t x)+{+ ARF_MAKE_SPECIAL(x);+ ARF_EXP(x) = ARF_EXP_POS_INF;+}++void+arf_neg_inf_(arf_t x)+{+ ARF_MAKE_SPECIAL(x);+ ARF_EXP(x) = ARF_EXP_NEG_INF;+}++void+arf_nan_(arf_t x)+{+ ARF_MAKE_SPECIAL(x);+ ARF_EXP(x) = ARF_EXP_NAN;+}++int+arf_is_special_(const arf_t x)+{+ return ARF_IS_SPECIAL(x);+}++int+arf_is_zero_(const arf_t x)+{+ return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_ZERO);+}++int+arf_is_pos_inf_(const arf_t x)+{+ return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_POS_INF);+}++int+arf_is_neg_inf_(const arf_t x)+{+ return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_NEG_INF);+}++int+arf_is_nan_(const arf_t x)+{+ return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_NAN);+}++int+arf_is_normal_(const arf_t x)+{+ return !ARF_IS_SPECIAL(x);+}++int+arf_is_finite_(const arf_t x)+{+ return !ARF_IS_SPECIAL(x) || (ARF_EXP(x) == ARF_EXP_ZERO);+}++int+arf_is_inf_(const arf_t x)+{+ return ARF_IS_SPECIAL(x) && (ARF_EXP(x) == ARF_EXP_POS_INF ||+ ARF_EXP(x) == ARF_EXP_NEG_INF);+}++void+arf_one_(arf_t x)+{+ fmpz_clear(ARF_EXPREF(x));+ ARF_DEMOTE(x);+ ARF_EXP(x) = 1;+ ARF_XSIZE(x) = ARF_MAKE_XSIZE(1, 0);+ ARF_NOPTR_D(x)[0] = LIMB_TOP;+}++int+arf_is_one_(const arf_t x)+{+ return (ARF_EXP(x) == 1) && (ARF_XSIZE(x) == ARF_MAKE_XSIZE(1, 0))+ && ARF_NOPTR_D(x)[0] == LIMB_TOP;+}++int+arf_sgn_(const arf_t x)+{+ if (arf_is_special(x))+ {+ if (arf_is_zero(x) || arf_is_nan(x))+ return 0;+ return arf_is_pos_inf(x) ? 1 : -1;+ }+ else+ {+ return ARF_SGNBIT(x) ? -1 : 1;+ }+}++void+arf_swap_(arf_t y, arf_t x)+{+ if (x != y)+ {+ arf_struct t = *x;+ *x = *y;+ *y = t;+ }+}++void+arf_neg_(arf_t y, const arf_t x)+{+ arf_set(y, x);++ if (arf_is_special(y))+ {+ if (arf_is_pos_inf(y))+ arf_neg_inf(y);+ else if (arf_is_neg_inf(y))+ arf_pos_inf(y);+ }+ else+ {+ ARF_NEG(y);+ }+}++void+arf_init_set_ui_(arf_t x, ulong v)+{+ if (v == 0)+ {+ ARF_EXP(x) = ARF_EXP_ZERO;+ ARF_XSIZE(x) = 0;+ }+ else+ {+ unsigned int c;+ c = flint_clz(v);+ ARF_EXP(x) = FLINT_BITS - c;+ ARF_NOPTR_D(x)[0] = v << c;+ ARF_XSIZE(x) = ARF_MAKE_XSIZE(1, 0);+ }+}++/* FLINT_ABS is unsafe for x = WORD_MIN */+#define UI_ABS_SI(x) (((slong)(x) < 0) ? (-(ulong)(x)) : ((ulong)(x)))++void+arf_init_set_si_(arf_t x, slong v)+{+ arf_init_set_ui(x, UI_ABS_SI(v));+ if (v < 0)+ ARF_NEG(x);+}++void+arf_set_ui_(arf_t x, ulong v)+{+ ARF_DEMOTE(x);+ _fmpz_demote(ARF_EXPREF(x));++ if (v == 0)+ {+ ARF_EXP(x) = ARF_EXP_ZERO;+ ARF_XSIZE(x) = 0;+ }+ else+ {+ unsigned int c;+ c = flint_clz(v);+ ARF_EXP(x) = FLINT_BITS - c;+ ARF_NOPTR_D(x)[0] = v << c;+ ARF_XSIZE(x) = ARF_MAKE_XSIZE(1, 0);+ }+}++void+arf_set_si_(arf_t x, slong v)+{+ arf_set_ui(x, UI_ABS_SI(v));+ if (v < 0)+ ARF_NEG(x);+}++void+arf_init_set_shallow_(arf_t z, const arf_t x)+{+ *z = *x;+}++void+arf_init_neg_shallow_(arf_t z, const arf_t x)+{+ *z = *x;+ arf_neg(z, z);+}++void+arf_init_set_mag_shallow_(arf_t y, const mag_t x)+{+ mp_limb_t t = MAG_MAN(x);+ ARF_XSIZE(y) = ARF_MAKE_XSIZE(t != 0, 0);+ ARF_EXP(y) = MAG_EXP(x);+ ARF_NOPTR_D(y)[0] = t << (FLINT_BITS - MAG_BITS);+}++void+arf_init_neg_mag_shallow_(arf_t z, const mag_t x)+{+ arf_init_set_mag_shallow(z, x);+ arf_neg(z, z);+}++int+arf_cmpabs_mag_(const arf_t x, const mag_t y)+{+ arf_t t;+ arf_init_set_mag_shallow(t, y); /* no need to free */+ return arf_cmpabs(x, t);+}++int+arf_mag_cmpabs_(const mag_t x, const arf_t y)+{+ arf_t t;+ arf_init_set_mag_shallow(t, x); /* no need to free */+ return arf_cmpabs(t, y);+}++void+arf_set_mpz_(arf_t y, const mpz_t x)+{+ slong size = x->_mp_size;++ if (size == 0)+ arf_zero(y);+ else+ arf_set_mpn(y, x->_mp_d, FLINT_ABS(size), size < 0);+}++void+arf_set_fmpz_(arf_t y, const fmpz_t x)+{+ if (!COEFF_IS_MPZ(*x))+ arf_set_si(y, *x);+ else+ arf_set_mpz(y, COEFF_TO_PTR(*x));+}++int+arf_set_round_ui_(arf_t x, ulong v, slong prec, arf_rnd_t rnd)+{+ return _arf_set_round_ui(x, v, 0, prec, rnd);+}++int+arf_set_round_si_(arf_t x, slong v, slong prec, arf_rnd_t rnd)+{+ return _arf_set_round_ui(x, UI_ABS_SI(v), v < 0, prec, rnd);+}++int+arf_set_round_mpz_(arf_t y, const mpz_t x, slong prec, arf_rnd_t rnd)+{+ int inexact;+ slong size = x->_mp_size;+ slong fix;++ if (size == 0)+ {+ arf_zero(y);+ return 0;+ }++ inexact = _arf_set_round_mpn(y, &fix, x->_mp_d, FLINT_ABS(size),+ (size < 0), prec, rnd);+ _fmpz_demote(ARF_EXPREF(y));+ ARF_EXP(y) = FLINT_ABS(size) * FLINT_BITS + fix;+ return inexact;+}++int+arf_set_round_fmpz_(arf_t y, const fmpz_t x, slong prec, arf_rnd_t rnd)+{+ if (!COEFF_IS_MPZ(*x))+ return arf_set_round_si(y, *x, prec, rnd);+ else+ return arf_set_round_mpz(y, COEFF_TO_PTR(*x), prec, rnd);+}++void+arf_min_(arf_t z, const arf_t a, const arf_t b)+{+ if (arf_cmp(a, b) <= 0)+ arf_set(z, a);+ else+ arf_set(z, b);+}++void+arf_max_(arf_t z, const arf_t a, const arf_t b)+{+ if (arf_cmp(a, b) > 0)+ arf_set(z, a);+ else+ arf_set(z, b);+}++void+arf_abs_(arf_t y, const arf_t x)+{+ if (arf_sgn(x) < 0)+ arf_neg(y, x);+ else+ arf_set(y, x);+}++slong+arf_bits_(const arf_t x)+{+ if (arf_is_special(x))+ return 0;+ else+ {+ mp_srcptr xp;+ mp_size_t xn;+ slong c;++ ARF_GET_MPN_READONLY(xp, xn, x);+ c = flint_ctz(xp[0]);+ return xn * FLINT_BITS - c;+ }+}++void+arf_bot_(fmpz_t e, const arf_t x)+{+ if (arf_is_special(x))+ fmpz_zero(e);+ else+ fmpz_sub_si(e, ARF_EXPREF(x), arf_bits(x));+}++void+arf_set_si_2exp_si_(arf_t x, slong man, slong exp)+{+ arf_set_si(x, man);+ if (man != 0)+ fmpz_add_si_inline(ARF_EXPREF(x), ARF_EXPREF(x), exp);+}++void+arf_set_ui_2exp_si_(arf_t x, ulong man, slong exp)+{+ arf_set_ui(x, man);+ if (man != 0)+ fmpz_add_si_inline(ARF_EXPREF(x), ARF_EXPREF(x), exp);+}++void+arf_mul_(arf_t z, arf_t x, arf_t y, slong prec, arf_rnd_t rnd) {+ if( rnd == ARF_RND_DOWN ) {+ arf_mul_rnd_down(z, x, y, prec);+ } else {+ arf_mul_rnd_any(z, x, y, prec, rnd);+ }+}++void+arf_mul_2exp_si_(arf_t y, const arf_t x, slong e)+{+ arf_set(y, x);+ if (!arf_is_special(y))+ fmpz_add_si_inline(ARF_EXPREF(y), ARF_EXPREF(y), e);+}++void+arf_mul_2exp_fmpz_(arf_t y, const arf_t x, const fmpz_t e)+{+ arf_set(y, x);+ if (!arf_is_special(y))+ fmpz_add_inline(ARF_EXPREF(y), ARF_EXPREF(y), e);+}++int+arf_set_round_fmpz_2exp_(arf_t y, const fmpz_t x, const fmpz_t exp, slong prec, arf_rnd_t rnd)+{+ if (fmpz_is_zero(x))+ {+ arf_zero(y);+ return 0;+ }+ else+ {+ int r = arf_set_round_fmpz(y, x, prec, rnd);+ fmpz_add_inline(ARF_EXPREF(y), ARF_EXPREF(y), exp);+ return r;+ }+}++void+arf_abs_bound_lt_2exp_fmpz_(fmpz_t b, const arf_t x)+{+ if (arf_is_special(x))+ fmpz_zero(b);+ else+ fmpz_set(b, ARF_EXPREF(x));+}++void+arf_abs_bound_le_2exp_fmpz_(fmpz_t b, const arf_t x)+{+ if (arf_is_special(x))+ fmpz_zero(b);+ else if (ARF_IS_POW2(x))+ fmpz_sub_ui(b, ARF_EXPREF(x), 1);+ else+ fmpz_set(b, ARF_EXPREF(x));+}++int+arf_neg_mul_(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd)+{+ if (arf_is_special(y))+ {+ arf_mul(z, x, y, prec, rnd);+ arf_neg(z, z);+ return 0;+ }+ else+ {+ arf_t t;+ *t = *y;+ ARF_NEG(t);+ return arf_mul(z, x, t, prec, rnd);+ }+}++int+arf_mul_ui_(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ arf_init_set_ui(t, y); /* no need to free */+ return arf_mul(z, x, t, prec, rnd);+}++int+arf_mul_si_(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ arf_init_set_si(t, y); /* no need to free */+ return arf_mul(z, x, t, prec, rnd);+}++int+arf_mul_fmpz_(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd)+{+ if (!COEFF_IS_MPZ(*y))+ return arf_mul_si(z, x, *y, prec, rnd);+ else+ return arf_mul_mpz(z, x, COEFF_TO_PTR(*y), prec, rnd);+}++int+arf_addmul_ui_(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ arf_init_set_ui(t, y); /* no need to free */+ return arf_addmul(z, x, t, prec, rnd);+}++int+arf_addmul_si_(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ arf_init_set_si(t, y); /* no need to free */+ return arf_addmul(z, x, t, prec, rnd);+}++int+arf_addmul_fmpz_(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd)+{+ if (!COEFF_IS_MPZ(*y))+ return arf_addmul_si(z, x, *y, prec, rnd);+ else+ return arf_addmul_mpz(z, x, COEFF_TO_PTR(*y), prec, rnd);+}++int+arf_submul_ui_(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ arf_init_set_ui(t, y); /* no need to free */+ return arf_submul(z, x, t, prec, rnd);+}++int+arf_submul_si_(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ arf_init_set_si(t, y); /* no need to free */+ return arf_submul(z, x, t, prec, rnd);+}++int+arf_submul_fmpz_(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd)+{+ if (!COEFF_IS_MPZ(*y))+ return arf_submul_si(z, x, *y, prec, rnd);+ else+ return arf_submul_mpz(z, x, COEFF_TO_PTR(*y), prec, rnd);+}++int+arf_div_ui_(arf_ptr z, arf_srcptr x, ulong y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ arf_init_set_ui(t, y); /* no need to free */+ return arf_div(z, x, t, prec, rnd);+}++int+arf_ui_div_(arf_ptr z, ulong x, arf_srcptr y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ arf_init_set_ui(t, x); /* no need to free */+ return arf_div(z, t, y, prec, rnd);+}++int+arf_div_si_(arf_ptr z, arf_srcptr x, slong y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ arf_init_set_si(t, y); /* no need to free */+ return arf_div(z, x, t, prec, rnd);+}++int+arf_si_div_(arf_ptr z, slong x, arf_srcptr y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ arf_init_set_si(t, x); /* no need to free */+ return arf_div(z, t, y, prec, rnd);+}++int+arf_div_fmpz_(arf_ptr z, arf_srcptr x, const fmpz_t y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ int r;+ arf_init(t);+ arf_set_fmpz(t, y);+ r = arf_div(z, x, t, prec, rnd);+ arf_clear(t);+ return r;+}++int+arf_fmpz_div_(arf_ptr z, const fmpz_t x, arf_srcptr y, slong prec, arf_rnd_t rnd)+{+ arf_t t;+ int r;+ arf_init(t);+ arf_set_fmpz(t, x);+ r = arf_div(z, t, y, prec, rnd);+ arf_clear(t);+ return r;+}++int+arf_fmpz_div_fmpz_(arf_ptr z, const fmpz_t x, const fmpz_t y, slong prec, arf_rnd_t rnd)+{+ arf_t t, u;+ int r;+ arf_init(t);+ arf_init(u);+ arf_set_fmpz(t, x);+ arf_set_fmpz(u, y);+ r = arf_div(z, t, u, prec, rnd);+ arf_clear(t);+ arf_clear(u);+ return r;+}++void+arf_set_mag_(arf_t y, const mag_t x)+{+ if (mag_is_zero(x))+ {+ arf_zero(y);+ }+ else if (mag_is_inf(x))+ {+ arf_pos_inf(y);+ }+ else+ {+ _fmpz_set_fast(ARF_EXPREF(y), MAG_EXPREF(x));+ ARF_DEMOTE(y);+ ARF_XSIZE(y) = ARF_MAKE_XSIZE(1, 0);+ ARF_NOPTR_D(y)[0] = MAG_MAN(x) << (FLINT_BITS - MAG_BITS);+ }+}++void+mag_init_set_arf_(mag_t y, const arf_t x)+{+ mag_init(y);+ arf_get_mag(y, x);+}++void+mag_fast_init_set_arf_(mag_t y, const arf_t x)+{+ if (ARF_IS_SPECIAL(x)) /* x == 0 */+ {+ mag_fast_zero(y);+ }+ else+ {+ mp_srcptr xp;+ mp_size_t xn;++ ARF_GET_MPN_READONLY(xp, xn, x);++ MAG_MAN(y) = (xp[xn - 1] >> (FLINT_BITS - MAG_BITS)) + LIMB_ONE;+ MAG_EXP(y) = ARF_EXP(x);++ MAG_FAST_ADJUST_ONE_TOO_LARGE(y);+ }+}++void+arf_mag_fast_add_ulp_(mag_t z, const mag_t x, const arf_t y, slong prec)+{+ mag_fast_add_2exp_si(z, x, ARF_EXP(y) - prec);+}++void+arf_mag_add_ulp_(mag_t z, const mag_t x, const arf_t y, slong prec)+{+ if (ARF_IS_SPECIAL(y))+ {+ flint_printf("error: ulp error not defined for special value!\n");+ flint_abort();+ }+ else if (MAG_IS_LAGOM(z) && MAG_IS_LAGOM(x) && ARF_IS_LAGOM(y))+ {+ arf_mag_fast_add_ulp(z, x, y, prec);+ }+ else+ {+ fmpz_t e;+ fmpz_init(e);+ fmpz_sub_ui(e, ARF_EXPREF(y), prec);+ mag_add_2exp_fmpz(z, x, e);+ fmpz_clear(e);+ }+}++void+arf_mag_set_ulp_(mag_t z, const arf_t y, slong prec)+{+ if (ARF_IS_SPECIAL(y))+ {+ flint_printf("error: ulp error not defined for special value!\n");+ flint_abort();+ }+ else+ {+ _fmpz_add_fast(MAG_EXPREF(z), ARF_EXPREF(y), 1 - prec);+ MAG_MAN(z) = MAG_ONE_HALF;+ }+}++int+arf_set_fmpq_(arf_t y, const fmpq_t x, slong prec, arf_rnd_t rnd)+{+ return arf_fmpz_div_fmpz(y, fmpq_numref(x), fmpq_denref(x), prec, rnd);+}++slong+arf_allocated_bytes_(const arf_t x)+{+ slong size = fmpz_allocated_bytes(ARF_EXPREF(x));++ if (ARF_HAS_PTR(x))+ size += ARF_PTR_ALLOC(x) * sizeof(mp_limb_t);++ return size;+}++
+ csrc/bool_mat/get_str.c view
@@ -0,0 +1,18 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/bool_mat.h>++#include "../bool_mat.h"++char*+bool_mat_get_str(const bool_mat_t mat) {+ char * buffer = NULL;+ size_t buffer_size = 0;+ FILE * out = open_memstream(&buffer, &buffer_size);+ bool_mat_fprint(out, mat);+ fclose(out);+ return buffer;+}
+ csrc/d_mat/entry.c view
@@ -0,0 +1,5 @@+#include <flint/d_mat.h>++double d_mat_entry_(d_mat_t a, slong i, slong j) {+ return d_mat_entry(a, i, j);+}
+ csrc/d_mat/io.c view
@@ -0,0 +1,32 @@+#include <stdio.h>+#include <stdlib.h>++#include <flint/flint.h>++#include "../d_mat.h"++void+d_mat_fprint(FILE *file, const d_mat_t mat) {+ slong i, j; + flint_fprintf(file, "[");+ for (i = 0; i < mat->r; i++) {+ flint_fprintf(file, "[");+ for (j = 0; j < mat->c; j++) {+ flint_fprintf(file, "%E", d_mat_entry(mat, i, j));+ if (j < mat->c - 1)+ flint_fprintf(file, " ");+ }+ flint_fprintf(file, "]\n");+ }+ flint_fprintf(file, "]\n");+}++char*+d_mat_get_str(const d_mat_t mat) {+ char * buffer = NULL;+ size_t buffer_size = 0;+ FILE * out = open_memstream(&buffer, &buffer_size);+ d_mat_fprint(out, mat);+ fclose(out);+ return buffer;+}
+ csrc/dlog/inlines.c view
@@ -0,0 +1,5 @@+#include <flint/flint.h>++#define DLOG_INLINES_C+#include <flint/dlog.h>+
+ csrc/double_interval/fprint.c view
@@ -0,0 +1,9 @@+#include <stdio.h>+#include <flint/double_interval.h>++#include "../double_interval.h"++void di_fprint(FILE * out, const di_t x) {+ flint_fprintf(stderr, "[%.17g, %.17g]", x.a, x.b);+ flint_fprintf(out, "[%.17g, %.17g]", x.a, x.b);+}
+ csrc/double_interval/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/double_interval.h>++#include "../double_interval.h"++char*+di_get_str(const di_t x)+{+ char * buffer = NULL;+ size_t buffer_size = 0;+ + FILE * out = open_memstream(&buffer, &buffer_size);++ di_fprint(out, x);++ fclose(out);++ flint_fprintf(stderr, "[%.17g, %.17g]", x.a, x.b);+ + return buffer;+}
+ csrc/fmpq/cfrac_st.c view
@@ -0,0 +1,59 @@+#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpq.h>++#include "../fmpq.h"++slong fmpq_get_cfrac_st(fmpz *c, fmpq_t rem, const fmpq_t x, slong n) {++ slong k = 0;+ fmpq_t y;++ fmpq_init(y);+ fmpq_set(y, x);+ + fmpz_t q, r;++ fmpz_init(q);+ fmpz_init(r);++ for(slong j=0; j<n; j++) {+ k++;+ fmpz_tdiv_qr(q, r, fmpq_numref(y), fmpq_denref(y));+ if( !fmpz_is_zero(r) ) {+ fmpz_add_ui(c + j, q, 1);+ } else {+ fmpz_set(c + j, q);+ }+ fmpq_set_fmpz_frac(y, r, fmpq_denref(y));+ fmpq_neg(y, y);+ fmpq_add_ui(y, y, 1);+ fmpq_inv(y, y);+ if( fmpz_is_zero(r) ) break;+ };++ fmpq_set(rem, y);+ fmpq_clear(y);+ + fmpz_clear(q);+ fmpz_clear(r);++ return k;+}++void fmpq_set_cfrac_st(fmpq_t x, const fmpz *c, slong n) {++ fmpq_zero(x);+ + for(slong j=n-1; j>0; j--) {+ fmpq_add_fmpz(x, x, c + j);+ fmpq_inv(x, x);+ fmpq_neg(x, x);+ }++ fmpq_add_fmpz(x, x, c);+ +}+ + +
+ csrc/fmpq/get_fmpz_frac.c view
@@ -0,0 +1,6 @@+#include "../fmpq.h"++void fmpq_get_fmpz_frac(fmpz_t num, fmpz_t den, fmpq_t x) {+ fmpz_set(num, fmpq_numref(x));+ fmpz_set(den, fmpq_denref(x));+}
+ csrc/fmpq/mediant.c view
@@ -0,0 +1,20 @@+#include "../fmpq.h"++#include <flint/flint.h>++void fmpq_mediant(fmpq_t x, fmpq_t l, fmpq_t r) {++ fmpz_t num, den;++ fmpz_init(num);+ fmpz_init(den);++ fmpz_add(num, fmpq_numref(l), fmpq_numref(r));+ fmpz_add(den, fmpq_denref(l), fmpq_denref(r));+ + fmpq_set_fmpz_frac(x, num, den);++ fmpz_clear(num);+ fmpz_clear(den);+ +}
+ csrc/fmpq_mat/fprint.c view
@@ -0,0 +1,23 @@+#include "../fmpq_mat.h"++int fmpq_mat_fprint(FILE * file, const fmpq_mat_t mat)+{+ slong i, j;+ + flint_fprintf(file, "<%wd x %wd matrix over Q>\n", mat->r, mat->c);++ flint_fprintf(file, "[");+ for (i = 0; i < mat->r; i++)+ {+ flint_fprintf(file, "[");+ for (j = 0; j < mat->c; j++)+ {+ fmpq_fprint(file, fmpq_mat_entry(mat, i, j));+ if (j + 1 < mat->c)+ flint_fprintf(file, ", ");+ }+ flint_fprintf(file, "]\n");+ }+ flint_fprintf(file, "]");+ return 1;+}
+ csrc/fmpq_mat/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fmpq.h>+#include <flint/fmpq_mat.h>++#include "../fmpq_mat.h"++char*+fmpq_mat_get_str(const fmpq_mat_t mat)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fmpq_mat_fprint(out, mat);++ fclose(out);++ return buffer;+}
+ csrc/fmpq_poly/io_as_series.c view
@@ -0,0 +1,82 @@+#include <stdio.h>+#include <stdlib.h>++#include <flint/flint.h>+#include <flint/fmpq.h>+#include <flint/fmpq_poly.h>++int+fmpq_poly_fprint_pretty_as_series(+ FILE *file,+ fmpq_poly_t poly,+ const char *var+) {++ fmpq_t c;+ + fmpq_init(c);++ slong k = 0;+ + if(poly->length == 0) {+ flint_fprintf(file, "0");+ return 0;+ }++ while( fmpz_is_zero(poly->coeffs+k) ) {+ k++;+ }+ + for(slong j=k; j<poly->length; j++) {+ if( fmpz_is_zero(poly->coeffs+j) ) continue;+ fmpq_set_fmpz_frac(c, poly->coeffs+j, poly->den);+ if( j > k ) {+ if( fmpq_cmp_si(c, 0) > 0 ) {+ flint_fprintf(file, " + ");+ } else {+ flint_fprintf(file, " - ");+ }+ } else {+ if( fmpq_cmp_si(c, 0) < 0 ) {+ flint_fprintf(file, "-");+ }+ }+ if( fmpq_is_pm1(c) ) {+ if( j > 0) {+ if( j > 1 ) {+ flint_fprintf(file, "%s^%d", var, j);+ } else {+ flint_fprintf(file, "%s", var);+ }+ } else if( j == 0 ) {+ fmpq_abs(c, c);+ fmpq_fprint(file, c);+ }+ } else {+ fmpq_abs(c, c);+ fmpq_fprint(file, c);+ if( j > 1 ) {+ flint_fprintf(file, "*%s^%d", var, j);+ } else {+ flint_fprintf(file, "*%s", var);+ }+ }+ }++ flint_fprintf(file, " + O(%s^%d)", var, poly->length);++ return 0;+}+ +char * fmpq_poly_get_str_pretty_as_series(fmpq_poly_t poly, const char *var) {+ char * buffer = NULL;+ size_t buffer_size = 0;+ FILE * out = open_memstream(&buffer, &buffer_size);+ fmpq_poly_fprint_pretty_as_series(out, poly, var);+ fclose(out);+ return buffer;+}++int fmpq_poly_print_pretty_as_series(fmpq_poly_t poly, const char *var) {+ return fmpq_poly_fprint_pretty_as_series(stdout, poly, var);+}
+ csrc/fmpq_poly/monien.c view
@@ -0,0 +1,62 @@+#include <flint/fmpz.h>+#include <flint/fmpq.h>+#include <flint/fmpq_poly.h>++#include "../fmpq_poly.h"++void+_fmpq_poly_monien_h (fmpz * coeffs, fmpz_t den, ulong n)+{+ fmpz_t c;+ int odd;+ ulong k;+ ulong L;++ if (n == 0)+ {+ fmpz_one (coeffs);+ fmpz_one (den);+ return;+ }++ if (n == 1)+ {+ fmpz_zero (coeffs);+ fmpz_set_si(coeffs, -1);+ fmpz_set_ui(coeffs + 1, 15);+ fmpz_set_ui(den, 15);+ return;+ }++ fmpz_init (c);++ for (k = 0; k <= n; k++)+ {+ fmpz_fac_ui (coeffs + k, 2 * (n + k) + 1);+ fmpz_fac_ui (c, 2 * (n - k) + 1);+ fmpz_divexact (coeffs + k, coeffs + k, c);+ fmpz_fac_ui (c, 2 * k);+ fmpz_divexact (coeffs + k, coeffs + k, c);+ fmpz_set_si (c, -4);+ fmpz_pow_ui (c, c, k);+ fmpz_divexact (coeffs + k, coeffs + k, c);+ }++ fmpz_fac_ui (den, 4 * n + 1);+ fmpz_fac_ui (c, 2 * n);+ fmpz_divexact (den, den, c);+ fmpz_set_si (c, -4);+ fmpz_pow_ui (c, c, n);+ fmpz_divexact (den, den, c);++ fmpz_clear (c);++}++void+fmpq_poly_monien_h (fmpq_poly_t poly, ulong n)+{+ fmpq_poly_fit_length (poly, n + 1);+ _fmpq_poly_monien_h (poly->coeffs, poly->den, n);+ _fmpq_poly_set_length (poly, n + 1);+}
+ csrc/fmpq_vec/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fmpq.h>+#include <flint/fmpq_vec.h>++#include "../fmpq_vec.h"++char*+_fmpq_vec_get_str(const long n, const fmpq_t vec)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ _fmpq_vec_fprint(out, vec, n);++ fclose(out);++ return buffer;+}
+ csrc/fmpz/clear.c view
@@ -0,0 +1,11 @@+#include <stdio.h>++#include <flint/flint.h>+#include <flint/fmpz.h>++void p_fmpz_clear(fmpz_t x) {+#ifdef DEBUG+ flint_fprintf(stderr, "p_fmpz_clear 0x%016p\n", x);+#endif+ fmpz_clear(x);+}
+ csrc/fmpz/init.c view
@@ -0,0 +1,11 @@+#include <stdio.h>++#include <flint/flint.h>+#include <flint/fmpz.h>++void p_fmpz_init(fmpz_t x) {+#ifdef DEBUG+ flint_fprintf(stderr, "p_fmpz_init 0x%016p\n", x);+#endif+ fmpz_init(x);+}
+ csrc/fmpz_factor/clear.c view
@@ -0,0 +1,12 @@+#include <stdio.h>++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_factor.h>++#include "../fmpz_factor.h"++void fmpz_factor_clear_(fmpz_factor_t x) {+ flint_fprintf(stderr, "p_fmpz_factor_clear 0x%016p\n", x);+ fmpz_factor_clear(x);+}
+ csrc/fmpz_factor/fprint.c view
@@ -0,0 +1,40 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_factor.h>++#include "../fmpz_factor.h"++void+fmpz_factor_fprint(FILE * out, const fmpz_factor_t factor)+{+ slong i;++ if (factor->sign == 0)+ {+ flint_fprintf(out, "0");+ return;+ }++ if (factor->sign == -1)+ {+ if (factor->num)+ flint_fprintf(out, "-1 * ");+ else+ flint_fprintf(out, "-1");+ }++ for (i = 0; i < factor->num; i++)+ {+ fmpz_fprint(out, factor->p + i);++ if (factor->exp[i] != UWORD(1))+ flint_fprintf(out, "^%wu", factor->exp[i]);++ if (i != factor->num - 1)+ flint_fprintf(out, " * ");+ }+}
+ csrc/fmpz_factor/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_factor.h>++#include "../fmpz_factor.h"++char*+fmpz_factor_get_str(const fmpz_factor_t factor)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fmpz_factor_fprint(out, factor);++ fclose(out);++ return buffer;+}
+ csrc/fmpz_factor/init.c view
@@ -0,0 +1,12 @@+#include <stdio.h>++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_factor.h>++#include "../fmpz_factor.h"++void fmpz_factor_init_(fmpz_factor_t x) {+ flint_fprintf(stderr, "p_fmpz_factor_init 0x%016p\n", x);+ fmpz_factor_init(x);+}
+ csrc/fmpz_mat/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_mat.h>++#include "../fmpz_mat.h"++char*+fmpz_mat_get_str(const fmpz_mat_t mat)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fmpz_mat_fprint(out, mat);++ fclose(out);++ return buffer;+}
+ csrc/fmpz_mat/get_str_pretty.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_mat.h>++#include "../fmpz_mat.h"++char*+fmpz_mat_get_str_pretty(const fmpz_mat_t mat)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fmpz_mat_fprint_pretty(out, mat);++ fclose(out);++ return buffer;+}
+ csrc/fmpz_mod_poly_factor/fprint.c view
@@ -0,0 +1,20 @@+#include <stdio.h>++#include <flint/fmpz_mod_poly.h>+#include <flint/fmpz_mod_poly_factor.h>++#include "../fmpz_mod_poly_factor.h"++void+fmpz_mod_poly_factor_fprint(FILE * out,+ const fmpz_mod_poly_factor_t fac,+ const fmpz_mod_ctx_t ctx)+{+ slong i;+ + for (i = 0; i < fac->num; i++)+ {+ fmpz_mod_poly_fprint(out, fac->poly + i, ctx);+ flint_fprintf(out, " ^ %wd\n", fac->exp[i]);+ }+}
+ csrc/fmpz_mod_poly_factor/fprint_pretty.c view
@@ -0,0 +1,20 @@+#include <stdio.h>++#include <flint/fmpz_mod_poly.h>+#include <flint/fmpz_mod_poly_factor.h>++#include "../fmpz_mod_poly_factor.h"++void+fmpz_mod_poly_factor_fprint_pretty(FILE * out,+ const fmpz_mod_poly_factor_t fac,+ const char *var,+ const fmpz_mod_ctx_t ctx)+{+ slong i;+ for (i = 0; i < fac->num; i++)+ {+ fmpz_mod_poly_fprint_pretty(out, fac->poly + i, var, ctx);+ flint_fprintf(out, " ^ %wd\n", fac->exp[i]);+ }+}
+ csrc/fmpz_mod_poly_factor/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/fmpz_mod_poly.h>+#include <flint/fmpz_mod_poly_factor.h>++#include "../fmpz_mod_poly_factor.h"++char * +fmpz_mod_poly_factor_get_str(const fmpz_mod_poly_factor_t fac,+ const fmpz_mod_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fmpz_mod_poly_factor_fprint(out, fac, ctx);++ fclose(out);++ return buffer;+}
+ csrc/fmpz_mod_poly_factor/get_str_pretty.c view
@@ -0,0 +1,25 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/fmpz_mod_poly.h>+#include <flint/fmpz_mod_poly_factor.h>++#include "../fmpz_mod_poly_factor.h"++char * +fmpz_mod_poly_factor_get_str_pretty(const fmpz_mod_poly_factor_t fac,+ const char * var, + const fmpz_mod_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fmpz_mod_poly_factor_fprint_pretty(out, fac, var, ctx);++ fclose(out);++ return buffer;+}
+ csrc/fmpz_mpoly_q/fprint.c view
@@ -0,0 +1,37 @@+/*+ Copyright (C) 2023 Hartmut Monien+ This file is part of Calcium.++ Calcium is free software: you can redistribute it and/or modify it under+ the terms of the GNU Lesser General Public License (LGPL) as published+ by the Free Software Foundation; either version 2.1 of the License, or+ (at your option) any later version. See <http://www.gnu.org/licenses/>.+*/++#include <stdio.h>+#include "../fmpz_mpoly_q.h"++void+fmpz_mpoly_q_fprint_pretty(FILE *out, const fmpz_mpoly_q_t f, const char ** x, const fmpz_mpoly_ctx_t ctx)+{+ if (fmpz_mpoly_is_one(fmpz_mpoly_q_denref(f), ctx))+ {+ fmpz_mpoly_fprint_pretty(out, fmpz_mpoly_q_numref(f), x, ctx);+ }+ else if (fmpz_mpoly_is_fmpz(fmpz_mpoly_q_denref(f), ctx))+ {+ flint_fprintf(out, "(");+ fmpz_mpoly_fprint_pretty(out, fmpz_mpoly_q_numref(f), x, ctx);+ flint_fprintf(out, ")/");+ fmpz_mpoly_fprint_pretty(out, fmpz_mpoly_q_denref(f), x, ctx);+ }+ else+ {+ flint_fprintf(out, "(");+ fmpz_mpoly_fprint_pretty(out, fmpz_mpoly_q_numref(f), x, ctx);+ flint_fprintf(out, ")/(");+ fmpz_mpoly_fprint_pretty(out, fmpz_mpoly_q_denref(f), x, ctx);+ flint_fprintf(out, ")");+ }+}+
+ csrc/fmpz_mpoly_q/get_str_pretty.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_mpoly_q.h>++#include "../fmpz_mpoly_q.h"++char*+fmpz_mpoly_q_get_str_pretty(const fmpz_mpoly_q_t x, const char ** vars, const fmpz_mpoly_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fmpz_mpoly_q_fprint_pretty(out, x, vars, ctx);++ fclose(out);++ return buffer;+}
+ csrc/fmpz_poly_mat/fprint.c view
@@ -0,0 +1,39 @@+/*+ Copyright (C) 2011 Fredrik Johansson++ This file is part of FLINT.++ FLINT is free software: you can redistribute it and/or modify it under+ the terms of the GNU Lesser General Public License (LGPL) as published+ by the Free Software Foundation; either version 2.1 of the License, or+ (at your option) any later version. See <https://www.gnu.org/licenses/>.+*/++#include <stdio.h>++#include <flint/flint.h>+#include <flint/fmpz_poly.h>+#include <flint/fmpz_poly_mat.h>++#include "../fmpz_poly_mat.h"++void+fmpz_poly_mat_fprint(FILE * file, const fmpz_poly_mat_t A, const char * x)+{+ slong i, j;+ + flint_fprintf(file, "<%wd x %wd matrix over Z[%s]>\n", A->r, A->c, x);++ for (i = 0; i < A->r; i++)+ {+ flint_fprintf(file, "[");+ for (j = 0; j < A->c; j++)+ {+ fmpz_poly_fprint_pretty(file, fmpz_poly_mat_entry(A, i, j), x);+ if (j + 1 < A->c)+ flint_fprintf(file, ", ");+ }+ flint_fprintf(file, "]\n");+ }+ flint_fprintf(file, "\n");+}
+ csrc/fmpz_poly_mat/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_poly_mat.h>++#include "../fmpz_poly_mat.h"++char*+fmpz_poly_mat_get_str(const fmpz_poly_mat_t mat, const char * x)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fmpz_poly_mat_fprint(out, mat, x);++ fclose(out);++ return buffer;+}
+ csrc/fmpz_vec/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_vec.h>++#include "../fmpz_vec.h"++char*+_fmpz_vec_get_str(const long n, const fmpz_t vec)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ _fmpz_vec_fprint(out, vec, n);++ fclose(out);++ return buffer;+}
+ csrc/fmpzi/fprint.c view
@@ -0,0 +1,18 @@+#include <stdio.h>++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpzi.h>++#include "../fmpzi.h"++void+fmpzi_fprint(FILE * file, const fmpzi_t x)+{+ fmpz_fprint(file, fmpzi_realref(x));+ if (fmpz_sgn(fmpzi_imagref(x)) >= 0)+ flint_fprintf(file, "+");+ fmpz_fprint(file, fmpzi_imagref(x));+ flint_fprintf(file, "*I");+}+
+ csrc/fmpzi/get_str.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fmpzi.h>++#include "../fmpzi.h"++char*+fmpzi_get_str(const fmpzi_t z)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fmpzi_fprint(out, z);++ fclose(out);++ return buffer;+}
+ csrc/fq/ctx_get_str.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fq.h>++#include "../fq.h"++char*+fq_ctx_get_str(const fq_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fq_ctx_fprint(out, ctx);++ fclose(out);++ return buffer;+}
+ csrc/fq_mat/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fq.h>+#include <flint/fq_mat.h>++#include "../fq_mat.h"++char*+fq_mat_get_str(const fq_mat_t mat, const fq_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fq_mat_fprint(out, mat, ctx);++ fclose(out);++ return buffer;+}
+ csrc/fq_mat/get_str_pretty.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fq.h>+#include <flint/fq_mat.h>++#include "../fq_mat.h"++char*+fq_mat_get_str_pretty(const fq_mat_t mat, const fq_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fq_mat_fprint_pretty(out, mat, ctx);++ fclose(out);++ return buffer;+}
+ csrc/fq_nmod/ctx_get_str.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fq_nmod.h>++#include "../fmpz_mat.h"++char*+fq_nmod_ctx_get_str(const fq_nmod_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fq_nmod_ctx_fprint(out, ctx);++ fclose(out);++ return buffer;+}
+ csrc/fq_nmod_mat/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fq_nmod.h>+#include <flint/fq_nmod_mat.h>++#include "../fq_nmod_mat.h"++char*+fq_nmod_mat_get_str(const fq_nmod_mat_t mat, fq_nmod_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fq_nmod_mat_fprint(out, mat, ctx);++ fclose(out);++ return buffer;+}
+ csrc/fq_nmod_mat/get_str_pretty.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fq_nmod.h>+#include <flint/fq_nmod_mat.h>++#include "../fq_nmod_mat.h"++char*+fq_nmod_mat_get_str_pretty(const fq_nmod_mat_t mat, fq_nmod_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fq_nmod_mat_fprint_pretty(out, mat, ctx);++ fclose(out);++ return buffer;+}
+ csrc/fq_zech/ctx_get_str.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fq_zech.h>++#include "../fmpz_mat.h"++char*+fq_zech_ctx_get_str(const fq_zech_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fq_zech_ctx_fprint(out, ctx);++ fclose(out);++ return buffer;+}
+ csrc/fq_zech_mat/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fq_zech.h>+#include <flint/fq_zech_mat.h>++#include "../fq_zech_mat.h"++char*+fq_zech_mat_get_str(const fq_zech_mat_t mat, fq_zech_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fq_zech_mat_fprint(out, mat, ctx);++ fclose(out);++ return buffer;+}
+ csrc/fq_zech_mat/get_str_pretty.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/fq_zech.h>+#include <flint/fq_zech_mat.h>++#include "../fq_zech_mat.h"++char*+fq_zech_mat_get_str_pretty(const fq_zech_mat_t mat, fq_zech_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ fq_zech_mat_fprint_pretty(out, mat, ctx);++ fclose(out);++ return buffer;+}
+ csrc/mag/get_str.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/mag.h>++#include "../mag.h"++char*+mag_get_str(const mag_t x)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ mag_fprint(out, x);++ fclose(out);++ return buffer;+}
+ csrc/mpfr_mat/swap_entrywise.c view
@@ -0,0 +1,14 @@+#include <flint/flint.h>+#include <flint/mpfr_mat.h>++#include "../mpfr_mat.h"++void+mpfr_mat_swap_entrywise_(mpfr_mat_t mat1, mpfr_mat_t mat2)+{+ slong i, j;++ for (i = 0; i < mpfr_mat_nrows(mat1); i++)+ for (j = 0; j < mpfr_mat_ncols(mat1); j++)+ mpfr_swap(mpfr_mat_entry(mat2, i, j), mpfr_mat_entry(mat1, i, j));+}
+ csrc/nmod_poly_factor/fprint.c view
@@ -0,0 +1,29 @@+/*+ Copyright (C) 2007 David Howden+ Copyright (C) 2007, 2008, 2009, 2010 William Hart+ Copyright (C) 2008 Richard Howell-Peak+ Copyright (C) 2011 Fredrik Johansson+ Copyright (C) 2023 Hartmut Monien++ This file is part of FLINT.++ FLINT is free software: you can redistribute it and/or modify it under+ the terms of the GNU Lesser General Public License (LGPL) as published+ by the Free Software Foundation; either version 2.1 of the License, or+ (at your option) any later version. See <https://www.gnu.org/licenses/>.+*/++#include <flint/nmod_poly.h>+#include <flint/nmod_poly_factor.h>++void+nmod_poly_factor_fprint(FILE * file, const nmod_poly_factor_t fac)+{+ slong i;+ + for (i = 0; i < fac->num; i++)+ {+ nmod_poly_fprint(file, fac->p + i);+ flint_fprintf(file, " ^ %wd\n", fac->exp[i]);+ }+}
+ csrc/nmod_poly_factor/fprint_pretty.c view
@@ -0,0 +1,25 @@+/*+ Copyright (C) 2023 Hartmut Monien++ This file is part of FLINT.++ FLINT is free software: you can redistribute it and/or modify it under+ the terms of the GNU Lesser General Public License (LGPL) as published+ by the Free Software Foundation; either version 2.1 of the License, or+ (at your option) any later version. See <https://www.gnu.org/licenses/>.+*/++#include <stdio.h>++#include <flint/nmod_poly.h>+#include <flint/nmod_poly_factor.h>++void nmod_poly_factor_fprint_pretty(FILE * file, const nmod_poly_factor_t fac, const char *var)+{+ slong i;+ for (i = 0; i < fac->num; i++)+ {+ nmod_poly_fprint_pretty(file, fac->p + i, var);+ flint_fprintf(file, " ^ %wd\n", fac->exp[i]);+ }+}
+ csrc/nmod_poly_factor/get_str.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/nmod_poly_factor.h>++#include "../nmod_poly_factor.h"++char*+nmod_poly_factor_get_str(const nmod_poly_factor_t fac)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ nmod_poly_factor_fprint(out, fac);++ fclose(out);++ return buffer;+}
+ csrc/nmod_poly_factor/get_str_pretty.c view
@@ -0,0 +1,23 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/nmod_poly_factor.h>++#include "../nmod_poly_factor.h"++char*+nmod_poly_factor_get_str_pretty(const nmod_poly_factor_t fac, const char *var)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ nmod_poly_factor_fprint_pretty(out, fac, var);++ fclose(out);++ return buffer;+}
+ csrc/nmod_poly_mat/fprint.c view
@@ -0,0 +1,29 @@+#include <stdio.h>++#include <flint/flint.h>+#include <flint/nmod_poly.h>+#include <flint/nmod_poly_mat.h>++#include "../nmod_poly_mat.h"++void+nmod_poly_mat_fprint(FILE * file, const nmod_poly_mat_t A, const char * x)+{+ slong i, j;++ flint_fprintf(file, "<%wd x %wd matrix over Z/nZ[%s]>\n", A->r, A->c, x);++ for (i = 0; i < A->r; i++)+ {+ flint_fprintf(file, "[");+ for (j = 0; j < A->c; j++)+ {+ /* TODO: pretty */+ nmod_poly_fprint(file, nmod_poly_mat_entry(A, i, j));+ if (j + 1 < A->c)+ flint_fprintf(file, ", ");+ }+ flint_fprintf(file, "]\n");+ }+ flint_fprintf(file, "\n");+}
+ csrc/nmod_poly_mat/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/nmod.h>+#include <flint/nmod_poly_mat.h>++#include "../nmod_poly_mat.h"++char*+nmod_poly_mat_get_str(const nmod_poly_mat_t mat, const char * x)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ nmod_poly_mat_fprint(out, mat, x);++ fclose(out);++ return buffer;+}
+ csrc/padic_mat/get_str.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/padic.h>+#include <flint/padic_mat.h>++#include "../padic_mat.h"++char*+padic_mat_get_str(const padic_mat_t mat, padic_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ padic_mat_fprint(out, mat, ctx);++ fclose(out);++ return buffer;+}
+ csrc/padic_mat/get_str_pretty.c view
@@ -0,0 +1,24 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/padic.h>+#include <flint/padic_mat.h>++#include "../padic_mat.h"++char*+padic_mat_get_str_pretty(const padic_mat_t mat, padic_ctx_t ctx)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ padic_mat_fprint_pretty(out, mat, ctx);++ fclose(out);++ return buffer;+}
+ csrc/padic_poly/get_str.c view
@@ -0,0 +1,16 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/padic_poly.h>++char*+padic_poly_get_str(padic_poly_t poly, const padic_ctx_t ctx)+{+ char* buffer = NULL;+ size_t bufferSize = 0;+ FILE* out = open_memstream(&buffer, &bufferSize);+ padic_poly_fprint(out, poly, ctx);+ fclose(out);+ return buffer;+}
+ csrc/padic_poly/get_str_pretty.c view
@@ -0,0 +1,16 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/padic_poly.h>++char*+padic_poly_get_str_pretty(padic_poly_t poly, const char *var, const padic_ctx_t ctx)+{+ char* buffer = NULL;+ size_t bufferSize = 0;+ FILE* out = open_memstream(&buffer, &bufferSize);+ padic_poly_fprint_pretty(out, poly, var, ctx);+ fclose(out);+ return buffer;+}
+ csrc/perm/mat.c view
@@ -0,0 +1,11 @@+#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_mat.h>+#include <flint/perm.h>++void _perm_mat(fmpz_mat_t a, slong *x, slong n) {+ fmpz_mat_zero(a);+ for(slong j=0; j<n; j++) {+ fmpz_one(fmpz_mat_entry(a, j, x[j]));+ }+}
+ csrc/perm/order.c view
@@ -0,0 +1,38 @@+#include "../perm.h"++void _perm_order(fmpz_t order, slong *x, slong n) {++ slong *m = _perm_init(n);+ slong k, l, mark = 0;+ + int found;++ fmpz_t tmp;+ + fmpz_init(tmp);+ fmpz_set_ui(order, 1);+ + do {+ found = 0;+ for(slong j=0; j<n; j++) {+ if( m[j] < 0 ) {+ } else {+ // found unmarked+ found = 1;+ mark--;+ k = j;+ l = 0;+ do {+ m[k] = mark;+ k = x[k];+ l++;+ } while ( m[k] >= 0 );+ fmpz_set_si(tmp, l);+ fmpz_lcm(order, order, tmp);+ }+ } + } while( found );+ + fmpz_clear(tmp);+ _perm_clear(m);+}
+ csrc/perm/power.c view
@@ -0,0 +1,26 @@+#include <stdlib.h>+#include <flint/perm.h>++#include "../perm.h"++void _perm_power(slong *x_p, slong *x, slong p, slong n) {++ ulong tmp = labs(p);++ slong *w = _perm_init(n);++ _perm_set(x_p, w, n);+ _perm_set(w, x, n);++ for(slong j=0; j<8*sizeof(ulong); j++) {+ if( tmp & 0x1 ) {+ _perm_compose(x_p, x_p, w, n);+ }+ _perm_compose(w, w, w, n);+ tmp >>= 1;+ }++ if( p < 0 ) _perm_inv(x_p, x_p, n);+ + _perm_clear(w);+}
+ csrc/perm/print_pretty.c view
@@ -0,0 +1,82 @@+#include <stdio.h>++#include "../perm.h"++void cycle_fprint(FILE *file, slong *x, slong n) {++ slong k = 0;++ if( n > 1 ) {+ + for(slong j=0; j<n; j++) {+ if( x[j] < x[k] ) k = j;+ }+ + flint_fprintf(file, "(");+ + for(slong j=0; j+1<n; j++) {+ flint_fprintf(file, "%d,", x[(j+k) % n] + 1);+ }+ + flint_fprintf(file, "%d)", x[(n-1+k) % n] + 1);+ }+}++void _perm_fprint_pretty(FILE *file, slong *x, slong n) {++ slong *m = flint_malloc(n * sizeof(slong));+ slong *c = flint_malloc(n * sizeof(slong));+ + slong k, l, mark = 0;+ + int found, flag = 1;++ for(slong j=0; j<n; j++) {+ m[j] = j;+ flag = flag && (x[j] == j);+ }+ + if ( flag ) {+ flint_fprintf(file, "()");+ return;+ }+ + do {+ found = 0;+ for(slong j=0; j<n; j++) {+ if( m[j] < 0 ) {+ } else {+ // found unmarked+ found = 1;+ mark--;+ l = 0;+ k = j;+ do {+ m[k] = mark;+ k = x[k];+ c[l] = k;;+ l++;+ } while( m[k] >= 0 );+ }+ cycle_fprint(file, c, l);+ l = 0;+ }+ } while( found );++ flint_free(m);+ flint_free(c);+}++void _perm_print_pretty(slong *x, slong n) {+ _perm_fprint_pretty(stdout, x, n);+}++char * _perm_get_str_pretty(slong *x, slong n) {+ char * buffer = NULL;+ size_t buffer_size = 0;+ FILE * out = open_memstream(&buffer, &buffer_size);+ _perm_fprint_pretty(out, x, n);+ fclose(out);+ return buffer;+}+
+ csrc/psl2z/word_problem.c view
@@ -0,0 +1,301 @@+#include <stdlib.h>+#include <stdio.h>++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpq.h>+#include <flint/fmpz_vec.h>+#include <flint/acb_modular.h>+#include <flint/perm.h>++#include "../perm.h"+#include "../psl2z.h"++void psl2z_word_init(psl2z_word_t word) {+ word->letters = _fmpz_vec_init(1);+ word->alloc = 0;+}++void psl2z_word_clear(psl2z_word_t word) {+ _fmpz_vec_clear(word->letters, word->alloc);+ word->alloc = 0;+}++void psl2z_normal_form(psl2z_t x) {+ if (fmpz_sgn(&x->c) < 0 || (fmpz_is_zero(&x->c) && fmpz_sgn(&x->d) < 0)) {+ fmpz_neg(&x->a, &x->a);+ fmpz_neg(&x->b, &x->b);+ fmpz_neg(&x->c, &x->c);+ fmpz_neg(&x->d, &x->d);+ }+}++void psl2z_get_word(psl2z_word_t word, psl2z_t g) {++ if( psl2z_is_one(g) ) return;++ psl2z_t x;+ psl2z_init(x);+ psl2z_set(x, g);+ + fmpz_t u, v, q, r;++ fmpz_init(u);+ fmpz_init(v);+ fmpz_init(q);+ fmpz_init(r);++ while( ! psl2z_is_one(x) ) {++ // add space for new letter+ word->alloc += 1;+ if( word->alloc == 1 ) {+ word->letters = flint_malloc(word->alloc * sizeof(fmpz));+ } else {+ word->letters = flint_realloc(word->letters, word->alloc * sizeof(fmpz));+ }++ fmpz_init(word->letters + word->alloc - 1);++ // 2*u = 2*(4*a*c + b*d)+ fmpz_mul(u, &x->a, &x->c);+ fmpz_mul_ui(u, u, 4);+ fmpz_mul(r, &x->b, &x->d);+ fmpz_add(u, u, r);+ fmpz_mul_ui(u, u, 2);++ // v = 4*c^2 + d^2+ fmpz_mul(v, &x->c, &x->c);+ fmpz_mul_ui(v, v, 4);+ fmpz_mul(r, &x->d, &x->d);+ fmpz_add(v, v, r);++ // quotRem (2*u + v) (2*v) = (q, r)+ fmpz_add(q, u, v);+ fmpz_mul_ui(r, v, 2);+ fmpz_fdiv_q(q, q, r);++ // |2*u| - v+ fmpz_abs(u, u);+ fmpz_sub(u, u, v);++ if( fmpz_cmp_si(u, 0) > 0) {+ // multiply be T ^ (-q)+ fmpz_submul(&x->a, q, &x->c);+ fmpz_submul(&x->b, q, &x->d);+ fmpz_set(word->letters + word->alloc - 1, q);+ } else {+ // multiply by S+ fmpz_swap(&x->a, &x->c);+ fmpz_swap(&x->b, &x->d);+ fmpz_neg(&x->a, &x->a);+ fmpz_neg(&x->b, &x->b);+ fmpz_zero(word->letters + word->alloc - 1);+ }++ psl2z_normal_form(x);+ }++ fmpz_clear(u);+ fmpz_clear(v);+ fmpz_clear(q);+ fmpz_clear(r);++ psl2z_clear(x);+}++void psl2z_set_word(psl2z_t x, psl2z_word_t word) {++ psl2z_one(x);+ + for(slong j=0; j<word->alloc; j++) {+ fmpz * q = word->letters + word->alloc - 1 - j;+ if( fmpz_cmp_si(q, 0) == 0) {+ // multiply by S+ fmpz_swap(&x->a, &x->c);+ fmpz_swap(&x->b, &x->d);+ fmpz_neg(&x->a, &x->a);+ fmpz_neg(&x->b, &x->b);+ } else {+ // multiply be T ^ q;+ fmpz_addmul(&x->a, q, &x->c);+ fmpz_addmul(&x->b, q, &x->d);+ }+ }++ psl2z_normal_form(x);+}++void _perm_set_word(slong *x, slong *s, slong *t, slong n, psl2z_word_t word) {++ fmpz_t q, m;++ fmpz_init(q);+ fmpz_init(m);++ _perm_order(m, t, n);+ + slong *r;+ r = _perm_init(n);++ _perm_set_one(x, n);+ + for(slong j=0; j<word->alloc; j++) {+ fmpz_set(q, word->letters + word->alloc - 1 - j);+ if( fmpz_cmp_si(q, 0) == 0) {+ _perm_compose(x, x, s, n);+ } else {+ // multiply be T ^ q;+ if( fmpz_cmp_si(q, 0) < 0 ) {+ fmpz_neg(q, q);+ _perm_inv(r, t, n);+ } else {+ _perm_set(r, t, n);+ }+ fmpz_mod(q, q, m);+ slong e = fmpz_get_si(q);+ for(slong j=0; j<e; j++) {+ _perm_compose(x, x, r, n);+ }+ }+ }++ fmpz_clear(q);+ fmpz_clear(m);+ + _perm_clear(r);++}++//-- Input and Output ----------------------------------------------------------++void psl2z_word_fprint_pretty(FILE * file, psl2z_word_t word) {+ flint_fprintf(file, "[");+ for(slong j=0; j<word->alloc; j++) {+ flint_fprintf(file, "(");+ if( fmpz_is_zero(word->letters + j) ) {+ flint_fprintf(file, "S,3");+ } else {+ flint_fprintf(file, "T,");+ fmpz_fprint(file, word->letters + j);+ }+ flint_fprintf(file, ")");+ if( j + 1 < word->alloc ) flint_fprintf(file, ",");+ }+ flint_fprintf(file, "]");+}++void psl2z_word_print_pretty(psl2z_word_t word) {+ psl2z_word_fprint_pretty(stdout, word);+}++char * psl2z_word_get_str_pretty(psl2z_word_t word) {+ char * buffer = NULL;+ size_t buffer_size = 0;+ FILE * out = open_memstream(&buffer, &buffer_size);+ psl2z_word_fprint_pretty(out, word);+ fclose(out);+ return buffer;+}++void psl2z_word_fprint(FILE * file, psl2z_word_t word) {+ _fmpz_vec_fprint(file, word->letters, word->alloc);+}++void psl2z_word_print(psl2z_word_t word) {+ psl2z_word_fprint(stdout, word);+}++char * psl2z_word_get_str(psl2z_word_t word) {+ char * buffer = NULL;+ size_t buffer_size = 0;+ FILE * out = open_memstream(&buffer, &buffer_size);+ psl2z_word_fprint(out, word);+ fclose(out);+ return buffer;+}++//------------------------------------------------------------------------------++void psl2z_get_perm(slong *p, slong *s, slong *t, slong n, psl2z_t g) {++ slong *tmp = _perm_init(n);+ + _perm_set(p, tmp, n);++ if( psl2z_is_one(g) ) {+ _perm_clear(tmp);+ return;+ }+++ psl2z_t x;+ psl2z_init(x);+ psl2z_set(x, g);+ + fmpz_t u, v, q, r, order;++ fmpz_init(u);+ fmpz_init(v);+ fmpz_init(q);+ fmpz_init(r);+ fmpz_init(order);++ _perm_order(order, t, n);++ while( ! psl2z_is_one(x) ) {++ // 2*u = 2*(4*a*c + b*d)+ fmpz_mul(u, &x->a, &x->c);+ fmpz_mul_ui(u, u, 4);+ fmpz_mul(r, &x->b, &x->d);+ fmpz_add(u, u, r);+ fmpz_mul_ui(u, u, 2);++ // v = 4*c^2 + d^2+ fmpz_mul(v, &x->c, &x->c);+ fmpz_mul_ui(v, v, 4);+ fmpz_mul(r, &x->d, &x->d);+ fmpz_add(v, v, r);++ // quotRem (2*u + v) (2*v) = (q, r)+ fmpz_add(q, u, v);+ fmpz_mul_ui(r, v, 2);+ fmpz_fdiv_q(q, q, r);++ // |2*u| - v+ fmpz_abs(u, u);+ fmpz_sub(u, u, v);++ if( fmpz_cmp_si(u, 0) > 0) {+ // multiply be T ^ (-q)+ fmpz_submul(&x->a, q, &x->c);+ fmpz_submul(&x->b, q, &x->d);+ fmpz_neg(q, q);+ fmpz_mod(q, q, order);+ _perm_power(tmp, t, fmpz_get_si(q), n);+ _perm_compose(p, p, tmp, n);+ } else {+ // multiply by S+ fmpz_swap(&x->a, &x->c);+ fmpz_swap(&x->b, &x->d);+ fmpz_neg(&x->a, &x->a);+ fmpz_neg(&x->b, &x->b);+ _perm_compose(p, p, s, n);+ }++ psl2z_normal_form(x);+ + }++ fmpz_clear(u);+ fmpz_clear(v);+ fmpz_clear(q);+ fmpz_clear(r);+ fmpz_clear(order);+ + psl2z_clear(x);+ _perm_clear(tmp);++ _perm_inv(p, p, n);+}
+ csrc/qadic/get_str_pretty.c view
@@ -0,0 +1,15 @@+#include <limits.h>+#include <string.h>++#include <flint/flint.h>+#include <flint/qadic.h>++char *+qadic_get_str_pretty (const qadic_t op, const qadic_ctx_t ctx) {+ char* buffer = NULL;+ size_t bufferSize = 0;+ FILE* out = open_memstream(&buffer, &bufferSize);+ qadic_fprint_pretty(out, op, ctx);+ fclose(out);+ return buffer;+}
+ csrc/qfb/fprint.c view
@@ -0,0 +1,26 @@+/*+ 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 <https://www.gnu.org/licenses/>.+*/++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/qfb.h>+ +#include "../qfb.h"+ +/* printing *******************************************************************/++void qfb_fprint(FILE * out, const qfb_t q)+{+ flint_fprintf(out, "(");+ fmpz_fprint(out, q->a); flint_fprintf(out, ", ");+ fmpz_fprint(out, q->b); flint_fprintf(out, ", ");+ fmpz_fprint(out, q->c); flint_fprintf(out, ")");+}
+ csrc/qfb/get_str.c view
@@ -0,0 +1,22 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>++#include "../qfb.h"++char*+qfb_get_str(const qfb_t x)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ qfb_fprint(out, x);++ fclose(out);++ return buffer;+}
+ csrc/qqbar/fprint.c view
@@ -0,0 +1,34 @@+/*+ Copyright (C) 2020 Fredrik Johansson++ This file is part of Calcium.++ Calcium is free software: you can redistribute it and/or modify it under+ the terms of the GNU Lesser General Public License (LGPL) as published+ by the Free Software Foundation; either version 2.1 of the License, or+ (at your option) any later version. See <http://www.gnu.org/licenses/>.+*/++#include <flint/flint.h>+#include <flint/qqbar.h>++#include "../qqbar.h"++void+qqbar_fprint(FILE * out, const qqbar_t x)+{+ slong i, d;+ d = qqbar_degree(x);++ flint_fprintf(out, "deg %wd [", qqbar_degree(x));+ for (i = 0; i <= d; i++)+ {+ fmpz_fprint(out, QQBAR_COEFFS(x) + i);+ if (i < d)+ flint_fprintf(out, ", ");+ }+ flint_fprintf(out, "] ");+ acb_fprintn(out, QQBAR_ENCLOSURE(x), FLINT_MAX(6, FLINT_MIN(acb_rel_accuracy_bits(QQBAR_ENCLOSURE(x)),+ acb_bits(QQBAR_ENCLOSURE(x)))), 0);+}+
+ csrc/qqbar/fprintn.c view
@@ -0,0 +1,39 @@+/*+ Copyright (C) 2020 Fredrik Johansson++ This file is part of Calcium.++ Calcium is free software: you can redistribute it and/or modify it under+ the terms of the GNU Lesser General Public License (LGPL) as published+ by the Free Software Foundation; either version 2.1 of the License, or+ (at your option) any later version. See <http://www.gnu.org/licenses/>.+*/++#include <flint/flint.h>+#include <flint/qqbar.h>++#include "../qqbar.h"++void+qqbar_fprintn(FILE * out, const qqbar_t x, slong n)+{+ acb_t t;+ slong prec;+ + n = FLINT_MAX(1, n);+ prec = n * 3.333 + 10;+ + acb_init(t);+ qqbar_get_acb(t, x, prec);+ + acb_fprintn(out, t, n, ARB_STR_NO_RADIUS);+ acb_clear(t);+}++void+qqbar_fprintnd(FILE * out, const qqbar_t x, slong n)+{+ qqbar_fprintn(out, x, n);+ flint_fprintf(out, " (deg %wd)", qqbar_degree(x));+}+
+ csrc/qqbar/get_str.c view
@@ -0,0 +1,22 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>++#include "../qqbar.h"++char*+qqbar_get_str(const qqbar_t x)+{+ char * buffer = NULL;+ size_t buffer_size = 0;++ FILE * out = open_memstream(&buffer, &buffer_size);++ qqbar_fprint(out, x);++ fclose(out);++ return buffer;+}
+ csrc/qqbar/get_strn.c view
@@ -0,0 +1,37 @@+#include <stdlib.h>+#include <stdio.h>+#include <string.h>++#include <flint/flint.h>++#include "../qqbar.h"++char*+qqbar_get_strn(const qqbar_t x, slong digits)+{+ char * buffer = NULL;+ size_t buffer_size = 0;+ + FILE * out = open_memstream(&buffer, &buffer_size);+ + qqbar_fprintn(out, x, digits);+ + fclose(out);+ + return buffer;+}++char*+qqbar_get_strnd(const qqbar_t x, slong digits)+{+ char * buffer = NULL;+ size_t buffer_size = 0;+ + FILE * out = open_memstream(&buffer, &buffer_size);+ + qqbar_fprintnd(out, x, digits);+ + fclose(out);+ + return buffer;+}
+ docs/out.png view
binary file changed (absent → 248693 bytes)
+ src/Data/Number/Flint.hs view
@@ -0,0 +1,342 @@+{-# OPTIONS_HADDOCK prune, ignore-exports #-}++{-|+module : Data.Number.Flint.Flint+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++= What is FLINT ?++FLINT is a C library for doing number theory, freely available under the GNU LGPL at [https://flintlib.org](https://flintlib.org)++Some domains handled by FLINT are \(\mathbb{Z}\), \(\mathbb{Q}\), \(\mathbb{F}_q\), \(\overline{\mathbb{Q}}\), \(\mathbb{C}\) and \(Q[x,y,z]\).+At its core, FLINT provides arithmetic+in standard rings such as the integers, rationals, algebraic, real,+complex and p-adic numbers, finite fields, and number fields. It also+provides polynomials (univariate and multivariate), power series, and+matrices.++FLINT covers a wide range of functionality: primality testing, integer factorisation, multivariate polynomial GCD and factorisation, FFTs, multimodular reconstruction, special functions, exact and approximate linear algebra, LLL, finite field embeddings, and more.++= Mature & widely used++FLINT is the work of dozens of contributors, spanning 15+ years of development. The upcoming FLINT 3.0 release comprises 8,000 documented functions, 3,500 test programs, and 900,000 lines of code.++FLINT runs on most common platforms, including Linux, macOS and Windows on typical hardware configurations. Several computer algebra systems rely on FLINT as a back-end library, including SageMath, Oscar, Singular, Macaulay2, Maple and Mathematica. Wrappers are also available for various programming languages, including Python and Julia.++= At the research frontier++FLINT has been used for many large scale research computations (for example: A Trillion Triangles) and has been cited in hundreds of publications. FLINT's authors themselves have published more than 20 papers describing new algorithms first implemented within or on top of FLINT.++= Efficient++FLINT is designed for all operand sizes, from single-word to multi-gigabyte. It implements many low-level optimisations and chooses automatically between basecase, intermediate, asymptotically fast and special-purpose algorithms depending on the size and structure of the problem. Many algorithms are fully parallel (multithreaded) and some key functions use SIMD acceleration.++= Handles real numbers++<<docs/out.png>> ++FLINT has advanced support for real and complex numbers, implemented using ball arithmetic. It covers a variety of numerical functionality (polynomial arithmetic, transcendental functions, numerical integration, linear algebra, etc.) with arbitrary precision and with rigorous error bounds. FLINT also provides an exact (symbolic) model of real and complex numbers with the ability to decide equalities.++= Developer-friendly++FLINT has a developer-friendly GMP-like C API which makes it easy to write performant and type-safe code with fine-grained control over in-place mutations, memory allocation, precision, conversions between representations, and algorithm parameters. FLINT also provides well-documented access to most of its internals. Finally, the FLINT project is developed openly in collaboration with the community, and welcomes contributions (feature requests, bug reports, patches, testing, documentation, general feedback) from anyone.++Note: this functionality is new in FLINT 3.0 and is due to merging the spin-off projects Arb, Antic and Calcium which were previously maintained as standalone libraries.++= Now this functionality is also available in Haskell!++The modules in `Data.Number.Flint` provide a access to most of the+functionality in @flintlib@. Many of the data structures have been+translated to Haskell. Typically an object of type __x_t__ in flint+will be called __X__ and can be created with a function name __newX__+and a applied to a flint function with a __withX__ function. E.g. the+integers in flint with the type `Fmpz` will be created in the IO+monad using `newFmpz` and used with the `withFmpz` function.++ -}++module Data.Number.Flint (+ module Data.Number.Flint.Flint+, module Data.Number.Flint.UFD+, module Data.Number.Flint.Quotient+, module Data.Number.Flint.MPoly+-- * Integers+, module Data.Number.Flint.Fmpz+-- ** Factorization of integers+, module Data.Number.Flint.Fmpz.Factor+-- ** Arithmtic and special functions for integers+, module Data.Number.Flint.Fmpz.Arith+, module Data.Number.Flint.Fmpz.Vec+, module Data.Number.Flint.Fmpz.Mat+, module Data.Number.Flint.Fmpz.Poly+, module Data.Number.Flint.Fmpz.Poly.Instances+, module Data.Number.Flint.Fmpz.Poly.Mat+, module Data.Number.Flint.Fmpz.Poly.Factor+, module Data.Number.Flint.Fmpz.Poly.Q+, module Data.Number.Flint.Fmpz.MPoly+, module Data.Number.Flint.Fmpz.MPoly.Factor+, module Data.Number.Flint.Fmpz.MPoly.Q+, module Data.Number.Flint.Fmpz.LLL+-- ** Integers mod n+, module Data.Number.Flint.Fmpz.Mod+, module Data.Number.Flint.Fmpz.Mod.Poly+, module Data.Number.Flint.Fmpz.Mod.Poly.Factor+, module Data.Number.Flint.Fmpz.Mod.MPoly+, module Data.Number.Flint.Fmpz.Mod.MPoly.Factor+, module Data.Number.Flint.Fmpz.Mod.Mat+-- * Rational numbers+, module Data.Number.Flint.Fmpq+, module Data.Number.Flint.Fmpq.Mat+, module Data.Number.Flint.Fmpq.Vec+, module Data.Number.Flint.Fmpq.Poly+, module Data.Number.Flint.Fmpq.MPoly+, module Data.Number.Flint.Fmpq.MPoly.Factor+-- * APRCL primality testing+, module Data.Number.Flint.APRCL+-- * FFT+, module Data.Number.Flint.FFT+--, module Data.Number.Flint.FFT.Small+-- * Quadratic sieve+, module Data.Number.Flint.QSieve+-- * Integers mod n+, module Data.Number.Flint.NMod+, module Data.Number.Flint.NMod.Poly+, module Data.Number.Flint.NMod.Poly.Factor+, module Data.Number.Flint.NMod.Poly.Mat+, module Data.Number.Flint.NMod.MPoly+, module Data.Number.Flint.NMod.MPoly.Factor+, module Data.Number.Flint.NMod.Mat+, module Data.Number.Flint.NMod.Vec+-- * Groups and other structures+, module Data.Number.Flint.Groups.Perm+, module Data.Number.Flint.Groups.Qfb+, module Data.Number.Flint.Groups.Dirichlet+, module Data.Number.Flint.Groups.DLog+, module Data.Number.Flint.Groups.Bool.Mat+-- * Number fields and algebraic numbers+, module Data.Number.Flint.NF+, module Data.Number.Flint.NF.Elem+, module Data.Number.Flint.NF.Fmpzi+, module Data.Number.Flint.NF.QQbar+-- * Real and complex numbers+-- ** Real+, module Data.Number.Flint.Arb+, module Data.Number.Flint.Arb.RealField+, module Data.Number.Flint.Arb.Mag+, module Data.Number.Flint.Arb.Arf+, module Data.Number.Flint.Arb.Poly+, module Data.Number.Flint.Arb.Fmpz.Poly+, module Data.Number.Flint.Arb.Mat+, module Data.Number.Flint.Arb.Hypgeom+, module Data.Number.Flint.Arb.Calc+, module Data.Number.Flint.Arb.FpWrap+-- * Complex+, module Data.Number.Flint.Acb+, module Data.Number.Flint.Acb.ComplexField+, module Data.Number.Flint.Acb.Acf+, module Data.Number.Flint.Acb.Poly+, module Data.Number.Flint.Acb.Mat+, module Data.Number.Flint.Acb.Hypgeom+, module Data.Number.Flint.Acb.Modular+, module Data.Number.Flint.Acb.Dirichlet+, module Data.Number.Flint.Acb.DFT+, module Data.Number.Flint.Acb.Calc+-- ** Partitions+, module Data.Number.Flint.Partitions+-- ** Bernoulli numbers+, module Data.Number.Flint.Bernoulli+-- * Finite Fields+, module Data.Number.Flint.Fq+, module Data.Number.Flint.Fq.Embed+, module Data.Number.Flint.Fq.Poly+, module Data.Number.Flint.Fq.Poly.Factor+, module Data.Number.Flint.Fq.Vec+, module Data.Number.Flint.Fq.Mat+-- ** NMod+, module Data.Number.Flint.Fq.NMod+, module Data.Number.Flint.Fq.NMod.Embed+, module Data.Number.Flint.Fq.NMod.Poly+, module Data.Number.Flint.Fq.NMod.Poly.Factor+, module Data.Number.Flint.Fq.NMod.MPoly+, module Data.Number.Flint.Fq.NMod.MPoly.Factor+, module Data.Number.Flint.Fq.NMod.Mat+, module Data.Number.Flint.Fq.NMod.Vec+-- ** Zech+, module Data.Number.Flint.Fq.Zech+, module Data.Number.Flint.Fq.Zech.Embed+, module Data.Number.Flint.Fq.Zech.Poly+, module Data.Number.Flint.Fq.Zech.Poly.Factor+, module Data.Number.Flint.Fq.Zech.Vec+, module Data.Number.Flint.Fq.Zech.Mat+-- * p-adic Numbers+, module Data.Number.Flint.Padic+, module Data.Number.Flint.Padic.Poly+, module Data.Number.Flint.Padic.Mat+, module Data.Number.Flint.Qadic+-- * Floating-point support code+, module Data.Number.Flint.Support.ULong.Extras+, module Data.Number.Flint.Support.D.Extras+, module Data.Number.Flint.Support.D.Interval+, module Data.Number.Flint.Support.D.Mat+, module Data.Number.Flint.Support.D.Vec+, module Data.Number.Flint.Support.Mpf.Mat+, module Data.Number.Flint.Support.Mpf.Vec+, module Data.Number.Flint.Support.Mpfr.Mat+, module Data.Number.Flint.Support.Mpfr.Vec+) where++import Data.Number.Flint.Flint+import Data.Number.Flint.MPoly+-- Integers+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Factor+import Data.Number.Flint.Fmpz.Arith+import Data.Number.Flint.Fmpz.Vec+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Poly.Mat+import Data.Number.Flint.Fmpz.Poly.Factor+import Data.Number.Flint.Fmpz.Poly.Q+import Data.Number.Flint.Fmpz.MPoly+import Data.Number.Flint.Fmpz.MPoly.Factor+import Data.Number.Flint.Fmpz.MPoly.Q+import Data.Number.Flint.Fmpz.LLL+import Data.Number.Flint.Fmpz.Mod+import Data.Number.Flint.Fmpz.Mod.Vec+import Data.Number.Flint.Fmpz.Mod.Mat+import Data.Number.Flint.Fmpz.Mod.Poly+import Data.Number.Flint.Fmpz.Mod.Poly.Factor+import Data.Number.Flint.Fmpz.Mod.MPoly+import Data.Number.Flint.Fmpz.Mod.MPoly.Factor+-- Rational numbers+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fmpq.Mat+import Data.Number.Flint.Fmpq.Vec+import Data.Number.Flint.Fmpq.Poly+import Data.Number.Flint.Fmpq.MPoly+import Data.Number.Flint.Fmpq.MPoly.Factor+-- APRCL primality testing+import Data.Number.Flint.APRCL+-- FFT+import Data.Number.Flint.FFT+-- import Data.Number.Flint.FFT.Small+-- Quadratic sieve+import Data.Number.Flint.QSieve+-- Integers mod n+import Data.Number.Flint.NMod+import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.NMod.Poly.Factor+import Data.Number.Flint.NMod.Poly.Mat+import Data.Number.Flint.NMod.MPoly+import Data.Number.Flint.NMod.MPoly.Factor+import Data.Number.Flint.NMod.Mat+import Data.Number.Flint.NMod.Vec+-- Groups and other structures+import Data.Number.Flint.Groups.Perm+import Data.Number.Flint.Groups.Qfb+import Data.Number.Flint.Groups.Dirichlet+import Data.Number.Flint.Groups.DLog+import Data.Number.Flint.Groups.Bool.Mat+-- Number fields and algebraic structures+import Data.Number.Flint.NF+import Data.Number.Flint.NF.Elem+import Data.Number.Flint.NF.Fmpzi+import Data.Number.Flint.NF.QQbar+-- Finite fields+import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.Embed+import Data.Number.Flint.Fq.Poly+import Data.Number.Flint.Fq.Poly.Factor+import Data.Number.Flint.Fq.Mat+import Data.Number.Flint.Fq.Vec+-- NMod+import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Embed+import Data.Number.Flint.Fq.NMod.Poly+import Data.Number.Flint.Fq.NMod.Poly.Factor+import Data.Number.Flint.Fq.NMod.MPoly+import Data.Number.Flint.Fq.NMod.MPoly.Factor+import Data.Number.Flint.Fq.NMod.Mat+import Data.Number.Flint.Fq.NMod.Vec+-- Zech+import Data.Number.Flint.Fq.Zech+import Data.Number.Flint.Fq.Zech.Embed+import Data.Number.Flint.Fq.Zech.Poly+import Data.Number.Flint.Fq.Zech.Poly.Factor+import Data.Number.Flint.Fq.Zech.Vec+import Data.Number.Flint.Fq.Zech.Mat+-- p-adic numbers+import Data.Number.Flint.Padic+import Data.Number.Flint.Padic.Poly+import Data.Number.Flint.Padic.Mat+import Data.Number.Flint.Qadic+-- Real and complex numbers+-- Real+import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.Mag+import Data.Number.Flint.Arb.Arf+import Data.Number.Flint.Arb.Poly+import Data.Number.Flint.Arb.Fmpz.Poly+import Data.Number.Flint.Arb.Mat+import Data.Number.Flint.Arb.Hypgeom+import Data.Number.Flint.Arb.RealField+import Data.Number.Flint.Arb.Calc+import Data.Number.Flint.Arb.FpWrap+-- Complex+import Data.Number.Flint.Acb+import Data.Number.Flint.Acb.Acf+import Data.Number.Flint.Acb.Poly+import Data.Number.Flint.Acb.Mat+import Data.Number.Flint.Acb.Modular+import Data.Number.Flint.Acb.Dirichlet+import Data.Number.Flint.Acb.Hypgeom+import Data.Number.Flint.Acb.DFT+import Data.Number.Flint.Acb.ComplexField+import Data.Number.Flint.Acb.Calc+-- Partitions+import Data.Number.Flint.Partitions+-- Bernoulli numbers+import Data.Number.Flint.Bernoulli+-- Floating-point support code+import Data.Number.Flint.Support.ULong.Extras+import Data.Number.Flint.Support.D.Extras+import Data.Number.Flint.Support.D.Interval+import Data.Number.Flint.Support.D.Mat+import Data.Number.Flint.Support.D.Vec+import Data.Number.Flint.Support.Mpf.Mat+import Data.Number.Flint.Support.Mpf.Vec+import Data.Number.Flint.Support.Mpfr.Mat+import Data.Number.Flint.Support.Mpfr.Vec++import Data.Number.Flint.UFD+import Data.Number.Flint.Quotient++import Data.Number.Flint.Fmpz.Instances+import Data.Number.Flint.Fmpz.Poly.Instances+import Data.Number.Flint.Fmpz.Poly.Q.Instances+import Data.Number.Flint.Fmpz.Mat.Instances++import Data.Number.Flint.Fmpq.Instances+import Data.Number.Flint.Fmpq.Poly.Instances+import Data.Number.Flint.Fmpq.Mat.Instances++import Data.Number.Flint.NF.Fmpzi.Instances+import Data.Number.Flint.NF.QQbar.Instances++import Data.Number.Flint.NMod.Poly.Instances++import Data.Number.Flint.Arb.Instances+import Data.Number.Flint.Arb.Poly.Instances+import Data.Number.Flint.Arb.Mat.Instances++import Data.Number.Flint.Acb.Instances+import Data.Number.Flint.Acb.Poly.Instances+import Data.Number.Flint.Acb.Mat.Instances+import Data.Number.Flint.Acb.Modular.Instances++import Data.Number.Flint.Groups.Qfb.Instances+import Data.Number.Flint.Groups.Bool.Mat.Instances++import Data.Number.Flint.Support.D.Mat.Instances
+ src/Data/Number/Flint/APRCL.hs view
@@ -0,0 +1,6 @@+module Data.Number.Flint.APRCL (+ module Data.Number.Flint.APRCL.FFI+) where++import Data.Number.Flint.APRCL.FFI+
+ src/Data/Number/Flint/APRCL/FFI.hsc view
@@ -0,0 +1,759 @@+{-|+module : Data.Number.Flint.APRCL.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.APRCL.FFI (+ -- * APRCL primality testing+ APRCLConfig (..)+ , CAPRCLConfig (..)+ , newAPRCLConfigGauss+ , newAPRCLConfigJacobi+ , withAPRCLConfig+ -- * Primality test functions+ , aprcl_is_prime+ , aprcl_is_prime_jacobi+ , aprcl_is_prime_gauss+ , _aprcl_is_prime_jacobi+ , _aprcl_is_prime_gauss+ , aprcl_is_prime_gauss_min_R+ , aprcl_is_prime_final_division+ -- * Configuration functions+ , aprcl_config_gauss_init+ , aprcl_config_gauss_init_min_R+ , aprcl_config_gauss_clear+ , aprcl_R_value+ , aprcl_config_jacobi_init+ , aprcl_config_jacobi_clear+ -- * Cyclotomic arithmetic+ , UnityZp (..)+ , CUnityZp (..)+ , newUnityZp+ , withUnityZp+ , UnityZpq (..)+ , CUnityZpq (..)+ , newUnityZpq+ , withUnityZpq+ -- * Memory management+ , unity_zp_init+ , unity_zp_clear+ , unity_zp_copy+ , unity_zp_swap+ , unity_zp_set_zero+ -- * Comparison+ , unity_zp_is_unity+ , unity_zp_equal+ -- * Output+ , unity_zp_print+ -- * Coefficient management+ , unity_zp_coeff_set_fmpz+ , unity_zp_coeff_set_ui+ , unity_zp_coeff_add_fmpz+ , unity_zp_coeff_add_ui+ , unity_zp_coeff_inc+ , unity_zp_coeff_dec+ -- * Scalar multiplication+ , unity_zp_mul_scalar_fmpz+ , unity_zp_mul_scalar_ui+ -- * Addition and multiplication+ , unity_zp_add+ , unity_zp_mul+ , unity_zp_sqr+ , unity_zp_mul_inplace+ , unity_zp_sqr_inplace+ -- * Powering functions+ , unity_zp_pow_fmpz+ , unity_zp_pow_ui+ , _unity_zp_pow_select_k+ , unity_zp_pow_2k_fmpz+ , unity_zp_pow_2k_ui+ , unity_zp_pow_sliding_fmpz+ -- * Cyclotomic reduction+ , _unity_zp_reduce_cyclotomic_divmod+ , _unity_zp_reduce_cyclotomic+ , unity_zp_reduce_cyclotomic+ -- * Automorphism and inverse+ , unity_zp_aut+ , unity_zp_aut_inv+ -- * Jacobi sum+ , unity_zp_jacobi_sum_pq+ , unity_zp_jacobi_sum_2q_one+ , unity_zp_jacobi_sum_2q_two+ -- * Extended rings+ , unity_zpq_init+ , unity_zpq_clear+ , unity_zpq_copy+ , unity_zpq_swap+ , unity_zpq_equal+ , unity_zpq_p_unity+ , unity_zpq_is_p_unity+ , unity_zpq_is_p_unity_generator+ , unity_zpq_coeff_set_fmpz+ , unity_zpq_coeff_set_ui+ , unity_zpq_coeff_add+ , unity_zpq_add+ , unity_zpq_mul+ , _unity_zpq_mul_unity_p+ , unity_zpq_mul_unity_p_pow+ , unity_zpq_pow+ , unity_zpq_pow_ui+ , unity_zpq_gauss_sum+ , unity_zpq_gauss_sum_sigma_pow+) where++-- APRCL primality testing -----------------------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mod+import Data.Number.Flint.Fmpz.Mod.Poly+import Data.Number.Flint.Support.ULong.Extras++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/aprcl.h>++-- aprcl_config ----------------------------------------------------------------++data APRCLConfig =+ Gauss {-# UNPACK #-} !(ForeignPtr CAPRCLConfig)+ | Jacobi {-# UNPACK #-} !(ForeignPtr CAPRCLConfig)+ +data CAPRCLConfig =+ CAPRCLConfig CULong+ (Ptr CFmpz)+ (Ptr CNFactor)+ (Ptr CFmpz)+ (Ptr CInt)+ +instance Storable CAPRCLConfig where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size aprcl_config}+ {-# INLINE alignment #-}+ alignment _ = #{alignment aprcl_config}+ peek = error "CAPRCLConfig.peek: not implemented."+ poke = error "CAPRCLConfig.poke: not implemented."++newAPRCLConfigGauss n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFmpz n $ \n ->+ aprcl_config_gauss_init x n+ addForeignPtrFinalizer p_aprcl_config_gauss_clear x+ return $ Gauss x++newAPRCLConfigJacobi n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFmpz n $ \n ->+ aprcl_config_jacobi_init x n+ addForeignPtrFinalizer p_aprcl_config_jacobi_clear x+ return $ Jacobi x++withAPRCLConfig (Gauss x) f = do+ withForeignPtr x $ \px -> f px >>= return . (Gauss x,)++withAPRCLConfig (Jacobi x) f = do+ withForeignPtr x $ \px -> f px >>= return . (Jacobi x,)++-- primality_test_status -------------------------------------------------------++newtype PrimalityTestStatus =+ PrimalityTestStatus { _PrimalityTestStatus :: CInt } deriving Eq++instance Show PrimalityTestStatus where+ show status+ | status == unknown = "UNKNOWN"+ | status == prime = "PRIME"+ | status == composite = "COMPOSITE"+ | status == probaprime = "PROBABPRIME"+ | otherwise = "unknown PrimalityTestStatus."++unknown = PrimalityTestStatus #const UNKNOWN+prime = PrimalityTestStatus #const PRIME+composite = PrimalityTestStatus #const COMPOSITE+probaprime = PrimalityTestStatus #const PROBABPRIME++-- Primality test functions ----------------------------------------------------++-- | /aprcl_is_prime/ /n/ +--+-- Tests \(n\) for primality using the APRCL test. This is the same as+-- @aprcl_is_prime_jacobi@.+foreign import ccall "aprcl.h aprcl_is_prime"+ aprcl_is_prime :: Ptr CFmpz -> IO CInt++-- | /aprcl_is_prime_jacobi/ /n/ +--+-- If \(n\) is prime returns 1; otherwise returns 0. The algorithm is well+-- described in \"Implementation of a New Primality Test\" by H. Cohen and+-- A.K. Lenstra and \"A Course in Computational Algebraic Number Theory\"+-- by H. Cohen.+-- +-- It is theoretically possible that this function fails to prove that+-- \(n\) is prime. In this event, @flint_abort@ is called. To handle this+-- condition, the @_aprcl_is_prime_jacobi@ function can be used.+foreign import ccall "aprcl.h aprcl_is_prime_jacobi"+ aprcl_is_prime_jacobi :: Ptr CFmpz -> IO CInt++-- | /aprcl_is_prime_gauss/ /n/ +--+-- If \(n\) is prime returns 1; otherwise returns 0. Uses the cyclotomic+-- primality testing algorithm described in \"Four primality testing+-- algorithms\" by Rene Schoof. The minimum required numbers \(s\) and+-- \(R\) are computed automatically.+-- +-- By default \(R \ge 180\). In some cases this function fails to prove+-- that \(n\) is prime. This means that we select a too small \(R\) value.+-- In this event, @flint_abort@ is called. To handle this condition, the+-- @_aprcl_is_prime_jacobi@ function can be used.+foreign import ccall "aprcl.h aprcl_is_prime_gauss"+ aprcl_is_prime_gauss :: Ptr CFmpz -> IO CInt++-- | /_aprcl_is_prime_jacobi/ /n/ /config/ +--+-- Jacobi sum test for \(n\). Possible return values: @PRIME@, @COMPOSITE@+-- and @UNKNOWN@ (if we cannot prove primality).+foreign import ccall "aprcl.h _aprcl_is_prime_jacobi"+ _aprcl_is_prime_jacobi :: Ptr CFmpz -> Ptr CAPRCLConfig -> IO PrimalityTestStatus++-- | /_aprcl_is_prime_gauss/ /n/ /config/ +--+-- Tests \(n\) for primality with fixed @config@. Possible return values:+-- @PRIME@, @COMPOSITE@ and @PROBABPRIME@ (if we cannot prove primality).+foreign import ccall "aprcl.h _aprcl_is_prime_gauss"+ _aprcl_is_prime_gauss :: Ptr CFmpz -> Ptr CAPRCLConfig -> IO PrimalityTestStatus++-- | /aprcl_is_prime_gauss_min_R/ /n/ /R/ +--+-- Same as @aprcl_is_prime_gauss@ with fixed minimum value of \(R\).+foreign import ccall "aprcl.h aprcl_is_prime_gauss_min_R"+ aprcl_is_prime_gauss_min_R :: Ptr CFmpz -> CULong -> IO ()++-- | /aprcl_is_prime_final_division/ /n/ /s/ /r/ +--+-- Returns 0 if for some \(a = n^k \bmod s\), where \(k \in [1, r - 1]\),+-- we have that \(a \mid n\); otherwise returns 1.+foreign import ccall "aprcl.h aprcl_is_prime_final_division"+ aprcl_is_prime_final_division :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO CInt++-- Configuration functions -----------------------------------------------------++-- | /aprcl_config_gauss_init/ /conf/ /n/ +--+-- Computes the \(s\) and \(R\) values used in the cyclotomic primality+-- test, \(s^2 > n\) and+-- \(s=\prod\limits_{\substack{q-1\mid R \\ q \text{ prime}}}q\). Also+-- stores factors of \(R\) and \(s\).+foreign import ccall "aprcl.h aprcl_config_gauss_init"+ aprcl_config_gauss_init :: Ptr CAPRCLConfig -> Ptr CFmpz -> IO ()++-- | /aprcl_config_gauss_init_min_R/ /conf/ /n/ /R/ +--+-- Computes the \(s\) with fixed minimum \(R\) such that+-- \(a^R \equiv 1 \mod{s}\) for all integers \(a\) coprime to \(s\).+foreign import ccall "aprcl.h aprcl_config_gauss_init_min_R"+ aprcl_config_gauss_init_min_R :: Ptr CAPRCLConfig -> Ptr CFmpz -> CULong -> IO ()++-- | /aprcl_config_gauss_clear/ /conf/ +--+-- Clears the given @aprcl_config@ element. It must be reinitialised in+-- order to be used again.+foreign import ccall "aprcl.h aprcl_config_gauss_clear"+ aprcl_config_gauss_clear :: Ptr CAPRCLConfig -> IO ()++foreign import ccall "aprcl.h &aprcl_config_gauss_clear"+ p_aprcl_config_gauss_clear :: FunPtr (Ptr CAPRCLConfig -> IO ())++-- | /aprcl_R_value/ /n/ +--+-- Returns a precomputed \(R\) value for APRCL, such that the corresponding+-- \(s\) value is greater than \(\sqrt{n}\). The maximum stored value+-- \(6983776800\) allows to test numbers up to \(6000\) digits.+foreign import ccall "aprcl.h aprcl_R_value"+ aprcl_R_value :: Ptr CFmpz -> IO CULong++-- | /aprcl_config_jacobi_init/ /conf/ /n/ +--+-- Computes the \(s\) and \(R\) values used in the cyclotomic primality+-- test, \(s^2 > n\) and \(a^R \equiv 1 \mod{s}\) for all \(a\) coprime to+-- \(s\). Also stores factors of \(R\) and \(s\).+foreign import ccall "aprcl.h aprcl_config_jacobi_init"+ aprcl_config_jacobi_init :: Ptr CAPRCLConfig -> Ptr CFmpz -> IO ()++-- | /aprcl_config_jacobi_clear/ /conf/ +--+-- Clears the given @aprcl_config@ element. It must be reinitialised in+-- order to be used again.+foreign import ccall "aprcl.h aprcl_config_jacobi_clear"+ aprcl_config_jacobi_clear :: Ptr CAPRCLConfig -> IO ()++foreign import ccall "aprcl.h &aprcl_config_jacobi_clear"+ p_aprcl_config_jacobi_clear :: FunPtr (Ptr CAPRCLConfig -> IO ())++-- Cyclotomic arithmetic -------------------------------------------------------++-- unity_zpq -------------------------------------------------------------------++data UnityZpq = UnityZpq {-# UNPACK #-} !(ForeignPtr CUnityZpq)+type CUnityZpq = CFlint UnityZpq++instance Storable CUnityZpq where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size unity_zpq}+ {-# INLINE alignment #-}+ alignment _ = #{alignment unity_zpq}+ peek = error "CUnityZpq.peek: not implemented."+ poke = error "CUnityZpq.poke: not implemented."++newUnityZpq q p n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> + withFmpz n $ \n -> + unity_zpq_init x q p n+ addForeignPtrFinalizer p_unity_zpq_clear x+ return $ UnityZpq x++{-# INLINE withUnityZpq #-}+withUnityZpq (UnityZpq x) f = do+ withForeignPtr x $ \px -> f px >>= return . (UnityZpq x,)++-- unity_zp --------------------------------------------------------------------++data UnityZp = UnityZp {-# UNPACK #-} !(ForeignPtr CUnityZp )+data CUnityZp = CUnityZp (Ptr CFmpzModPoly) CULong CULong (Ptr CFmpzModCtx)++instance Storable CUnityZp where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size unity_zp}+ {-# INLINE alignment #-}+ alignment _ = #{alignment unity_zp}+ peek ptr = CUnityZp+ <$> #{peek _unity_zp, poly} ptr+ <*> #{peek _unity_zp, p } ptr+ <*> #{peek _unity_zp, exp } ptr+ <*> #{peek _unity_zp, ctx } ptr+ poke = error "CUnityZp.poke: not implemented."++newUnityZp p exp n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFmpz n $ \n -> + unity_zp_init x p exp n+ addForeignPtrFinalizer p_unity_zp_clear x+ return $ UnityZp x++{-# INLINE withUnityZp #-}+withUnityZp (UnityZp x) f = do+ withForeignPtr x $ \px -> f px >>= return . (UnityZp x,)+ +-- Memory management -----------------------------------------------------------++-- | /unity_zp_init/ /f/ /p/ /exp/ /n/ +--+-- Initializes \(f\) as an element of \(\mathbb{Z}[\zeta_{p^{exp}}]/(n)\).+foreign import ccall "aprcl.h unity_zp_init"+ unity_zp_init :: Ptr CUnityZp -> CULong -> CULong -> Ptr CFmpz -> IO ()++-- | /unity_zp_clear/ /f/ +--+-- Clears the given element. It must be reinitialised in order to be used+-- again.+foreign import ccall "aprcl.h unity_zp_clear"+ unity_zp_clear :: Ptr CUnityZp -> IO ()++foreign import ccall "aprcl.h &unity_zp_clear"+ p_unity_zp_clear :: FunPtr (Ptr CUnityZp -> IO ())++-- | /unity_zp_copy/ /f/ /g/ +--+-- Sets \(f\) to \(g\). \(f\) and \(g\) must be initialized with same \(p\)+-- and \(n\).+foreign import ccall "aprcl.h unity_zp_copy"+ unity_zp_copy :: Ptr CUnityZp -> Ptr CUnityZp -> IO ()++-- | /unity_zp_swap/ /f/ /q/ +--+-- Swaps \(f\) and \(g\). \(f\) and \(g\) must be initialized with same+-- \(p\) and \(n\).+foreign import ccall "aprcl.h unity_zp_swap"+ unity_zp_swap :: Ptr CUnityZp -> Ptr CUnityZp -> IO ()++-- | /unity_zp_set_zero/ /f/ +--+-- Sets \(f\) to zero.+foreign import ccall "aprcl.h unity_zp_set_zero"+ unity_zp_set_zero :: Ptr CUnityZp -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /unity_zp_is_unity/ /f/ +--+-- If \(f = \zeta^h\) returns h; otherwise returns -1.+foreign import ccall "aprcl.h unity_zp_is_unity"+ unity_zp_is_unity :: Ptr CUnityZp -> IO CLong++-- | /unity_zp_equal/ /f/ /g/ +--+-- Returns nonzero if \(f = g\) reduced by the \(p^{exp}\)-th cyclotomic+-- polynomial.+foreign import ccall "aprcl.h unity_zp_equal"+ unity_zp_equal :: Ptr CUnityZp -> Ptr CUnityZp -> IO CInt++-- Output ----------------------------------------------------------------------++foreign import ccall "aprcl.h unity_zp_get_str"+ unity_zp_get_str :: Ptr CUnityZp -> IO CString+ +-- | /unity_zp_print/ /f/ +--+-- Prints the contents of the \(f\).+unity_zp_print :: Ptr CUnityZp -> IO ()+unity_zp_print z = do+ printCStr unity_zp_get_str z+ return ()+ +-- Coefficient management ------------------------------------------------------++-- | /unity_zp_coeff_set_fmpz/ /f/ /ind/ /x/ +foreign import ccall "aprcl.h unity_zp_coeff_set_fmpz"+ unity_zp_coeff_set_fmpz :: Ptr CUnityZp -> CULong -> Ptr CFmpz -> IO ()+-- | /unity_zp_coeff_set_ui/ /f/ /ind/ /x/ +--+-- Sets the coefficient of \(\zeta^{ind}\) to \(x\). \(ind\) must be less+-- than \(p^{exp}\).+foreign import ccall "aprcl.h unity_zp_coeff_set_ui"+ unity_zp_coeff_set_ui :: Ptr CUnityZp -> CULong -> CULong -> IO ()++-- | /unity_zp_coeff_add_fmpz/ /f/ /ind/ /x/ +foreign import ccall "aprcl.h unity_zp_coeff_add_fmpz"+ unity_zp_coeff_add_fmpz :: Ptr CUnityZp -> CULong -> Ptr CFmpz -> IO ()+-- | /unity_zp_coeff_add_ui/ /f/ /ind/ /x/ +--+-- Adds \(x\) to the coefficient of \(\zeta^{ind}\). \(x\) must be less+-- than \(n\). \(ind\) must be less than \(p^{exp}\).+foreign import ccall "aprcl.h unity_zp_coeff_add_ui"+ unity_zp_coeff_add_ui :: Ptr CUnityZp -> CULong -> CULong -> IO ()++-- | /unity_zp_coeff_inc/ /f/ /ind/ +--+-- Increments the coefficient of \(\zeta^{ind}\). \(ind\) must be less than+-- \(p^{exp}\).+foreign import ccall "aprcl.h unity_zp_coeff_inc"+ unity_zp_coeff_inc :: Ptr CUnityZp -> CULong -> IO ()++-- | /unity_zp_coeff_dec/ /f/ /ind/ +--+-- Decrements the coefficient of \(\zeta^{ind}\). \(ind\) must be less than+-- \(p^{exp}\).+foreign import ccall "aprcl.h unity_zp_coeff_dec"+ unity_zp_coeff_dec :: Ptr CUnityZp -> CULong -> IO ()++-- Scalar multiplication -------------------------------------------------------++-- | /unity_zp_mul_scalar_fmpz/ /f/ /g/ /s/ +--+-- Sets \(f\) to \(s \cdot g\). \(f\) and \(g\) must be initialized with+-- same \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_mul_scalar_fmpz"+ unity_zp_mul_scalar_fmpz :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CFmpz -> IO ()++-- | /unity_zp_mul_scalar_ui/ /f/ /g/ /s/ +--+-- Sets \(f\) to \(s \cdot g\). \(f\) and \(g\) must be initialized with+-- same \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_mul_scalar_ui"+ unity_zp_mul_scalar_ui :: Ptr CUnityZp -> Ptr CUnityZp -> CULong -> IO ()++-- Addition and multiplication -------------------------------------------------++-- | /unity_zp_add/ /f/ /g/ /h/ +--+-- Sets \(f\) to \(g + h\). \(f\), \(g\) and \(h\) must be initialized with+-- same \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_add"+ unity_zp_add :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CUnityZp -> IO ()++-- | /unity_zp_mul/ /f/ /g/ /h/ +--+-- Sets \(f\) to \(g \cdot h\). \(f\), \(g\) and \(h\) must be initialized+-- with same \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_mul"+ unity_zp_mul :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CUnityZp -> IO ()++-- | /unity_zp_sqr/ /f/ /g/ +--+-- Sets \(f\) to \(g \cdot g\). \(f\), \(g\) and \(h\) must be initialized+-- with same \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_sqr"+ unity_zp_sqr :: Ptr CUnityZp -> Ptr CUnityZp -> IO ()++-- | /unity_zp_mul_inplace/ /f/ /g/ /h/ /t/ +--+-- Sets \(f\) to \(g \cdot h\). If \(p^{exp} = 3, 4, 5, 7, 8, 9, 11, 16\)+-- special multiplication functions are used. The preallocated array \(t\)+-- of @fmpz_t@ is used for all computations in this case. \(f\), \(g\) and+-- \(h\) must be initialized with same \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_mul_inplace"+ unity_zp_mul_inplace :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CUnityZp -> Ptr (Ptr CFmpz) -> IO ()++-- | /unity_zp_sqr_inplace/ /f/ /g/ /t/ +--+-- Sets \(f\) to \(g \cdot g\). If \(p^{exp} = 3, 4, 5, 7, 8, 9, 11, 16\)+-- special multiplication functions are used. The preallocated array \(t\)+-- of @fmpz_t@ is used for all computations in this case. \(f\) and \(g\)+-- must be initialized with same \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_sqr_inplace"+ unity_zp_sqr_inplace :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr (Ptr CFmpz) -> IO ()++-- Powering functions ----------------------------------------------------------++-- | /unity_zp_pow_fmpz/ /f/ /g/ /pow/ +--+-- Sets \(f\) to \(g^{pow}\). \(f\) and \(g\) must be initialized with same+-- \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_pow_fmpz"+ unity_zp_pow_fmpz :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CFmpz -> IO ()++-- | /unity_zp_pow_ui/ /f/ /g/ /pow/ +--+-- Sets \(f\) to \(g^{pow}\). \(f\) and \(g\) must be initialized with same+-- \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_pow_ui"+ unity_zp_pow_ui :: Ptr CUnityZp -> Ptr CUnityZp -> CULong -> IO ()++-- | /_unity_zp_pow_select_k/ /n/ +--+-- Returns the smallest integer \(k\) satisfying+-- \(\log (n) < (k(k + 1)2^{2k}) / (2^{k + 1} - k - 2) + 1\)+foreign import ccall "aprcl.h _unity_zp_pow_select_k"+ _unity_zp_pow_select_k :: Ptr CFmpz -> IO CULong++-- | /unity_zp_pow_2k_fmpz/ /f/ /g/ /pow/ +--+-- Sets \(f\) to \(g^{pow}\) using the \(2^k\)-ary exponentiation method.+-- \(f\) and \(g\) must be initialized with same \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_pow_2k_fmpz"+ unity_zp_pow_2k_fmpz :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CFmpz -> IO ()++-- | /unity_zp_pow_2k_ui/ /f/ /g/ /pow/ +--+-- Sets \(f\) to \(g^{pow}\) using the \(2^k\)-ary exponentiation method.+-- \(f\) and \(g\) must be initialized with same \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_pow_2k_ui"+ unity_zp_pow_2k_ui :: Ptr CUnityZp -> Ptr CUnityZp -> CULong -> IO ()++-- | /unity_zp_pow_sliding_fmpz/ /f/ /g/ /pow/ +--+-- Sets \(f\) to \(g^{pow}\) using the sliding window exponentiation+-- method. \(f\) and \(g\) must be initialized with same \(p\), \(exp\) and+-- \(n\).+foreign import ccall "aprcl.h unity_zp_pow_sliding_fmpz"+ unity_zp_pow_sliding_fmpz :: Ptr CUnityZp -> Ptr CUnityZp -> Ptr CFmpz -> IO ()++-- Cyclotomic reduction --------------------------------------------------------++-- | /_unity_zp_reduce_cyclotomic_divmod/ /f/ +foreign import ccall "aprcl.h _unity_zp_reduce_cyclotomic_divmod"+ _unity_zp_reduce_cyclotomic_divmod :: Ptr CUnityZp -> IO ()+-- | /_unity_zp_reduce_cyclotomic/ /f/ +--+-- Sets \(f = f \bmod \Phi_{p^{exp}}\). \(\Phi_{p^{exp}}\) is the+-- \(p^{exp}\)-th cyclotomic polynomial. \(g\) must be reduced by+-- \(x^{p^{exp}}-1\) poly. \(f\) and \(g\) must be initialized with same+-- \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h _unity_zp_reduce_cyclotomic"+ _unity_zp_reduce_cyclotomic :: Ptr CUnityZp -> IO ()++-- | /unity_zp_reduce_cyclotomic/ /f/ /g/ +--+-- Sets \(f = g \bmod \Phi_{p^{exp}}\). \(\Phi_{p^{exp}}\) is the+-- \(p^{exp}\)-th cyclotomic polynomial.+foreign import ccall "aprcl.h unity_zp_reduce_cyclotomic"+ unity_zp_reduce_cyclotomic :: Ptr CUnityZp -> Ptr CUnityZp -> IO ()++-- Automorphism and inverse ----------------------------------------------------++-- | /unity_zp_aut/ /f/ /g/ /x/ +--+-- Sets \(f = \sigma_x(g)\), the automorphism \(\sigma_x(\zeta)=\zeta^x\).+-- \(f\) and \(g\) must be initialized with the same \(p\), \(exp\) and+-- \(n\).+foreign import ccall "aprcl.h unity_zp_aut"+ unity_zp_aut :: Ptr CUnityZp -> Ptr CUnityZp -> CULong -> IO ()++-- | /unity_zp_aut_inv/ /f/ /g/ /x/ +--+-- Sets \(f = \sigma_x^{-1}(g)\), so \(\sigma_x(f) = g\). \(g\) must be+-- reduced by \(\Phi_{p^{exp}}\). \(f\) and \(g\) must be initialized with+-- the same \(p\), \(exp\) and \(n\).+foreign import ccall "aprcl.h unity_zp_aut_inv"+ unity_zp_aut_inv :: Ptr CUnityZp -> Ptr CUnityZp -> CULong -> IO ()++-- Jacobi sum ------------------------------------------------------------------++-- Here \(\chi_{p, q}\) is the character defined by chi_{p, q}(g^x) =+-- zeta_{p^k}^x, where \(g\) is a primitive root modulo \(q\).+--+-- | /unity_zp_jacobi_sum_pq/ /f/ /q/ /p/ +--+-- Sets \(f\) to the Jacobi sum \(J(p, q) = j(\chi_{p, q}, \chi_{p, q})\).+foreign import ccall "aprcl.h unity_zp_jacobi_sum_pq"+ unity_zp_jacobi_sum_pq :: Ptr CUnityZp -> CULong -> CULong -> IO ()++-- | /unity_zp_jacobi_sum_2q_one/ /f/ /q/ +--+-- Sets \(f\) to the Jacobi sum+-- \(J_2(q) = j(\chi_{2, q}^{2^{k - 3}}, \chi_{2, q}^{3 \cdot 2^{k - 3}}))^2\).+foreign import ccall "aprcl.h unity_zp_jacobi_sum_2q_one"+ unity_zp_jacobi_sum_2q_one :: Ptr CUnityZp -> CULong -> IO ()++-- | /unity_zp_jacobi_sum_2q_two/ /f/ /q/ +--+-- Sets \(f\) to the Jacobi sum+-- \(J_3(1) = j(\chi_{2, q}, \chi_{2, q}, \chi_{2, q}) =+-- J(2, q) \cdot j(\chi_{2, q}^2, \chi_{2, q})\).+foreign import ccall "aprcl.h unity_zp_jacobi_sum_2q_two"+ unity_zp_jacobi_sum_2q_two :: Ptr CUnityZp -> CULong -> IO ()++-- Extended rings --------------------------------------------------------------++-- | /unity_zpq_init/ /f/ /q/ /p/ /n/ +--+-- Initializes \(f\) as an element of \(\mathbb{Z}[\zeta_q, \zeta_p]/(n)\).+foreign import ccall "aprcl.h unity_zpq_init"+ unity_zpq_init :: Ptr CUnityZpq -> CULong -> CULong -> Ptr CFmpz -> IO ()++-- | /unity_zpq_clear/ /f/ +--+-- Clears the given element. It must be reinitialized in order to be used+-- again.+foreign import ccall "aprcl.h unity_zpq_clear"+ unity_zpq_clear :: Ptr CUnityZpq -> IO ()++foreign import ccall "aprcl.h &unity_zpq_clear"+ p_unity_zpq_clear :: FunPtr (Ptr CUnityZpq -> IO ())++-- | /unity_zpq_copy/ /f/ /g/ +--+-- Sets \(f\) to \(g\). \(f\) and \(g\) must be initialized with same+-- \(p\), \(q\) and \(n\).+foreign import ccall "aprcl.h unity_zpq_copy"+ unity_zpq_copy :: Ptr CUnityZpq ->Ptr CUnityZpq -> IO ()++-- | /unity_zpq_swap/ /f/ /q/ +--+-- Swaps \(f\) and \(g\). \(f\) and \(g\) must be initialized with same+-- \(p\), \(q\) and \(n\).+foreign import ccall "aprcl.h unity_zpq_swap"+ unity_zpq_swap :: Ptr CUnityZpq ->Ptr CUnityZpq -> IO ()++-- | /unity_zpq_equal/ /f/ /g/ +--+-- Returns nonzero if \(f = g\).+foreign import ccall "aprcl.h unity_zpq_equal"+ unity_zpq_equal :: Ptr CUnityZpq ->Ptr CUnityZpq -> IO CInt++-- | /unity_zpq_p_unity/ /f/ +--+-- If \(f = \zeta_p^x\) returns \(x \in [0, p - 1]\); otherwise returns+-- \(p\).+foreign import ccall "aprcl.h unity_zpq_p_unity"+ unity_zpq_p_unity :: Ptr CUnityZpq -> IO CULong++-- | /unity_zpq_is_p_unity/ /f/ +--+-- Returns nonzero if \(f = \zeta_p^x\).+foreign import ccall "aprcl.h unity_zpq_is_p_unity"+ unity_zpq_is_p_unity :: Ptr CUnityZpq -> IO CInt++-- | /unity_zpq_is_p_unity_generator/ /f/ +--+-- Returns nonzero if \(f\) is a generator of the cyclic group+-- \(\langle\zeta_p\rangle\).+foreign import ccall "aprcl.h unity_zpq_is_p_unity_generator"+ unity_zpq_is_p_unity_generator :: Ptr CUnityZpq -> IO CInt++-- | /unity_zpq_coeff_set_fmpz/ /f/ /i/ /j/ /x/ +--+-- Sets the coefficient of \(\zeta_q^i \zeta_p^j\) to \(x\). \(i\) must be+-- less than \(q\) and \(j\) must be less than \(p\).+foreign import ccall "aprcl.h unity_zpq_coeff_set_fmpz"+ unity_zpq_coeff_set_fmpz :: Ptr CUnityZpq -> CULong -> CULong -> Ptr CFmpz -> IO ()++-- | /unity_zpq_coeff_set_ui/ /f/ /i/ /j/ /x/ +--+-- Sets the coefficient of \(\zeta_q^i \zeta_p^j\) to \(x\). \(i\) must be+-- less than \(q\) and \(j\) must be less then \(p\).+foreign import ccall "aprcl.h unity_zpq_coeff_set_ui"+ unity_zpq_coeff_set_ui :: Ptr CUnityZpq -> CULong -> CULong -> CULong -> IO ()++-- | /unity_zpq_coeff_add/ /f/ /i/ /j/ /x/ +--+-- Adds \(x\) to the coefficient of \(\zeta_p^i \zeta_q^j\). \(x\) must be+-- less than \(n\).+foreign import ccall "aprcl.h unity_zpq_coeff_add"+ unity_zpq_coeff_add :: Ptr CUnityZpq -> CULong -> CULong -> Ptr CFmpz -> IO ()++-- | /unity_zpq_add/ /f/ /g/ /h/ +--+-- Sets \(f\) to \(g + h\). \(f\), \(g\) and \(h\) must be initialized with+-- same \(q\), \(p\) and \(n\).+foreign import ccall "aprcl.h unity_zpq_add"+ unity_zpq_add :: Ptr CUnityZpq ->Ptr CUnityZpq ->Ptr CUnityZpq -> IO ()++-- | /unity_zpq_mul/ /f/ /g/ /h/ +--+-- Sets the \(f\) to \(g \cdot h\). \(f\), \(g\) and \(h\) must be+-- initialized with same \(q\), \(p\) and \(n\).+foreign import ccall "aprcl.h unity_zpq_mul"+ unity_zpq_mul :: Ptr CUnityZpq ->Ptr CUnityZpq ->Ptr CUnityZpq -> IO ()++-- | /_unity_zpq_mul_unity_p/ /f/ +--+-- Sets \(f = f \cdot \zeta_p\).+foreign import ccall "aprcl.h _unity_zpq_mul_unity_p"+ _unity_zpq_mul_unity_p :: Ptr CUnityZpq -> IO ()++-- | /unity_zpq_mul_unity_p_pow/ /f/ /g/ /k/ +--+-- Sets \(f\) to \(g \cdot \zeta_p^k\).+foreign import ccall "aprcl.h unity_zpq_mul_unity_p_pow"+ unity_zpq_mul_unity_p_pow :: Ptr CUnityZpq ->Ptr CUnityZpq -> CULong -> IO ()++-- | /unity_zpq_pow/ /f/ /g/ /p/ +--+-- Sets \(f\) to \(g^p\). \(f\) and \(g\) must be initialized with same+-- \(p\), \(q\) and \(n\).+foreign import ccall "aprcl.h unity_zpq_pow"+ unity_zpq_pow :: Ptr CUnityZpq ->Ptr CUnityZpq -> Ptr CFmpz -> IO ()++-- | /unity_zpq_pow_ui/ /f/ /g/ /p/ +--+-- Sets \(f\) to \(g^p\). \(f\) and \(g\) must be initialized with same+-- \(p\), \(q\) and \(n\).+foreign import ccall "aprcl.h unity_zpq_pow_ui"+ unity_zpq_pow_ui :: Ptr CUnityZpq ->Ptr CUnityZpq -> CULong -> IO ()++-- | /unity_zpq_gauss_sum/ /f/ /q/ /p/ +--+-- Sets \(f = \tau(\chi_{p, q})\).+foreign import ccall "aprcl.h unity_zpq_gauss_sum"+ unity_zpq_gauss_sum :: Ptr CUnityZpq -> CULong -> CULong -> IO ()++-- | /unity_zpq_gauss_sum_sigma_pow/ /f/ /q/ /p/ +--+-- Sets \(f = \tau^{\sigma_n}(\chi_{p, q})\).+foreign import ccall "aprcl.h unity_zpq_gauss_sum_sigma_pow"+ unity_zpq_gauss_sum_sigma_pow :: Ptr CUnityZpq -> CULong -> CULong -> IO ()+
+ src/Data/Number/Flint/Acb.hs view
@@ -0,0 +1,33 @@+{-|+module : Data.Number.Flint.Acb+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+++An @Acb@ represents a complex number with error bounds. An @Acb@+consists of a pair of real number balls of type @Arb@,+representing the real and imaginary part with separate error bounds.++An @Acb@ thus represents a +rectangle \([m_1-r_1, m_1+r_1] + [m_2-r_2, m_2+r_2] i\) in the complex plane. +This is used instead of a disk or+square representation (consisting of a complex floating-point midpoint+with a single radius), since it allows implementing many operations more+conveniently by splitting into ball operations on the real and imaginary+parts. It also allows tracking when complex numbers have an exact (for+example exactly zero) real part and an inexact imaginary part, or vice+versa.++The interface for the @Acb@ type is slightly less developed than that+for the @Arb@ type. In many cases, the user can easily perform missing+operations by directly manipulating the real and imaginary parts.++-}++module Data.Number.Flint.Acb (+ module Data.Number.Flint.Acb.FFI+ ) where++import Data.Number.Flint.Acb.FFI+
+ src/Data/Number/Flint/Acb/Acf.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Acb.Acf (+ module Data.Number.Flint.Acb.Acf.FFI+ ) where++import Data.Number.Flint.Acb.Acf.FFI
+ src/Data/Number/Flint/Acb/Acf/FFI.hsc view
@@ -0,0 +1,179 @@+{-|+module : Data.Number.Flint.Acb.Acf.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Acb.Acf.FFI (+ -- * Complex floating-point numbers+ Acf (..)+ , CAcf (..)+ , newAcf+ , withAcf+ , withNewAcf+ -- * Memory management+ , acf_init+ , acf_clear+ , acf_swap+ , acf_allocated_bytes+ -- * Basic manipulation+ , acf_real_ptr+ , acf_imag_ptr+ , acf_set+ , acf_equal+ -- * Arithmetic+ , acf_add+ , acf_sub+ , acf_mul+ -- * Approximate arithmetic+ , acf_approx_inv+ , acf_approx_div+ , acf_approx_sqrt+ , acf_approx_dot+) where++-- Complex floating-point numbers ----------------------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable+import Foreign.Marshal.Alloc+import Foreign.C.Types+import Foreign.C.String++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb.Types++#define ACF_INLINES_C+#include <flint/acf.h>++-- acf_t -----------------------------------------------------------------------++-- | Createst a new `CAcf` structure encapsulated in `Acf`.+newAcf = do+ p <- mallocForeignPtr+ withForeignPtr p acf_init+ addForeignPtrFinalizer p_acf_clear p+ return $ Acf p+ +-- | Access to the C pointer in `Acf` structure.+{-# INLINE withAcf #-}+withAcf (Acf p) f = withForeignPtr p $ fmap (Acf p,) . f++withNewAcf f = do+ x <- newAcf+ withAcf x $ \x -> f x+ +instance Storable CAcf where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size acf_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment acf_t}+ peek = error "CAcf.peek: Not defined"+ poke = error "CAcf.poke: Not defined"++-- Memory management -----------------------------------------------------------++-- | /acf_init/ /x/ +--+-- Initializes the variable /x/ for use, and sets its value to zero.+foreign import ccall "acf.h acf_init"+ acf_init :: Ptr CAcf -> IO ()++-- | /acf_clear/ /x/ +--+-- Clears the variable /x/, freeing or recycling its allocated memory.+foreign import ccall "acf.h acf_clear"+ acf_clear :: Ptr CAcf -> IO ()++foreign import ccall "acf.h &acf_clear"+ p_acf_clear :: FunPtr (Ptr CAcf -> IO ())++-- | /acf_swap/ /z/ /x/ +--+-- Swaps /z/ and /x/ efficiently.+foreign import ccall "acf.h acf_swap"+ acf_swap :: Ptr CAcf -> Ptr CAcf -> IO ()++-- | /acf_allocated_bytes/ /x/ +--+-- Returns the total number of bytes heap-allocated internally by this+-- object. The count excludes the size of the structure itself. Add+-- @sizeof(acf_struct)@ to get the size of the object as a whole.+foreign import ccall "acf.h acf_allocated_bytes"+ acf_allocated_bytes :: Ptr CAcf -> IO CLong++-- Basic manipulation ----------------------------------------------------------++-- | /acf_real_ptr/ /z/ +foreign import ccall "acf.h acf_real_ptr"+ acf_real_ptr :: Ptr CAcf -> IO (Ptr CArf)+ +-- | /acf_imag_ptr/ /z/ +--+-- Returns a pointer to the real or imaginary part of /z/.+foreign import ccall "acf.h acf_imag_ptr"+ acf_imag_ptr :: Ptr CAcf -> IO (Ptr CArf)++-- | /acf_set/ /z/ /x/ +--+-- Sets /z/ to the value /x/.+foreign import ccall "acf.h acf_set"+ acf_set :: Ptr CAcf -> Ptr CAcf -> IO ()++-- | /acf_equal/ /x/ /y/ +--+-- Returns whether /x/ and /y/ are equal.+foreign import ccall "acf.h acf_equal"+ acf_equal :: Ptr CAcf -> Ptr CAcf -> IO CInt++-- Arithmetic ------------------------------------------------------------------++-- | /acf_add/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "acf.h acf_add"+ acf_add :: Ptr CAcf -> Ptr CAcf -> Ptr CAcf -> CLong -> ArfRnd -> IO CInt++-- | /acf_sub/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "acf.h acf_sub"+ acf_sub :: Ptr CAcf -> Ptr CAcf -> Ptr CAcf -> CLong -> ArfRnd -> IO CInt++-- | /acf_mul/ /res/ /x/ /y/ /prec/ /rnd/ +--+-- Sets /res/ to the sum, difference or product of /x/ or /y/, correctly+-- rounding the real and imaginary parts in direction /rnd/. The return+-- flag has the least significant bit set if the real part is inexact, and+-- the second least significant bit set if the imaginary part is inexact.+foreign import ccall "acf.h acf_mul"+ acf_mul :: Ptr CAcf -> Ptr CAcf -> Ptr CAcf -> CLong -> ArfRnd -> IO CInt++-- Approximate arithmetic ------------------------------------------------------++-- The following operations are /not/ correctly rounded. The @rnd@+-- parameter specifies the final direction of rounding, but intermediate+-- roundings are implementation-defined.+--+-- | /acf_approx_inv/ /res/ /x/ /prec/ /rnd/ +foreign import ccall "acf.h acf_approx_inv"+ acf_approx_inv :: Ptr CAcf -> Ptr CAcf -> CLong -> ArfRnd -> IO ()+-- | /acf_approx_div/ /res/ /x/ /y/ /prec/ /rnd/ +foreign import ccall "acf.h acf_approx_div"+ acf_approx_div :: Ptr CAcf -> Ptr CAcf -> Ptr CAcf -> CLong -> ArfRnd -> IO ()+-- | /acf_approx_sqrt/ /res/ /x/ /prec/ /rnd/ +--+-- Computes an approximate inverse, quotient or square root.+foreign import ccall "acf.h acf_approx_sqrt"+ acf_approx_sqrt :: Ptr CAcf -> Ptr CAcf -> CLong -> ArfRnd -> IO ()++-- | /acf_approx_dot/ /res/ /initial/ /subtract/ /x/ /xstep/ /y/ /ystep/ /len/ /prec/ /rnd/ +--+-- Computes an approximate dot product, with the same meaning of the+-- parameters as @arb_dot@.+foreign import ccall "acf.h acf_approx_dot"+ acf_approx_dot :: Ptr CAcf -> Ptr CAcf -> CInt -> Ptr CAcf -> CLong -> Ptr CAcf -> CLong -> CLong -> CLong -> ArfRnd -> IO ()+
+ src/Data/Number/Flint/Acb/Calc.hs view
@@ -0,0 +1,10 @@+{-|+This module provides functions for operations of calculus over the+complex numbers (intended to include root-finding, integration, and so+on). The numerical integration code is described in < [Joh2018a]>.+-}+module Data.Number.Flint.Acb.Calc (+ module Data.Number.Flint.Acb.Calc.FFI+ ) where++import Data.Number.Flint.Acb.Calc.FFI
+ src/Data/Number/Flint/Acb/Calc/FFI.hsc view
@@ -0,0 +1,284 @@+{-|+module : Data.Number.Flint.Acb.Calc.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Acb.Calc.FFI (+ -- * Calculus with complex-valued functions+ -- * Integration function+ CAcbCalcFunc+ -- * Integration+ , acb_calc_integrate+ -- * Options for integration+ , AcbCalcIntegrateOpt ()+ , CAcbCalcIntegrateOpt+ , newAcbCalcIntegrateOpt+ , withAcbCalcIntegrateOpt+ , acb_calc_integrate_opt_init+ -- * Local integration algorithms+ , acb_calc_integrate_gl_auto_deg+ -- * Integration (old)+ , acb_calc_cauchy_bound+ , acb_calc_integrate_taylor+) where ++-- Calculus with complex-valued functions --------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, nullPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Functor ((<&>))++import Data.Number.Flint.Flint++import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.Types++import Data.Number.Flint.Acb+import Data.Number.Flint.Acb.Types++#include <flint/acb_calc.h>++-- Types, macros and constants -------------------------------------------------++data AcbCalcIntegrateOpt =+ AcbCalcIntegrateOpt {-# UNPACK #-} !(ForeignPtr CAcbCalcIntegrateOpt)+data CAcbCalcIntegrateOpt = CAcbCalcIntegrateOpt CLong CLong CLong CInt CInt++instance Storable CAcbCalcIntegrateOpt where+ sizeOf _ = #{size acb_calc_integrate_opt_t}+ alignment _ = #{alignment acb_calc_integrate_opt_t}+ peek ptr = CAcbCalcIntegrateOpt+ <$> #{peek acb_calc_integrate_opt_struct, deg_limit } ptr+ <*> #{peek acb_calc_integrate_opt_struct, eval_limit } ptr+ <*> #{peek acb_calc_integrate_opt_struct, depth_limit} ptr+ <*> #{peek acb_calc_integrate_opt_struct, use_heap } ptr+ <*> #{peek acb_calc_integrate_opt_struct, verbose } ptr+ poke = error "CAcbCalcIntegrateOpt.poke undefined."++newAcbCalcIntegrateOpt = do+ x <- mallocForeignPtr+ withForeignPtr x acb_calc_integrate_opt_init+ return $ AcbCalcIntegrateOpt x++withAcbCalcIntegrateOpt (AcbCalcIntegrateOpt x) f =+ withForeignPtr x $ \xp -> f xp <&> (AcbCalcIntegrateOpt x,)+ +-- acb_calc_func_t -------------------------------------------------------------++type CAcbCalcFunc = Ptr CAcb -> Ptr () -> CLong -> CLong++-- Integration -----------------------------------------------------------------++-- | /acb_calc_integrate/ /res/ /func/ /param/ /a/ /b/ /rel_goal/ /abs_tol/ /options/ /prec/ +--+-- Computes a rigorous enclosure of the integral+-- +-- \[`\]+-- \[I = \int_a^b f(t) dt\]+-- +-- where /f/ is specified by (/func/, /param/), following a straight-line+-- path between the complex numbers /a/ and /b/. For finite results, /a/,+-- /b/ must be finite and /f/ must be bounded on the path of integration.+-- To compute improper integrals, the user should therefore truncate the+-- path of integration manually (or make a regularizing change of+-- variables, if possible). Returns /ARB_CALC_SUCCESS/ if the integration+-- converged to the target accuracy on all subintervals, and returns+-- /ARB_CALC_NO_CONVERGENCE/ otherwise.+-- +-- By default, the integrand /func/ will only be called with /order/ = 0 or+-- /order/ = 1; that is, derivatives are not required.+-- +-- - The integrand will be called with /order/ = 0 to evaluate /f/+-- normally on the integration path (either at a single point or on a+-- subinterval). In this case, /f/ is treated as a pointwise defined+-- function and can have arbitrary discontinuities.+-- - The integrand will be called with /order/ = 1 to evaluate /f/ on a+-- domain surrounding a segment of the integration path for the purpose+-- of bounding the error of a quadrature formula. In this case, /func/+-- must verify that /f/ is holomorphic on this domain (and output a+-- non-finite value if it is not).+-- +-- The integration algorithm combines direct interval enclosures,+-- Gauss-Legendre quadrature where /f/ is holomorphic, and adaptive+-- subdivision. This strategy supports integrands with discontinuities+-- while providing exponential convergence for typical piecewise+-- holomorphic integrands.+-- +-- The following parameters control accuracy:+-- +-- - /rel_goal/ - relative accuracy goal as a number of bits, i.e. target+-- a relative error less than \(\varepsilon_{rel} = 2^{-r}\) where /r/+-- = /rel_goal/ (note the sign: /rel_goal/ should be nonnegative).+-- - /abs_tol/ - absolute accuracy goal as a @mag_t@ describing the error+-- tolerance, i.e. target an absolute error less than+-- \(\varepsilon_{abs}\) = /abs_tol/.+-- - /prec/ - working precision. This is the working precision used to+-- evaluate the integrand and manipulate interval endpoints. As+-- currently implemented, the algorithm does not attempt to adjust the+-- working precision by itself, and adaptive control of the working+-- precision must be handled by the user.+-- +-- For typical usage, set /rel_goal/ = /prec/ and /abs_tol/ =+-- \(2^{-prec}\). It usually only makes sense to have /rel_goal/ between 0+-- and /prec/.+-- +-- The algorithm attempts to achieve an error of+-- \(\max(\varepsilon_{abs}, M \varepsilon_{rel})\) on each subinterval,+-- where /M/ is the magnitude of the integral. These parameters are only+-- guidelines; the cumulative error may be larger than both the prescribed+-- absolute and relative error goals, depending on the number of+-- subdivisions, cancellation between segments of the integral, and+-- numerical errors in the evaluation of the integrand.+-- +-- To compute tiny integrals with high relative accuracy, one should set+-- \(\varepsilon_{abs} \approx M \varepsilon_{rel}\) where /M/ is a known+-- estimate of the magnitude. Setting \(\varepsilon_{abs}\) to 0 is also+-- allowed, forcing use of a relative instead of an absolute tolerance+-- goal. This can be handy for exponentially small or large functions of+-- unknown magnitude. It is recommended to avoid setting+-- \(\varepsilon_{abs}\) very small if possible since the algorithm might+-- need many extra subdivisions to estimate /M/ automatically; if the+-- approximate magnitude can be estimated by some external means (for+-- example if a midpoint-width or endpoint-width estimate is known to be+-- accurate), providing an appropriate+-- \(\varepsilon_{abs} \approx M \varepsilon_{rel}\) will be more+-- efficient.+-- +-- If the integral has very large magnitude, setting the absolute tolerance+-- to a corresponding large value is recommended for best performance, but+-- it is not necessary for convergence since the absolute tolerance is+-- increased automatically during the execution of the algorithm if the+-- partial integrals are found to have larger error.+-- +-- Additional options for the integration can be provided via the /options/+-- parameter (documented below). To use all defaults, /NULL/ can be passed+-- for /options/.+foreign import ccall "acb_calc.h acb_calc_integrate"+ acb_calc_integrate :: Ptr CAcb -> FunPtr CAcbCalcFunc -> Ptr () -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CMag -> Ptr CAcbCalcIntegrateOpt -> CLong -> IO CInt++-- Options for integration -----------------------------------------------------++-- | /acb_calc_integrate_opt_init/ /options/ +--+-- Initializes /options/ for use, setting all fields to 0 indicating+-- default values.+foreign import ccall "acb_calc.h acb_calc_integrate_opt_init"+ acb_calc_integrate_opt_init :: Ptr CAcbCalcIntegrateOpt -> IO ()++-- Local integration algorithms ------------------------------------------------++-- | /acb_calc_integrate_gl_auto_deg/ /res/ /num_eval/ /func/ /param/ /a/ /b/ /tol/ /deg_limit/ /flags/ /prec/ +--+-- Attempts to compute \(I = \int_a^b f(t) dt\) using a single application+-- of Gauss-Legendre quadrature with automatic determination of the+-- quadrature degree so that the error is smaller than /tol/. Returns+-- /ARB_CALC_SUCCESS/ if the integral has been evaluated successfully or+-- /ARB_CALC_NO_CONVERGENCE/ if the tolerance could not be met. The total+-- number of function evaluations is written to /num_eval/.+-- +-- For the interval \([-1,1]\), the error of the /n/-point Gauss-Legendre+-- rule is bounded by+-- +-- \[`\]+-- \[\left| I - \sum_{k=0}^{n-1} w_k f(x_k) \right| \le \frac{64 M}{15 (\rho-1) \rho^{2n-1}}\]+-- +-- if \(f\) is holomorphic with \(|f(z)| \le M\) inside the ellipse /E/+-- with foci \(\pm 1\) and semiaxes \(X\) and \(Y = \sqrt{X^2 - 1}\) such+-- that \(\rho = X + Y\) with \(\rho > 1\) < [Tre2008]>.+-- +-- For an arbitrary interval, we use+-- \(\int_a^b f(t) dt = \int_{-1}^1 g(t) dt\) where+-- \(g(t) = \Delta f(\Delta t + m)\), \(\Delta = \tfrac{1}{2}(b-a)\),+-- \(m = \tfrac{1}{2}(a+b)\). With \(I = [\pm X] + [\pm Y]i\), this means+-- that we evaluate \(\Delta f(\Delta I + m)\) to get the bound \(M\). (An+-- improvement would be to reduce the wrapping effect of rotating the+-- ellipse when the path is not rectilinear).+-- +-- We search for an \(X\) that makes the error small by trying steps+-- \(2^{2^k}\). Larger \(X\) will give smaller \(1 / \rho^{2n-1}\) but+-- larger \(M\). If we try successive larger values of \(k\), we can abort+-- when \(M = \infty\) since this either means that we have hit a+-- singularity or a branch cut or that overestimation in the evaluation of+-- \(f\) is becoming too severe.+foreign import ccall "acb_calc.h acb_calc_integrate_gl_auto_deg"+ acb_calc_integrate_gl_auto_deg :: Ptr CAcb -> Ptr CLong -> FunPtr CAcbCalcFunc -> Ptr () -> Ptr CAcb -> Ptr CAcb -> Ptr CMag -> CLong -> CInt -> CLong -> IO CInt++-- Integration (old) -----------------------------------------------------------++-- | /acb_calc_cauchy_bound/ /bound/ /func/ /param/ /x/ /radius/ /maxdepth/ /prec/ +--+-- Sets /bound/ to a ball containing the value of the integral+-- +-- \[`\]+-- \[C(x,r) = \frac{1}{2 \pi r} \oint_{|z-x| = r} |f(z)| dz+-- = \int_0^1 |f(x+re^{2\pi i t})| dt\]+-- +-- where /f/ is specified by (/func/, /param/) and /r/ is given by+-- /radius/. The integral is computed using a simple step sum. The+-- integration range is subdivided until the order of magnitude of /b/ can+-- be determined (i.e. its error bound is smaller than its midpoint), or+-- until the step length has been cut in half /maxdepth/ times. This+-- function is currently implemented completely naively, and repeatedly+-- subdivides the whole integration range instead of performing adaptive+-- subdivisions.+foreign import ccall "acb_calc.h acb_calc_cauchy_bound"+ acb_calc_cauchy_bound :: Ptr CArb -> FunPtr CAcbCalcFunc -> Ptr () -> Ptr CAcb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /acb_calc_integrate_taylor/ /res/ /func/ /param/ /a/ /b/ /inner_radius/ /outer_radius/ /accuracy_goal/ /prec/ +--+-- Computes the integral+-- +-- \[`\]+-- \[I = \int_a^b f(t) dt\]+-- +-- where /f/ is specified by (/func/, /param/), following a straight-line+-- path between the complex numbers /a/ and /b/ which both must be finite.+-- +-- The integral is approximated by piecewise centered Taylor polynomials.+-- Rigorous truncation error bounds are calculated using the Cauchy+-- integral formula. More precisely, if the Taylor series of /f/ centered+-- at the point /m/ is \(f(m+x) = \sum_{n=0}^{\infty} a_n x^n\), then+-- +-- \[`\]+-- \[\int f(m+x) = \left( \sum_{n=0}^{N-1} a_n \frac{x^{n+1}}{n+1} \right)+-- + \left( \sum_{n=N}^{\infty} a_n \frac{x^{n+1}}{n+1} \right).\]+-- +-- For sufficiently small /x/, the second series converges and its absolute+-- value is bounded by+-- +-- \[`\]+-- \[\sum_{n=N}^{\infty} \frac{C(m,R)}{R^n} \frac{|x|^{n+1}}{N+1}+-- = \frac{C(m,R) R x}{(R-x)(N+1)} \left( \frac{x}{R} \right)^N.\]+-- +-- It is required that any singularities of /f/ are isolated from the path+-- of integration by a distance strictly greater than the positive value+-- /outer_radius/ (which is the integration radius used for the Cauchy+-- bound). Taylor series step lengths are chosen so as not to exceed+-- /inner_radius/, which must be strictly smaller than /outer_radius/ for+-- convergence. A smaller /inner_radius/ gives more rapid convergence of+-- each Taylor series but means that more series might have to be used. A+-- reasonable choice might be to set /inner_radius/ to half the value of+-- /outer_radius/, giving roughly one accurate bit per term.+-- +-- The truncation point of each Taylor series is chosen so that the+-- absolute truncation error is roughly \(2^{-p}\) where /p/ is given by+-- /accuracy_goal/ (in the future, this might change to a relative+-- accuracy). Arithmetic operations and function evaluations are performed+-- at a precision of /prec/ bits. Note that due to accumulation of+-- numerical errors, both values may have to be set higher (and the+-- endpoints may have to be computed more accurately) to achieve a desired+-- accuracy.+-- +-- This function chooses the evaluation points uniformly rather than+-- implementing adaptive subdivision.+foreign import ccall "acb_calc.h acb_calc_integrate_taylor"+ acb_calc_integrate_taylor :: Ptr CAcb -> FunPtr CAcbCalcFunc -> Ptr () -> Ptr CAcb -> Ptr CAcb -> Ptr CArf -> Ptr CArf -> CLong -> CLong -> IO CInt+
+ src/Data/Number/Flint/Acb/ComplexField.hs view
@@ -0,0 +1,286 @@+module Data.Number.Flint.Acb.ComplexField (+ CF(..)+, RF'(..)+, Special (..)+, realPart+, imagPart+-- * Polar form+, mkPolar+, cis+, polar+, magnitude+, phase+-- * Conjugate+, conjugate+) where++import GHC.TypeLits+import Data.Proxy+import Data.Ratio++import System.IO.Unsafe+import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Instances+import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.RealField++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb+import Data.Number.Flint.Acb.Acf+import Data.Number.Flint.Acb.Types+import Data.Number.Flint.Acb.Hypgeom+import Data.Number.Flint.Acb.Modular+import Data.Number.Flint.Acb.Elliptic++import Data.Number.Flint.Support.D.Interval++newtype CF (n :: Nat) = CF Acb++realPart :: forall n. KnownNat n => (CF n) -> (RF n)+realPart (CF z) = unsafePerformIO $ do+ res <- newArb+ withArb res $ \res -> do + withAcb z $ \z -> do+ acb_get_real res z+ return $ RF res++imagPart :: forall n. KnownNat n => (CF n) -> (RF n)+imagPart (CF z) = unsafePerformIO $ do+ res <- newArb+ withArb res $ \res -> do+ withAcb z $ \z -> do+ acb_get_imag res z+ return $ RF res++mkPolar :: forall n. KnownNat n => (RF n) -> (RF n) -> (CF n)+mkPolar (RF r) (RF theta) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ res <- newAcb+ withAcb res $ \res -> do + withArb r $ \r -> do+ withArb theta $ \theta -> do+ withNewArb $ \x -> do+ withNewArb $ \y -> do+ arb_sin_cos y x theta prec+ arb_mul x x r prec+ arb_mul y y r prec+ acb_set_arb_arb res x y+ return $ CF res++cis :: forall n. KnownNat n => (RF n) -> (CF n)+cis (RF theta) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ res <- newAcb+ withAcb res $ \res -> do + withArb theta $ \theta -> do+ withNewArb $ \x -> do+ withNewArb $ \y -> do+ arb_sin_cos y x theta prec+ acb_set_arb_arb res x y+ return $ CF res++polar :: forall n. KnownNat n => (CF n) -> (RF n, RF n)+polar z = (magnitude z, phase z)++magnitude :: forall n. KnownNat n => (CF n) -> (RF n)+magnitude (CF z) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ res <- newArb+ withArb res $ \res -> do+ withAcb z $ \z -> do+ acb_abs res z prec+ return $ RF res++phase :: forall n. KnownNat n => (CF n) -> (RF n)+phase (CF z) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ res <- newArb+ withArb res $ \res -> do+ withAcb z $ \z -> do+ acb_arg res z prec+ return $ RF res++conjugate :: forall n. KnownNat n => (CF n) -> (CF n)+conjugate (CF z) = unsafePerformIO $ do+ res <- newAcb+ withAcb res $ \res -> do+ withAcb z $ \z -> do+ acb_conj res z+ return $ CF res++instance forall n. KnownNat n => Eq (CF n) where+ {-# INLINE (==) #-}+ (==) = liftCmp acb_eq+ {-# INLINE (/=) #-}+ (/=) = liftCmp acb_ne++instance forall n. KnownNat n => Ord (CF n) where+ compare = undefined+ +instance forall n. KnownNat n => Num (CF n) where+ {-# INLINE (+) #-}+ (+) = lift2 acb_add+ {-# INLINE (-) #-}+ (-) = lift2 acb_sub+ {-# INLINE (*) #-}+ (*) = lift2 acb_mul+ {-# INLINE negate #-}+ negate = lift1 acb_neg+ abs = undefined+ {-# INLINE fromInteger #-}+ fromInteger x = unsafePerformIO $ do+ result <- newAcb+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ withAcb result $ \result -> do+ acb_set_ui result (fromIntegral x)+ return (CF result)+ signum = undefined+ +instance forall n. KnownNat n => Fractional (CF n) where+ {-# INLINE (/) #-}+ (/) = lift2 acb_div+ fromRational x = p / q where+ p = fromIntegral (numerator x) :: CF n+ q = fromIntegral (denominator x) :: CF n++instance forall n. KnownNat n => Real (CF n) where+ toRational = undefined+ +instance forall n. KnownNat n => RealFrac (CF n) where+ properFraction = undefined+ +instance forall n. KnownNat n => Floating (CF n) where+ pi = liftConstant arb_const_pi+ exp = liftF1 acb_exp+ log = liftF1 acb_log+ sqrt = liftF1 acb_sqrt+ sin = liftF1 acb_sin+ cos = liftF1 acb_cos+ tan = liftF1 acb_tan+ asin = liftF1 acb_asin+ acos = liftF1 acb_acos+ atan = liftF1 acb_atan+ sinh = liftF1 acb_sinh+ cosh = liftF1 acb_cosh+ tanh = liftF1 acb_tanh+ asinh = liftF1 acb_asinh+ acosh = liftF1 acb_acosh+ atanh = liftF1 acb_atanh+ +instance forall n. KnownNat n => Show (CF n) where+ show (CF x) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ digits = floor (fromIntegral prec * logBase 10 2)+ (_, cstr) <- withAcb x $ \p ->+ acb_get_strn p (fromIntegral digits) arb_str_no_radius+ str <- peekCString cstr+ return str+ +------------------------------------------------------------------------++instance forall n. KnownNat n => Special (CF n) where+ gamma = liftF1 acb_gamma+ digamma = liftF1 acb_digamma+ lgamma = liftF1 acb_hypgeom_lgamma+ zeta = liftF1 acb_zeta+ erf = liftF1 acb_hypgeom_erf+ airy (CF x) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ ai <- newAcb+ ai' <- newAcb+ bi <- newAcb+ bi' <- newAcb+ withAcb x $ \x -> + withAcb ai $ \ai -> + withAcb ai' $ \ai' ->+ withAcb bi $ \bi ->+ withAcb bi' $ \bi' ->+ acb_hypgeom_airy ai ai' bi bi' x prec+ return $ (CF ai, CF ai', CF bi, CF bi')+ airyZeros = undefined+ besselJ = lift2 acb_hypgeom_bessel_j+ besselY = lift2 acb_hypgeom_bessel_y+ besselI = lift2 acb_hypgeom_bessel_i+ besselK = lift2 acb_hypgeom_bessel_k+ modj = liftF1 acb_modular_j+ modjq = undefined+ modeta = liftF1 acb_modular_eta+ modetaq = undefined+ modlambda = liftF1 acb_modular_lambda+ modlambdaq = undefined+ ellipp = lift2 acb_elliptic_p+ ellipzeta = lift2 acb_elliptic_zeta+ ellipsigma = lift2 acb_elliptic_sigma+ barnesg = liftF1 acb_barnes_g+ agm = lift2 acb_agm+ fresnels = undefined+ fresnelc = undefined+ +instance forall n. KnownNat n => RF' (CF n) where+ euler = liftConstant arb_const_euler+ glaisher = liftConstant arb_const_glaisher+ catalan = liftConstant arb_const_catalan+ khinchin = liftConstant arb_const_khinchin+ polylog = lift2 acb_polylog+ midPoint = lift1 acb_get_mid+ +-- lifting -------------------------------------------------------------++type Binary = Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()+type Cmp = Ptr CAcb -> Ptr CAcb -> IO CInt+type Function = Ptr CAcb -> Ptr CAcb -> IO ()++lift2 :: forall n. KnownNat n => Binary -> CF n -> CF n -> CF n+lift2 f (CF a) (CF b) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ c <- newAcb+ withAcb a $ \a ->+ withAcb b $ \b ->+ withAcb c $ \c ->+ f c a b (CLong prec)+ return (CF c)++lift1 :: forall n. KnownNat n => Function -> CF n -> CF n+lift1 f (CF x) = unsafePerformIO $ do+ y <- newAcb+ withAcb x $ \x -> withAcb y $ \y -> f y x+ return (CF y)+ +lift0 f x = CF $ unsafePerformIO $ fst <$> withNewAcb (`f` x)+ +liftF1 :: forall n. KnownNat n =>+ (Ptr CAcb -> Ptr CAcb -> CLong -> IO ()) -> CF n -> CF n+liftF1 f (CF x) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ y <- newAcb+ withAcb x $ \x -> withAcb y $ \y -> f y x (CLong prec)+ return (CF y)++liftCmp :: forall n. KnownNat n => Cmp -> CF n -> CF n -> Bool+liftCmp f (CF x) (CF y) = unsafePerformIO $ do+ (_, (_, cmp)) <- withAcb x $ \x -> withAcb y $ \y -> f x y+ return (cmp == 1)++liftProp :: forall n. KnownNat n => (Ptr CAcb -> IO CInt) -> CF n -> Bool+liftProp f (CF x) = unsafePerformIO $ do+ (_, prop) <- withAcb x $ \x -> f x+ return (prop == 1)++liftConstant :: forall n. KnownNat n => (Ptr CArb -> CLong -> IO ()) -> CF n+liftConstant f = CF $ fst $ snd $ unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ tmp <- newArb+ withArb tmp $ \tmp -> do+ f tmp prec+ withNewAcb (`acb_set_arb` tmp)+
+ src/Data/Number/Flint/Acb/DFT.hs view
@@ -0,0 +1,24 @@+{- |+__Warning__: the interfaces in this module are experimental and may change+without notice.++All functions support aliasing.++Let /G/ be a finite abelian group, and \(\chi\) a character of /G/. For+any map \(f:G\to\mathbb C\), the discrete fourier +transform \(\hat f:\hat G\to \mathbb C\) is defined by++\[\hat f(\chi) = \sum_{x\in G}\overline{\chi(x)}f(x)\]++Note that by the inversion formula++\[\widehat{\hat{f}}\left(\chi\right) = \# G \times f\left(\chi^{{}-1}\right)\]++it is straightforward to recover \(f\) from its DFT \(\hat f\).+-}++module Data.Number.Flint.Acb.DFT (+ module Data.Number.Flint.Acb.DFT.FFI+ ) where++import Data.Number.Flint.Acb.DFT.FFI
+ src/Data/Number/Flint/Acb/DFT/FFI.hsc view
@@ -0,0 +1,619 @@+{-|+module : Data.Number.Flint.Acb.DFT.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Acb.DFT.FFI (+ -- * Discrete Fourier transform+ -- DFTAlgorithms+ -- * Main DFT functions+ -- | If \(G=\mathbb Z/n\mathbb Z\), we compute the DFT according to the usual+ -- convention+ --+ -- \[w_x = \sum_{y\bmod n} v_y e^{-\frac{2i \pi}nxy}\]+ --+ acb_dft+ , acb_dft_inverse+ -- * DFT Precomputation+ , AcbDftPre (..)+ , CAcbDftPre (..)+ , newAcbDftPre+ , withAcbDftPre+ , withNewAcbDftPre+ -- *+ , acb_dft_precomp_init+ , acb_dft_precomp_clear+ , acb_dft_precomp+ , acb_dft_inverse_precomp+ -- -- * DFT on products+ -- -- $Products+ -- , AcbDftProd (..)+ -- , CAcbDftProd (..)+ -- , newAcbDftProd+ -- , withAcbDftProd+ -- , withNewAcbDftProd+ -- -- *+ -- -- , acb_dirichlet_dft_prod+ -- , acb_dft_prod_init+ -- , acb_dft_prod_clear+ -- , acb_dirichlet_dft_prod_precomp+ -- * Convolution+ , acb_dft_convol_naive+ , acb_dft_convol_rad2+ , acb_dft_convol+ -- * FFT algorithms+ -- -- * Naive algorithm+ -- , AcbDftNaive (..)+ -- , CAcbDftNaive (..)+ -- , newAcbDftNaive+ -- , withAcbDftNaive+ -- , withNewAcbDftNaive+ -- -- *+ -- , acb_dft_naive+ -- , acb_dft_naive_init+ -- , acb_dft_naive_clear+ -- , acb_dft_naive_precomp+ -- * CRT decomposition+ , AcbDftCrt (..)+ , CAcbDftCrt (..)+ , newAcbDftCrt+ , withAcbDftCrt+ , withNewAcbDftCrt+ -- *+ , acb_dft_crt+ , acb_dft_crt_init+ , acb_dft_crt_clear+ , acb_dft_crt_precomp+ -- -- * Cooley-Tukey decomposition+ -- , AcbDftCyc (..)+ -- , CAcbDftCyc (..)+ -- , newAcbDftCyc+ -- , withAcbDftCyc+ -- , withNewAcbDftCyc+ -- -- *+ -- , acb_dft_cyc+ -- , acb_dft_cyc_init+ -- , acb_dft_cyc_clear+ -- , acb_dft_cyc_precomp+ -- * Radix 2 decomposition+ -- , AcbDftRad2 (..)+ -- , CAcbDftRad2 (..)+ -- , newAcbDftRad2+ -- , withAcbDftRad2+ -- , withNewAcbDftRad2+ -- -- *+ -- , acb_dft_rad2+ -- , acb_dft_inverse_rad2+ -- , acb_dft_rad2_init+ -- , acb_dft_rad2_clear+ -- , acb_dft_rad2_precomp+ -- * Bluestein transform+ -- , AcbDftBluestein (..)+ -- , CAcbDftBluestein (..)+ -- , newAcbDftBluestein+ -- , withAcbDftBluestein+ -- , withNewAcbDftBluestein+ -- -- *+ -- , acb_dft_bluestein+ -- , acb_dft_bluestein_init+ -- , acb_dft_bluestein_clear+ -- , acb_dft_bluestein_precomp+) where++-- Discrete Fourier transform --------------------------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Alloc (free)+import Foreign.Marshal.Array (advancePtr)++import Data.Typeable++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb.Types++#include <flint/acb.h>+#include <flint/acb_dft.h>+ +-- Main DFT functions ----------------------------------------------------------+++-- | /acb_dft/ /w/ /v/ /n/ /prec/ +--+-- Set /w/ to the DFT of /v/ of length /len/, using an automatic choice of+-- algorithm.+foreign import ccall "acb_dft.h acb_dft"+ acb_dft :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_dft_inverse/ /w/ /v/ /n/ /prec/ +--+-- Compute the inverse DFT of /v/ into /w/.+foreign import ccall "acb_dft.h acb_dft_inverse"+ acb_dft_inverse :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- acb_dft_pre -----------------------------------------------------------------++data AcbDftPre = AcbDftPre {-# UNPACK #-} !(ForeignPtr CAcbDftPre)+type CAcbDftPre = CFlint AcbDftPre++instance Storable CAcbDftPre where+ sizeOf _ = #{size acb_dft_pre_t}+ alignment _ = #{alignment acb_dft_pre_t}+ peek = undefined+ poke = undefined++newAcbDftPre len prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ acb_dft_precomp_init x len prec+ addForeignPtrFinalizer p_acb_dft_precomp_clear x+ return $ AcbDftPre x++withAcbDftPre (AcbDftPre p) f = do+ withForeignPtr p $ \fp -> (AcbDftPre p,) <$> f fp++withNewAcbDftPre len prec f = do+ x <- newAcbDftPre len prec+ withAcbDftPre x f++--------------------------------------------------------------------------------++-- | /acb_dft_precomp_init/ /pre/ /len/ /prec/ +--+-- Initializes the fast DFT scheme of length /len/, using an automatic+-- choice of algorithms depending on the factorization of /len/.+-- +-- The length /len/ is stored as /pre->n/.+--+-- If several computations are to be done on the same group, the FFT scheme+-- should be reused.+--+foreign import ccall "acb_dft.h acb_dft_precomp_init"+ acb_dft_precomp_init :: Ptr CAcbDftPre -> CLong -> CLong -> IO ()++-- | /acb_dft_precomp_clear/ /pre/ +--+-- Clears /pre/.+foreign import ccall "acb_dft.h acb_dft_precomp_clear"+ acb_dft_precomp_clear :: Ptr CAcbDftPre -> IO ()++foreign import ccall "acb_dft.h &acb_dft_precomp_clear"+ p_acb_dft_precomp_clear :: FunPtr (Ptr CAcbDftPre -> IO ())++-- | /acb_dft_precomp/ /w/ /v/ /pre/ /prec/ +--+-- Computes the DFT of the sequence /v/ into /w/ by applying the+-- precomputed scheme /pre/. Both /v/ and /w/ must have length /pre->n/.+foreign import ccall "acb_dft.h acb_dft_precomp"+ acb_dft_precomp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcbDftPre -> CLong -> IO ()++-- | /acb_dft_inverse_precomp/ /w/ /v/ /pre/ /prec/ +--+-- Compute the inverse DFT of /v/ into /w/.+foreign import ccall "acb_dft.h acb_dft_inverse_precomp"+ acb_dft_inverse_precomp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcbDftPre -> CLong -> IO ()++-- -- DFT on products -------------------------------------------------------------++-- data AcbDftProd = AcbDftProd {-# UNPACK #-} !(ForeignPtr CAcbDftProd)+-- type CAcbDftProd = CFlint AcbDftProd++-- instance Storable CAcbDftProd where+-- sizeOf _ = #{size acb_dft_prod_t}+-- alignment _ = #{alignment acb_dft_prod_t}+-- peek = undefined+-- poke = undefined++-- newAcbDftProd cyc num prec = do+-- x <- mallocForeignPtr+-- withForeignPtr x $ \x -> do+-- acb_dft_prod_init x cyc num prec+-- addForeignPtrFinalizer p_acb_dft_prod_clear x+-- return $ AcbDftProd x++-- withAcbDftProd (AcbDftProd p) f = do+-- withForeignPtr p $ \fp -> (AcbDftProd p,) <$> f fp++-- withNewAcbDftProd cyc num prec f = do+-- x <- newAcbDftProd cyc num prec+-- withAcbDftProd x f++-- --------------------------------------------------------------------------------++-- -- $Products+-- --+-- -- A finite abelian group is isomorphic to a product of cyclic components+-- --+-- -- \[G = \bigoplus_{i=1}^r \mathbb Z/n_i\mathbb Z\]+-- --+-- -- Characters are product of component characters and the DFT reads+-- --+-- -- \[\hat f(x_1,\dots x_r) = \sum_{y_1\dots y_r} f(y_1,\dots y_r)+-- -- e^{-2i \pi \sum\frac{x_i y_i}{n_i}}\]+-- --+-- -- We assume that \(f\) is given by a vector of length \(\prod n_i\)+-- -- corresponding to a lexicographic ordering of the values+-- -- \(y_1,\dots y_r\), and the computation returns the same indexing for+-- -- values of \(\hat f\).+-- --++-- -- -- | /acb_dirichlet_dft_prod/ /w/ /v/ /cyc/ /num/ /prec/ +-- -- --+-- -- -- Computes the DFT on the group product of /num/ cyclic components of+-- -- -- sizes /cyc/. Assume the entries of /v/ are indexed according to+-- -- -- lexicographic ordering of the cyclic components.+-- -- foreign import ccall "acb_dft.h acb_dirichlet_dft_prod"+-- -- acb_dirichlet_dft_prod :: Ptr CAcb -> Ptr CAcb -> Ptr CLong -> CLong -> CLong -> IO ()++-- -- | /acb_dft_prod_init/ /t/ /cyc/ /num/ /prec/ +-- --+-- -- Stores in /t/ a DFT scheme for the product of /num/ cyclic components+-- -- whose sizes are given in the array /cyc/.+-- foreign import ccall "acb_dft.h acb_dft_prod_init"+-- acb_dft_prod_init :: Ptr CAcbDftProd -> Ptr CLong -> CLong -> CLong -> IO ()++-- -- | /acb_dft_prod_clear/ /t/ +-- --+-- -- Clears /t/.+-- foreign import ccall "acb_dft.h acb_dft_prod_clear"+-- acb_dft_prod_clear :: Ptr CAcbDftProd -> IO ()++-- foreign import ccall "acb_dft.h &acb_dft_prod_clear"+-- p_acb_dft_prod_clear :: FunPtr (Ptr CAcbDftProd -> IO ())++-- -- | /acb_dirichlet_dft_prod_precomp/ /w/ /v/ /prod/ /prec/ +-- --+-- -- Sets /w/ to the DFT of /v/. Assume the entries are lexicographically+-- -- ordered according to the product of cyclic groups initialized in /t/.+-- foreign import ccall "acb_dft.h acb_dirichlet_dft_prod_precomp"+-- acb_dirichlet_dft_prod_precomp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcbDftProd -> CLong -> IO ()++-- Convolution -----------------------------------------------------------------++-- For functions \(f\) and \(g\) on \(G\) we consider the convolution+--+-- \[(f \star g)(x) = \sum_{y\in G} f(x-y)g(y)\]+--+-- | /acb_dft_convol_naive/ /w/ /f/ /g/ /len/ /prec/ +--+foreign import ccall "acb_dft.h acb_dft_convol_naive"+ acb_dft_convol_naive :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_dft_convol_rad2/ /w/ /f/ /g/ /len/ /prec/ +--+foreign import ccall "acb_dft.h acb_dft_convol_rad2"+ acb_dft_convol_rad2 :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_dft_convol/ /w/ /f/ /g/ /len/ /prec/ +--+-- Sets /w/ to the convolution of /f/ and /g/ of length /len/.+-- +-- The /naive/ version simply uses the definition.+-- +-- The /rad2/ version embeds the sequence into a power of 2 length and uses+-- the formula+-- +-- \[\widehat{f \star g}(\chi) = \hat f(\chi)\hat g(\chi)\]+-- +-- to compute it using three radix 2 FFT.+-- +-- The default version uses radix 2 FFT unless /len/ is a product of small+-- primes where a non padded FFT is faster.+foreign import ccall "acb_dft.h acb_dft_convol"+ acb_dft_convol :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- -- FFT algorithms --------------------------------------------------------------++-- -- $FFTAlgorithms+-- --+-- -- Fast Fourier transform techniques allow to compute efficiently all+-- -- values \(\hat f(\chi)\) by reusing common computations.+-- --+-- -- Specifically, if \(H\triangleleft G\) is a subgroup of size \(M\) and+-- -- index [G:H]=m, then writing \(f_x(h)=f(xh)\) the translate of \(f\) by+-- -- representatives x of \(G/H\), one has a decomposition+-- --+-- -- \[\hat f(\chi) = \sum_{x\in G/H} \overline{\chi(x)} \hat{f_x}(\chi_{H})\]+-- --+-- -- so that the DFT on \(G\) can be computed using \(m\) DFT on \(H\) (of+-- -- appropriate translates of \(f\)), then \(M\) DFT on \(G/H\), one for+-- -- each restriction \(\chi_{H}\).+-- --+-- -- This decomposition can be done recursively.+-- --++-- -- Naive algorithm -------------------------------------------------------------++-- data AcbDftNaive = AcbDftNaive {-# UNPACK #-} !(ForeignPtr CAcbDftNaive)+-- type CAcbDftNaive = CFlint AcbDftNaive++-- instance Storable CAcbDftNaive where+-- sizeOf _ = #{size acb_dft_naive_t}+-- alignment _ = #{alignment acb_dft_naive_t}+-- peek = undefined+-- poke = undefined++-- newAcbDftNaive len prec = do+-- x <- mallocForeignPtr+-- withForeignPtr x $ \x -> do+-- acb_dft_naive_init x len prec+-- addForeignPtrFinalizer p_acb_dft_naive_clear x+-- return $ AcbDftNaive x++-- withAcbDftNaive (AcbDftNaive p) f = do+-- withForeignPtr p $ \fp -> (AcbDftNaive p,) <$> f fp++-- withNewAcbDftNaive len prec f = do+-- x <- newAcbDftNaive len prec+-- withAcbDftNaive x f++-- --------------------------------------------------------------------------------++-- -- | /acb_dft_naive/ /w/ /v/ /n/ /prec/ +-- --+-- -- Computes the DFT of /v/ into /w/, where /v/ and /w/ have size /n/, using+-- -- the naive \(O(n^2)\) algorithm.+-- foreign import ccall "acb_dft.h acb_dft_naive"+-- acb_dft_naive :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- -- | /acb_dft_naive_init/ /t/ /len/ /prec/ +-- --+-- foreign import ccall "acb_dft.h acb_dft_naive_init"+-- acb_dft_naive_init :: Ptr CAcbDftNaive -> CLong -> CLong -> IO ()++-- -- | /acb_dft_naive_clear/ /t/ +-- --+-- -- Stores a table of roots of unity in /t/. The length /len/ is stored as+-- -- /t->n/.+-- foreign import ccall "acb_dft.h acb_dft_naive_clear"+-- acb_dft_naive_clear :: Ptr CAcbDftNaive -> IO ()++-- foreign import ccall "acb_dft.h &acb_dft_naive_clear"+-- p_acb_dft_naive_clear :: FunPtr (Ptr CAcbDftNaive -> IO ())++-- -- | /acb_dft_naive_precomp/ /w/ /v/ /t/ /prec/ +-- --+-- -- Sets /w/ to the DFT of /v/ of size /t->n/, using the naive algorithm+-- -- data /t/.+-- foreign import ccall "acb_dft.h acb_dft_naive_precomp"+-- acb_dft_naive_precomp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcbDftNaive -> CLong -> IO ()++-- CRT decomposition -----------------------------------------------------------++data AcbDftCrt = AcbDftCrt {-# UNPACK #-} !(ForeignPtr CAcbDftCrt)+type CAcbDftCrt = CFlint AcbDftCrt++instance Storable CAcbDftCrt where+ sizeOf _ = #{size acb_dft_crt_t}+ alignment _ = #{alignment acb_dft_crt_t}+ peek = undefined+ poke = undefined++newAcbDftCrt len prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ acb_dft_crt_init x len prec+ addForeignPtrFinalizer p_acb_dft_crt_clear x+ return $ AcbDftCrt x++withAcbDftCrt (AcbDftCrt p) f = do+ withForeignPtr p $ \fp -> (AcbDftCrt p,) <$> f fp++withNewAcbDftCrt len prec f = do+ x <- newAcbDftCrt len prec+ withAcbDftCrt x f++--------------------------------------------------------------------------------++-- | /acb_dft_crt/ /w/ /v/ /n/ /prec/ +--+-- Computes the DFT of /v/ into /w/, where /v/ and /w/ have size /len/,+-- using CRT to express \(\mathbb Z/n\mathbb Z\) as a product of cyclic+-- groups.+foreign import ccall "acb_dft.h acb_dft_crt"+ acb_dft_crt :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_dft_crt_init/ /t/ /len/ /prec/ +--+foreign import ccall "acb_dft.h acb_dft_crt_init"+ acb_dft_crt_init :: Ptr CAcbDftCrt -> CLong -> CLong -> IO ()++-- | /acb_dft_crt_clear/ /t/ +--+-- Initialize a CRT decomposition of \(\mathbb Z/n\mathbb Z\) as a direct+-- product of cyclic groups. The length /len/ is stored as /t->n/.+foreign import ccall "acb_dft.h acb_dft_crt_clear"+ acb_dft_crt_clear :: Ptr CAcbDftCrt -> IO ()++foreign import ccall "acb_dft.h &acb_dft_crt_clear"+ p_acb_dft_crt_clear :: FunPtr (Ptr CAcbDftCrt -> IO ())++-- | /acb_dft_crt_precomp/ /w/ /v/ /t/ /prec/ +--+-- Sets /w/ to the DFT of /v/ of size /t->n/, using the CRT decomposition+-- scheme /t/.+foreign import ccall "acb_dft.h acb_dft_crt_precomp"+ acb_dft_crt_precomp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcbDftCrt -> CLong -> IO ()++-- -- Cooley-Tukey decomposition --------------------------------------------------++-- data AcbDftCyc = AcbDftCyc {-# UNPACK #-} !(ForeignPtr CAcbDftCyc)+-- type CAcbDftCyc = CFlint AcbDftCyc++-- instance Storable CAcbDftCyc where+-- sizeOf _ = #{size acb_dft_cyc_t}+-- alignment _ = #{alignment acb_dft_cyc_t}+-- peek = undefined+-- poke = undefined++-- newAcbDftCyc len prec = do+-- x <- mallocForeignPtr+-- withForeignPtr x $ \x -> do+-- acb_dft_cyc_init x len prec+-- addForeignPtrFinalizer p_acb_dft_cyc_clear x+-- return $ AcbDftCyc x++-- withAcbDftCyc (AcbDftCyc p) f = do+-- withForeignPtr p $ \fp -> (AcbDftCyc p,) <$> f fp++-- withNewAcbDftCyc len prec f = do+-- x <- newAcbDftCyc len prec+-- withAcbDftCyc x f++-- --------------------------------------------------------------------------------++-- -- | /acb_dft_cyc/ /w/ /v/ /n/ /prec/ +-- --+-- -- Computes the DFT of /v/ into /w/, where /v/ and /w/ have size /n/, using+-- -- each prime factor of \(m\) of \(n\) to decompose with the subgroup+-- -- \(H=m\mathbb Z/n\mathbb Z\).+-- foreign import ccall "acb_dft.h acb_dft_cyc"+-- acb_dft_cyc :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- -- | /acb_dft_cyc_init/ /t/ /len/ /prec/ +-- --+-- foreign import ccall "acb_dft.h acb_dft_cyc_init"+-- acb_dft_cyc_init :: Ptr CAcbDftCyc -> CLong -> CLong -> IO ()++-- -- | /acb_dft_cyc_clear/ /t/ +-- --+-- -- Initialize a decomposition of \(\mathbb Z/n\mathbb Z\) into cyclic+-- -- subgroups. The length /len/ is stored as /t->n/.+-- foreign import ccall "acb_dft.h acb_dft_cyc_clear"+-- acb_dft_cyc_clear :: Ptr CAcbDftCyc -> IO ()++-- foreign import ccall "acb_dft.h &acb_dft_cyc_clear"+-- p_acb_dft_cyc_clear :: FunPtr (Ptr CAcbDftCyc -> IO ())++-- -- | /acb_dft_cyc_precomp/ /w/ /v/ /t/ /prec/ +-- --+-- -- Sets /w/ to the DFT of /v/ of size /t->n/, using the cyclic+-- -- decomposition scheme /t/.+-- foreign import ccall "acb_dft.h acb_dft_cyc_precomp"+-- acb_dft_cyc_precomp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcbDftCyc -> CLong -> IO ()++-- -- Radix 2 decomposition -------------------------------------------------------++-- data AcbDftRad2 = AcbDftRad2 {-# UNPACK #-} !(ForeignPtr CAcbDftRad2)+-- type CAcbDftRad2 = CFlint AcbDftRad2++-- instance Storable CAcbDftRad2 where+-- sizeOf _ = #{size acb_dft_rad2_t}+-- alignment _ = #{alignment acb_dft_rad2_t}+-- peek = undefined+-- poke = undefined++-- newAcbDftRad2 len prec = do+-- x <- mallocForeignPtr+-- withForeignPtr x $ \x -> do+-- acb_dft_rad2_init x len prec+-- addForeignPtrFinalizer p_acb_dft_rad2_clear x+-- return $ AcbDftRad2 x++-- withAcbDftRad2 (AcbDftRad2 p) f = do+-- withForeignPtr p $ \fp -> (AcbDftRad2 p,) <$> f fp++-- withNewAcbDftRad2 len prec f = do+-- x <- newAcbDftRad2 len prec+-- withAcbDftRad2 x f++-- --------------------------------------------------------------------------------++-- -- | /acb_dft_rad2/ /w/ /v/ /e/ /prec/ +-- --+-- -- Computes the DFT of /v/ into /w/, where /v/ and /w/ have size \(2^e\),+-- -- using a radix 2 FFT.+-- foreign import ccall "acb_dft.h acb_dft_rad2"+-- acb_dft_rad2 :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- -- | /acb_dft_inverse_rad2/ /w/ /v/ /e/ /prec/ +-- --+-- -- Computes the inverse DFT of /v/ into /w/, where /v/ and /w/ have size+-- -- \(2^e\), using a radix 2 FFT.+-- foreign import ccall "acb_dft.h acb_dft_inverse_rad2"+-- acb_dft_inverse_rad2 :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- -- | /acb_dft_rad2_init/ /t/ /e/ /prec/ +-- --+-- foreign import ccall "acb_dft.h acb_dft_rad2_init"+-- acb_dft_rad2_init :: Ptr CAcbDftRad2 -> CInt -> CLong -> IO ()++-- -- | /acb_dft_rad2_clear/ /t/ +-- --+-- -- Initialize and clear a radix 2 FFT of size \(2^e\), stored as /t->n/.+-- foreign import ccall "acb_dft.h acb_dft_rad2_clear"+-- acb_dft_rad2_clear :: Ptr CAcbDftRad2 -> IO ()++-- foreign import ccall "acb_dft.h &acb_dft_rad2_clear"+-- p_acb_dft_rad2_clear :: FunPtr (Ptr CAcbDftRad2 -> IO ())++-- -- | /acb_dft_rad2_precomp/ /w/ /v/ /t/ /prec/ +-- --+-- -- Sets /w/ to the DFT of /v/ of size /t->n/, using the precomputed radix 2+-- -- scheme /t/.+-- foreign import ccall "acb_dft.h acb_dft_rad2_precomp"+-- acb_dft_rad2_precomp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcbDftRad2 -> CLong -> IO ()++-- -- Bluestein transform ---------------------------------------------------------++-- data AcbDftBluestein = AcbDftBluestein {-# UNPACK #-} !(ForeignPtr CAcbDftBluestein)+-- type CAcbDftBluestein = CFlint AcbDftBluestein++-- instance Storable CAcbDftBluestein where+-- sizeOf _ = #{size acb_dft_bluestein_t}+-- alignment _ = #{alignment acb_dft_bluestein_t}+-- peek = undefined+-- poke = undefined++-- newAcbDftBluestein len prec = do+-- x <- mallocForeignPtr+-- withForeignPtr x $ \x -> do+-- acb_dft_bluestein_init x len prec+-- addForeignPtrFinalizer p_acb_dft_bluestein_clear x+-- return $ AcbDftBluestein x++-- withAcbDftBluestein (AcbDftBluestein p) f = do+-- withForeignPtr p $ \fp -> (AcbDftBluestein p,) <$> f fp++-- withNewAcbDftBluestein len prec f = do+-- x <- newAcbDftBluestein len prec+-- withAcbDftBluestein x f++-- --------------------------------------------------------------------------------++-- -- | /acb_dft_bluestein/ /w/ /v/ /n/ /prec/ +-- --+-- -- Computes the DFT of /v/ into /w/, where /v/ and /w/ have size /n/, by+-- -- conversion to a radix 2 one using Bluestein\'s convolution trick.+-- foreign import ccall "acb_dft.h acb_dft_bluestein"+-- acb_dft_bluestein :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- -- | /acb_dft_bluestein_init/ /t/ /len/ /prec/ +-- --+-- foreign import ccall "acb_dft.h acb_dft_bluestein_init"+-- acb_dft_bluestein_init :: Ptr CAcbDftBluestein -> CLong -> CLong -> IO ()++-- -- | /acb_dft_bluestein_clear/ /t/ +-- --+-- -- Initialize and clear a Bluestein scheme to compute DFT of size /len/.+-- foreign import ccall "acb_dft.h acb_dft_bluestein_clear"+-- acb_dft_bluestein_clear :: Ptr CAcbDftBluestein -> IO ()++-- foreign import ccall "acb_dft.h &acb_dft_bluestein_clear"+-- p_acb_dft_bluestein_clear :: FunPtr (Ptr CAcbDftBluestein -> IO ())++-- -- | /acb_dft_bluestein_precomp/ /w/ /v/ /t/ /prec/ +-- --+-- -- Sets /w/ to the DFT of /v/ of size /t->n/, using the precomputed+-- -- Bluestein scheme /t/.+-- foreign import ccall "acb_dft.h acb_dft_bluestein_precomp"+-- acb_dft_bluestein_precomp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcbDftBluestein -> CLong -> IO ()+
+ src/Data/Number/Flint/Acb/Dirichlet.hs view
@@ -0,0 +1,21 @@+{- |+This module allows working with values of Dirichlet characters,+Dirichlet L-functions, and related functions. A Dirichlet L-function is+the analytic continuation of an L-series++\[L(s,\chi) = \sum_{k=1}^\infty \frac{\chi(k)}{k^s}\]++where \(\chi(k)\) is a Dirichlet character. The trivial character chi(k)+= 1 gives the Riemann zeta function. Working with Dirichlet characters+is documented in [Dirichlet]("Data.Number.Flint.Groups.Dirichlet").++The code in other modules for computing the Riemann zeta function,+Hurwitz zeta function and polylogarithm will possibly be migrated to+this module in the future.+-}++module Data.Number.Flint.Acb.Dirichlet (+ module Data.Number.Flint.Acb.Dirichlet.FFI+ ) where++import Data.Number.Flint.Acb.Dirichlet.FFI
+ src/Data/Number/Flint/Acb/Dirichlet/FFI.hsc view
@@ -0,0 +1,1159 @@+{-|+module : Data.Number.Flint.Acb.Dirichlet.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Acb.Dirichlet.FFI (+ -- * Dirichlet L-functions, Riemann zeta and related functions+ -- * Roots of unity+ DirichletRoots (..)+ , CDirichletRoots+ , newDirichletRoots+ , withDirichletRoots+ , withNewDirichletRoots+ , acb_dirichlet_roots_init+ , acb_dirichlet_roots_clear+ , acb_dirichlet_root+ -- * Truncated L-series and power sums+ , acb_dirichlet_powsum_term+ , acb_dirichlet_powsum_sieved+ , acb_dirichlet_powsum_smooth+ -- * Riemann zeta function+ , acb_dirichlet_zeta+ , acb_dirichlet_zeta_jet+ , acb_dirichlet_zeta_bound+ , acb_dirichlet_zeta_deriv_bound+ , acb_dirichlet_eta+ , acb_dirichlet_xi+ -- * Riemann-Siegel formula+ , acb_dirichlet_zeta_rs_f_coeffs+ , acb_dirichlet_zeta_rs_d_coeffs+ , acb_dirichlet_zeta_rs_bound+ , acb_dirichlet_zeta_rs_r+ , acb_dirichlet_zeta_rs+ , acb_dirichlet_zeta_jet_rs+ -- * Hurwitz zeta function+ , acb_dirichlet_hurwitz+ -- * Hurwitz zeta function precomputation+ , DirichletHurwitzPrecomp (..)+ , CDirichletHurwitzPrecomp (..)+ , newDirichletHurwitzPrecomp+ , withDirichletHurwitzPrecomp+ , withNewDirichletHurwitzPrecomp+ , acb_dirichlet_hurwitz_precomp_init+ , acb_dirichlet_hurwitz_precomp_init_num+ , acb_dirichlet_hurwitz_precomp_clear+ , acb_dirichlet_hurwitz_precomp_choose_param+ , acb_dirichlet_hurwitz_precomp_bound+ , acb_dirichlet_hurwitz_precomp_eval+ -- * Lerch transcendent+ , acb_dirichlet_lerch_phi_integral+ -- * Stieltjes constants+ , acb_dirichlet_stieltjes+ -- * Dirichlet character evaluation+ , acb_dirichlet_chi+ , acb_dirichlet_chi_vec+ , acb_dirichlet_pairing+ , acb_dirichlet_pairing_char+ -- * Dirichlet character Gauss, Jacobi and theta sums+ , acb_dirichlet_gauss_sum_naive+ , acb_dirichlet_gauss_sum_factor+ , acb_dirichlet_gauss_sum_order2+ , acb_dirichlet_gauss_sum_theta+ , acb_dirichlet_gauss_sum+ , acb_dirichlet_gauss_sum_ui+ , acb_dirichlet_jacobi_sum_naive+ , acb_dirichlet_jacobi_sum_factor+ , acb_dirichlet_jacobi_sum_gauss+ , acb_dirichlet_jacobi_sum+ , acb_dirichlet_jacobi_sum_ui+ --, acb_dirichlet_chi_theta_arb+ , acb_dirichlet_ui_theta_arb+ , acb_dirichlet_theta_length+ --, acb_dirichlet_qseries_powers_naive+ --, acb_dirichlet_qseries_powers_smallorder+ -- * Discrete Fourier transforms+ --, acb_dirichlet_dft_conrey+ , acb_dirichlet_dft+ -- * Dirichlet L-functions+ , acb_dirichlet_root_number_theta+ , acb_dirichlet_root_number+ , acb_dirichlet_l_hurwitz+ , acb_dirichlet_l_euler_product+ , _acb_dirichlet_euler_product_real_ui+ , acb_dirichlet_l+ , acb_dirichlet_l_fmpq+ , acb_dirichlet_l_vec_hurwitz+ , acb_dirichlet_l_jet+ , _acb_dirichlet_l_series+ , acb_dirichlet_l_series+ -- * Hardy Z-functions+ , acb_dirichlet_hardy_theta+ , acb_dirichlet_hardy_z+ , _acb_dirichlet_hardy_theta_series+ , acb_dirichlet_hardy_theta_series+ , _acb_dirichlet_hardy_z_series+ , acb_dirichlet_hardy_z_series+ -- * Gram points+ , acb_dirichlet_gram_point+ -- * Riemann zeta function zeros+ , acb_dirichlet_turing_method_bound+ , _acb_dirichlet_definite_hardy_z+ , _acb_dirichlet_isolate_gram_hardy_z_zero+ , _acb_dirichlet_isolate_rosser_hardy_z_zero+ , _acb_dirichlet_isolate_turing_hardy_z_zero+ , acb_dirichlet_isolate_hardy_z_zero+ , _acb_dirichlet_refine_hardy_z_zero+ --, acb_dirichlet_hardy_z_zero+ , acb_dirichlet_hardy_z_zeros+ --, acb_dirichlet_zeta_zero+ , acb_dirichlet_zeta_zeros+ , _acb_dirichlet_exact_zeta_nzeros+ , acb_dirichlet_zeta_nzeros+ , acb_dirichlet_backlund_s+ , acb_dirichlet_backlund_s_bound+ , acb_dirichlet_zeta_nzeros_gram+ , acb_dirichlet_backlund_s_gram+ -- * Riemann zeta function zeros (Platt\'s method)+ , acb_dirichlet_platt_scaled_lambda+ , acb_dirichlet_platt_scaled_lambda_vec+ , acb_dirichlet_platt_multieval+ , acb_dirichlet_platt_multieval_threaded+ , acb_dirichlet_platt_ws_interpolation+ , _acb_dirichlet_platt_local_hardy_z_zeros+ , acb_dirichlet_platt_local_hardy_z_zeros+ , acb_dirichlet_platt_hardy_z_zeros+ , acb_dirichlet_platt_zeta_zeros+) where ++-- Dirichlet L-functions, Riemann zeta and related functions++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.C.String+import Foreign.Storable++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Groups.Dirichlet++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb.Types+import Data.Number.Flint.Acb.Poly++#include <flint/acb_dirichlet.h>++-- dirichlet_roots_t -----------------------------------------------------------++data DirichletRoots =+ DirichletRoots {-# UNPACK #-} !(ForeignPtr CDirichletRoots)+type CDirichletRoots = CFlint DirichletRoots++instance Storable CDirichletRoots where+ sizeOf _ = #{size acb_dirichlet_roots_t}+ alignment _ = #{alignment acb_dirichlet_roots_t}+ peek = undefined+ poke = undefined++-- | Create new `DirichletRoots` /n/ /num/ /prec/+newDirichletRoots n num prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> acb_dirichlet_roots_init x n num prec+ addForeignPtrFinalizer p_acb_dirichlet_roots_clear x+ return $ DirichletRoots x++-- | Use `DirichletRoots`+withDirichletRoots (DirichletRoots x) f = do+ withForeignPtr x $ \xp -> (DirichletRoots x,) <$> f xp++-- | Use new `DirichletRoots`+withNewDirichletRoots n num prec f = do+ x <- newDirichletRoots n num prec+ withDirichletRoots x f+ +-- acb_dirichlet_powers_t ------------------------------------------------------++data AcbDirichletPowers =+ AcbDirichletPowers {-# UNPACK #-} !(ForeignPtr CAcbDirichletPowers)+type CAcbDirichletPowers = CFlint AcbDirichletPowers++-- Roots of unity --------------------------------------------------------------++-- | /acb_dirichlet_roots_init/ /roots/ /n/ /num/ /prec/ +-- +-- Initializes /roots/ with precomputed data for fast evaluation of roots+-- of unity \(e^{2\pi i k/n}\) of a fixed order /n/. The precomputation is+-- optimized for /num/ evaluations.+-- +-- For very small /num/, only the single root \(e^{2\pi i/n}\) will be+-- precomputed, which can then be raised to a power. For small /prec/ and+-- large /n/, this method might even skip precomputing this single root if+-- it estimates that evaluating roots of unity from scratch will be faster+-- than powering.+-- +-- If /num/ is large enough, the whole set of roots in the first quadrant+-- will be precomputed at once. However, this is automatically avoided for+-- large /n/ if too much memory would be used. For intermediate /num/,+-- baby-step giant-step tables are computed.+foreign import ccall "acb_dirichlet.h acb_dirichlet_roots_init"+ acb_dirichlet_roots_init :: Ptr CDirichletRoots -> CULong -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_roots_clear/ /roots/ +-- +-- Clears the structure.+foreign import ccall "acb_dirichlet.h acb_dirichlet_roots_clear"+ acb_dirichlet_roots_clear :: Ptr CDirichletRoots -> IO ()++foreign import ccall "acb_dirichlet.h &acb_dirichlet_roots_clear"+ p_acb_dirichlet_roots_clear :: FunPtr (Ptr CDirichletRoots -> IO ())++-- | /acb_dirichlet_root/ /res/ /roots/ /k/ /prec/ +-- +-- Computes \(e^{2\pi i k/n}\).+foreign import ccall "acb_dirichlet.h acb_dirichlet_root"+ acb_dirichlet_root :: Ptr CAcb -> Ptr CDirichletRoots -> CULong -> CLong -> IO ()++-- Truncated L-series and power sums -------------------------------------------++-- | /acb_dirichlet_powsum_term/ /res/ /log_prev/ /prev/ /s/ /k/ /integer/ /critical_line/ /len/ /prec/ +-- +-- Sets /res/ to \(k^{-(s+x)}\) as a power series in /x/ truncated to+-- length /len/. The flags /integer/ and /critical_line/ respectively+-- specify optimizing for /s/ being an integer or having real part 1\/2.+-- +-- On input /log_prev/ should contain the natural logarithm of the integer+-- at /prev/. If /prev/ is close to /k/, this can be used to speed up+-- computations. If \(\log(k)\) is computed internally by this function,+-- then /log_prev/ is overwritten by this value, and the integer at /prev/+-- is overwritten by /k/, allowing /log_prev/ to be recycled for the next+-- term when evaluating a power sum.+foreign import ccall "acb_dirichlet.h acb_dirichlet_powsum_term"+ acb_dirichlet_powsum_term :: Ptr CAcb -> Ptr CArb -> Ptr CULong -> Ptr CAcb -> CULong -> CInt -> CInt -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_powsum_sieved/ /res/ /s/ /n/ /len/ /prec/ +-- +-- Sets /res/ to \(\sum_{k=1}^n k^{-(s+x)}\) as a power series in /x/+-- truncated to length /len/. This function stores a table of powers that+-- have already been calculated, computing \((ij)^r\) as \(i^r j^r\)+-- whenever \(k = ij\) is composite. As a further optimization, it groups+-- all even \(k\) and evaluates the sum as a polynomial in \(2^{-(s+x)}\).+-- This scheme requires about \(n / \log n\) powers, \(n / 2\)+-- multiplications, and temporary storage of \(n / 6\) power series. Due to+-- the extra power series multiplications, it is only faster than the naive+-- algorithm when /len/ is small.+foreign import ccall "acb_dirichlet.h acb_dirichlet_powsum_sieved"+ acb_dirichlet_powsum_sieved :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_powsum_smooth/ /res/ /s/ /n/ /len/ /prec/ +-- +-- Sets /res/ to \(\sum_{k=1}^n k^{-(s+x)}\) as a power series in /x/+-- truncated to length /len/. This function performs partial sieving by+-- adding multiples of 5-smooth /k/ into separate buckets. Asymptotically,+-- this requires computing 4\/15 of the powers, which is slower than+-- /sieved/, but only requires logarithmic extra space. It is also faster+-- for large /len/, since most power series multiplications are traded for+-- additions. A slightly bigger gain for larger /n/ could be achieved by+-- using more small prime factors, at the expense of space.+foreign import ccall "acb_dirichlet.h acb_dirichlet_powsum_smooth"+ acb_dirichlet_powsum_smooth :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> CLong -> IO ()++-- Riemann zeta function -------------------------------------------------------++-- | /acb_dirichlet_zeta/ /res/ /s/ /prec/ +-- +-- Computes \(\zeta(s)\) using an automatic choice of algorithm.+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta"+ acb_dirichlet_zeta :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_dirichlet_zeta_jet/ /res/ /s/ /deflate/ /len/ /prec/ +-- +-- Computes the first /len/ terms of the Taylor series of the Riemann zeta+-- function at /s/. If /deflate/ is nonzero, computes the deflated function+-- \(\zeta(s) - 1/(s-1)\) instead.+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_jet"+ acb_dirichlet_zeta_jet :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_zeta_bound/ /res/ /s/ +-- +-- Computes an upper bound for \(|\zeta(s)|\) quickly. On the critical+-- strip (and slightly outside of it), formula (43.3) in < [Rad1973]> is+-- used. To the right, evaluating at the real part of /s/ gives a trivial+-- bound. To the left, the functional equation is used.+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_bound"+ acb_dirichlet_zeta_bound :: Ptr CMag -> Ptr CAcb -> IO ()++-- | /acb_dirichlet_zeta_deriv_bound/ /der1/ /der2/ /s/ +-- +-- Sets /der1/ to a bound for \(|\zeta'(s)|\) and /der2/ to a bound for+-- \(|\zeta''(s)|\). These bounds are mainly intended for use in the+-- critical strip and will not be tight.+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_deriv_bound"+ acb_dirichlet_zeta_deriv_bound :: Ptr CMag -> Ptr CMag -> Ptr CAcb -> IO ()++-- | /acb_dirichlet_eta/ /res/ /s/ /prec/ +-- +-- Sets /res/ to the Dirichlet eta function+-- \(\eta(s) = \sum_{k=1}^{\infty} (-1)^{k+1} / k^s = (1-2^{1-s}) \zeta(s)\),+-- also known as the alternating zeta function. Note that the alternating+-- character \(\{1,-1\}\) is not itself a Dirichlet character.+foreign import ccall "acb_dirichlet.h acb_dirichlet_eta"+ acb_dirichlet_eta :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_dirichlet_xi/ /res/ /s/ /prec/ +-- +-- Sets /res/ to the Riemann xi function+-- \(\xi(s) = \frac{1}{2} s (s-1) \pi^{-s/2} \Gamma(\frac{1}{2} s) \zeta(s)\).+-- The functional equation for xi is \(\xi(1-s) = \xi(s)\).+foreign import ccall "acb_dirichlet.h acb_dirichlet_xi"+ acb_dirichlet_xi :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Riemann-Siegel formula ------------------------------------------------------++-- The Riemann-Siegel (RS) formula is implemented closely following J.+-- Arias de Reyna < [Ari2011]>. For \(s = \sigma + it\) with \(t > 0\), the+-- expansion takes the form+--+-- \[`\]+-- \[\zeta(s) = \mathcal{R}(s) + X(s) \overline{\mathcal{R}}(1-s), \quad X(s) = \pi^{s-1/2} \frac{\Gamma((1-s)/2)}{\Gamma(s/2)}\]+--+-- where+--+-- \[`\]+-- \[\mathcal{R}(s) = \sum_{k=1}^N \frac{1}{k^s} + (-1)^{N-1} U a^{-\sigma} \left[ \sum_{k=0}^K \frac{C_k(p)}{a^k} + RS_K \right]\]+--+-- \[`\]+-- \[U = \exp\left(-i\left[ \frac{t}{2} \log\left(\frac{t}{2\pi}\right)-\frac{t}{2}-\frac{\pi}{8} \right]\right), \quad+-- a = \sqrt{\frac{t}{2\pi}}, \quad N = \lfloor a \rfloor, \quad p = 1-2(a-N).\]+--+-- The coefficients \(C_k(p)\) in the asymptotic part of the expansion are+-- expressed in terms of certain auxiliary coefficients \(d_j^{(k)}\) and+-- \(F^{(j)}(p)\). Because of artificial discontinuities, /s/ should be+-- exact inside the evaluation.+--+-- | /acb_dirichlet_zeta_rs_f_coeffs/ /f/ /p/ /n/ /prec/ +-- +-- Computes the coefficients \(F^{(j)}(p)\) for \(0 \le j < n\). Uses power+-- series division. This method breaks down when \(p = \pm 1/2\) (which is+-- not problem if /s/ is an exact floating-point number).+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_rs_f_coeffs"+ acb_dirichlet_zeta_rs_f_coeffs :: Ptr CAcb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_zeta_rs_d_coeffs/ /d/ /sigma/ /k/ /prec/ +-- +-- Computes the coefficients \(d_j^{(k)}\) for+-- \(0 \le j \le \lfloor 3k/2 \rfloor + 1\). On input, the array /d/ must+-- contain the coefficients for \(d_j^{(k-1)}\) unless \(k = 0\), and these+-- coefficients will be updated in-place.+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_rs_d_coeffs"+ acb_dirichlet_zeta_rs_d_coeffs :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_zeta_rs_bound/ /err/ /s/ /K/ +-- +-- Bounds the error term \(RS_K\) following Theorem 4.2 in Arias de Reyna.+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_rs_bound"+ acb_dirichlet_zeta_rs_bound :: Ptr CMag -> Ptr CAcb -> CLong -> IO ()++-- | /acb_dirichlet_zeta_rs_r/ /res/ /s/ /K/ /prec/ +-- +-- Computes \(\mathcal{R}(s)\) in the upper half plane. Uses precisely /K/+-- asymptotic terms in the RS formula if this input parameter is positive;+-- otherwise chooses the number of terms automatically based on /s/ and the+-- precision.+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_rs_r"+ acb_dirichlet_zeta_rs_r :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_zeta_rs/ /res/ /s/ /K/ /prec/ +-- +-- Computes \(\zeta(s)\) using the Riemann-Siegel formula. Uses precisely+-- /K/ asymptotic terms in the RS formula if this input parameter is+-- positive; otherwise chooses the number of terms automatically based on+-- /s/ and the precision.+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_rs"+ acb_dirichlet_zeta_rs :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_zeta_jet_rs/ /res/ /s/ /len/ /prec/ +-- +-- Computes the first /len/ terms of the Taylor series of the Riemann zeta+-- function at /s/ using the Riemann Siegel formula. This function+-- currently only supports /len/ = 1 or /len/ = 2. A finite difference is+-- used to compute the first derivative.+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_jet_rs"+ acb_dirichlet_zeta_jet_rs :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- Hurwitz zeta function -------------------------------------------------------++-- | /acb_dirichlet_hurwitz/ /res/ /s/ /a/ /prec/ +-- +-- Computes the Hurwitz zeta function \(\zeta(s, a)\). This function+-- automatically delegates to the code for the Riemann zeta function when+-- \(a = 1\). Some other special cases may also be handled by direct+-- formulas. In general, Euler-Maclaurin summation is used.+foreign import ccall "acb_dirichlet.h acb_dirichlet_hurwitz"+ acb_dirichlet_hurwitz :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Hurwitz zeta function precomputation ----------------------------------------++data DirichletHurwitzPrecomp = DirichletHurwitzPrecomp {-# UNPACK #-} !(ForeignPtr CDirichletHurwitzPrecomp)+type CDirichletHurwitzPrecomp = CFlint DirichletHurwitzPrecomp++instance Storable CDirichletHurwitzPrecomp where+ sizeOf _ = #{size acb_dirichlet_hurwitz_precomp_t}+ alignment _ = #{alignment acb_dirichlet_hurwitz_precomp_t}+ peek = undefined+ poke = undefined++-- | Create new `DirichletHurwitzPrecomp`+newDirichletHurwitzPrecomp s deflate a k n prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ acb_dirichlet_hurwitz_precomp_init x s deflate a k n prec+ addForeignPtrFinalizer p_acb_dirichlet_hurwitz_precomp_clear x+ return $ DirichletHurwitzPrecomp x++-- | Use `f` on `DirichletHurwitzPrecomp`+withDirichletHurwitzPrecomp (DirichletHurwitzPrecomp x) f = do+ withForeignPtr x $ \xp -> (DirichletHurwitzPrecomp x,) <$> f xp++-- | Use `f` on new `DirichletHurwitzPrecomp`+withNewDirichletHurwitzPrecomp s deflate a k n prec f = do+ x <- newDirichletHurwitzPrecomp s deflate a k n prec+ withDirichletHurwitzPrecomp x f++--------------------------------------------------------------------------------++-- | /acb_dirichlet_hurwitz_precomp_init/ /pre/ /s/ /deflate/ /A/ /K/ /N/ /prec/ +-- +-- Precomputes a grid of Taylor polynomials for fast evaluation of+-- \(\zeta(s,a)\) on \(a \in (0,1]\) with fixed /s/. /A/ is the initial+-- shift to apply to /a/, /K/ is the number of Taylor terms, /N/ is the+-- number of grid points. The precomputation requires /NK/ evaluations of+-- the Hurwitz zeta function, and each subsequent evaluation requires /2K/+-- simple arithmetic operations (polynomial evaluation) plus /A/ powers. As+-- /K/ grows, the error is at most \(O(1/(2AN)^K)\).+-- +-- This function can be called with /A/ set to zero, in which case no+-- Taylor series precomputation is performed. This means that evaluation+-- will be identical to calling @acb_dirichlet_hurwitz@ directly.+-- +-- Otherwise, we require that /A/, /K/ and /N/ are all positive. For a+-- finite error bound, we require \(K+\operatorname{re}(s) > 1\). To avoid+-- an initial \"bump\" that steals precision and slows convergence, /AN/+-- should be at least roughly as large as \(|s|\), e.g. it is a good idea+-- to have at least \(AN > 0.5 |s|\).+-- +-- If /deflate/ is set, the deflated Hurwitz zeta function is used,+-- removing the pole at \(s = 1\).+foreign import ccall "acb_dirichlet.h acb_dirichlet_hurwitz_precomp_init"+ acb_dirichlet_hurwitz_precomp_init :: Ptr CDirichletHurwitzPrecomp -> Ptr CAcb -> CInt -> CULong -> CULong -> CULong -> CLong -> IO ()++-- | /acb_dirichlet_hurwitz_precomp_init_num/ /pre/ /s/ /deflate/ /num_eval/ /prec/ +-- +-- Initializes /pre/, choosing the parameters /A/, /K/, and /N/+-- automatically to minimize the cost of /num_eval/ evaluations of the+-- Hurwitz zeta function at argument /s/ to precision /prec/.+foreign import ccall "acb_dirichlet.h acb_dirichlet_hurwitz_precomp_init_num"+ acb_dirichlet_hurwitz_precomp_init_num :: Ptr CDirichletHurwitzPrecomp -> Ptr CAcb -> CInt -> CDouble -> CLong -> IO ()++-- | /acb_dirichlet_hurwitz_precomp_clear/ /pre/ +-- +-- Clears the precomputed data.+foreign import ccall "acb_dirichlet.h acb_dirichlet_hurwitz_precomp_clear"+ acb_dirichlet_hurwitz_precomp_clear :: Ptr CDirichletHurwitzPrecomp -> IO ()++foreign import ccall "acb_dirichlet.h &acb_dirichlet_hurwitz_precomp_clear"+ p_acb_dirichlet_hurwitz_precomp_clear :: FunPtr (Ptr CDirichletHurwitzPrecomp -> IO ())++-- | /acb_dirichlet_hurwitz_precomp_choose_param/ /A/ /K/ /N/ /s/ /num_eval/ /prec/ +-- +-- Chooses precomputation parameters /A/, /K/ and /N/ to minimize the cost+-- of /num_eval/ evaluations of the Hurwitz zeta function at argument /s/+-- to precision /prec/. If it is estimated that evaluating each Hurwitz+-- zeta function from scratch would be better than performing a+-- precomputation, /A/, /K/ and /N/ are all set to 0.+foreign import ccall "acb_dirichlet.h acb_dirichlet_hurwitz_precomp_choose_param"+ acb_dirichlet_hurwitz_precomp_choose_param :: Ptr CULong -> Ptr CULong -> Ptr CULong -> Ptr CAcb -> CDouble -> CLong -> IO ()++-- | /acb_dirichlet_hurwitz_precomp_bound/ /res/ /s/ /A/ /K/ /N/ +-- +-- Computes an upper bound for the truncation error (not accounting for+-- roundoff error) when evaluating \(\zeta(s,a)\) with precomputation+-- parameters /A/, /K/, /N/, assuming that \(0 < a \le 1\). For details,+-- see @algorithms_hurwitz@.+foreign import ccall "acb_dirichlet.h acb_dirichlet_hurwitz_precomp_bound"+ acb_dirichlet_hurwitz_precomp_bound :: Ptr CMag -> Ptr CAcb -> CULong -> CULong -> CULong -> IO ()++-- | /acb_dirichlet_hurwitz_precomp_eval/ /res/ /pre/ /p/ /q/ /prec/ +-- +-- Evaluates \(\zeta(s,p/q)\) using precomputed data, assuming that+-- \(0 < p/q \le 1\).+foreign import ccall "acb_dirichlet.h acb_dirichlet_hurwitz_precomp_eval"+ acb_dirichlet_hurwitz_precomp_eval :: Ptr CAcb -> Ptr CDirichletHurwitzPrecomp -> CULong -> CULong -> CLong -> IO ()++-- Lerch transcendent ----------------------------------------------------------++-- | /acb_dirichlet_lerch_phi_integral/ /res/ /z/ /s/ /a/ /prec/ +-- +-- Computes the Lerch transcendent+-- +-- \[`\]+-- \[\Phi(z,s,a) = \sum_{k=0}^{\infty} \frac{z^k}{(k+a)^s}\]+-- +-- which is analytically continued for \(|z| \ge 1\).+-- +-- The /direct/ version evaluates a truncation of the defining series. The+-- /integral/ version uses the Hankel contour integral+-- +-- \[`\]+-- \[\Phi(z,s,a) = -\frac{\Gamma(1-s)}{2 \pi i} \int_C \frac{(-t)^{s-1} e^{-a t}}{1 - z e^{-t}} dt\]+-- +-- where the path is deformed as needed to avoid poles and branch cuts of+-- the integrand. The default method chooses an algorithm automatically and+-- also checks for some special cases where the function can be expressed+-- in terms of simpler functions (Hurwitz zeta, polylogarithms).+foreign import ccall "acb_dirichlet.h acb_dirichlet_lerch_phi_integral"+ acb_dirichlet_lerch_phi_integral :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Stieltjes constants ---------------------------------------------------------++-- | /acb_dirichlet_stieltjes/ /res/ /n/ /a/ /prec/ +-- +-- Given a nonnegative integer /n/, sets /res/ to the generalized Stieltjes+-- constant \(\gamma_n(a)\) which is the coefficient in the Laurent series+-- of the Hurwitz zeta function at the pole+-- +-- \[`\]+-- \[\zeta(s,a) = \frac{1}{s-1} + \sum_{n=0}^\infty \frac{(-1)^n}{n!} \gamma_n(a) (s-1)^n.\]+-- +-- With \(a = 1\), this gives the ordinary Stieltjes constants for the+-- Riemann zeta function.+-- +-- This function uses an integral representation to permit fast computation+-- for extremely large /n/ < [JB2018]>. If /n/ is moderate and the+-- precision is high enough, it falls back to evaluating the Hurwitz zeta+-- function of a power series and reading off the last coefficient.+-- +-- Note that for computing a range of values+-- \(\gamma_0(a), \ldots, \gamma_n(a)\), it is generally more efficient to+-- evaluate the Hurwitz zeta function series expansion once at \(s = 1\)+-- than to call this function repeatedly, unless /n/ is extremely large (at+-- least several hundred).+foreign import ccall "acb_dirichlet.h acb_dirichlet_stieltjes"+ acb_dirichlet_stieltjes :: Ptr CAcb -> Ptr CFmpz -> Ptr CAcb -> CLong -> IO ()++-- Dirichlet character evaluation ----------------------------------------------++-- | /acb_dirichlet_chi/ /res/ /G/ /chi/ /n/ /prec/ +-- +-- Sets /res/ to \(\chi(n)\), the value of the Dirichlet character /chi/ at+-- the integer /n/.+foreign import ccall "acb_dirichlet.h acb_dirichlet_chi"+ acb_dirichlet_chi :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CULong -> CLong -> IO ()++-- | /acb_dirichlet_chi_vec/ /v/ /G/ /chi/ /nv/ /prec/ +-- +-- Compute the /nv/ first Dirichlet values.+foreign import ccall "acb_dirichlet.h acb_dirichlet_chi_vec"+ acb_dirichlet_chi_vec :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_pairing"+ acb_dirichlet_pairing :: Ptr CAcb -> Ptr CDirichletGroup -> CULong -> CULong -> CLong -> IO ()++-- | /acb_dirichlet_pairing_char/ /res/ /G/ /a/ /b/ /prec/ +-- +-- Sets /res/ to the value of the Dirichlet pairing \(\chi(m,n)\) at+-- numbers \(m\) and \(n\). The second form takes two characters as input.+foreign import ccall "acb_dirichlet.h acb_dirichlet_pairing_char"+ acb_dirichlet_pairing_char :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletChar -> CLong -> IO ()++-- Dirichlet character Gauss, Jacobi and theta sums ----------------------------++foreign import ccall "acb_dirichlet.h acb_dirichlet_gauss_sum_naive"+ acb_dirichlet_gauss_sum_naive :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_gauss_sum_factor"+ acb_dirichlet_gauss_sum_factor :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_gauss_sum_order2"+ acb_dirichlet_gauss_sum_order2 :: Ptr CAcb -> Ptr CDirichletChar -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_gauss_sum_theta"+ acb_dirichlet_gauss_sum_theta :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_gauss_sum"+ acb_dirichlet_gauss_sum :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++-- | /acb_dirichlet_gauss_sum_ui/ /res/ /G/ /a/ /prec/ +-- +-- Sets /res/ to the Gauss sum+-- +-- \[G_q(a) = \sum_{x \bmod q} \chi_q(a, x) e^{\frac{2i\pi x}q}\]+-- +-- - the /naive/ version computes the sum as defined.+-- - the /factor/ version writes it as a product of local Gauss sums by+-- chinese remainder theorem.+-- - the /order2/ version assumes /chi/ is real and primitive and returns+-- \(i^p\sqrt q\) where \(p\) is the parity of \(\chi\).+-- - the /theta/ version assumes that /chi/ is primitive to obtain the+-- Gauss sum by functional equation of the theta series at \(t=1\). An+-- abort will be raised if the theta series vanishes at \(t=1\). Only 4+-- exceptional characters of conductor 300 and 600 are known to have+-- this particularity, and none with primepower modulus.+-- - the default version automatically combines the above methods.+-- - the /ui/ version only takes the Conrey number /a/ as parameter.+foreign import ccall "acb_dirichlet.h acb_dirichlet_gauss_sum_ui"+ acb_dirichlet_gauss_sum_ui :: Ptr CAcb -> Ptr CDirichletGroup -> CULong -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_jacobi_sum_naive"+ acb_dirichlet_jacobi_sum_naive :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletChar -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_jacobi_sum_factor"+ acb_dirichlet_jacobi_sum_factor :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletChar -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_jacobi_sum_gauss"+ acb_dirichlet_jacobi_sum_gauss :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletChar -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_jacobi_sum"+ acb_dirichlet_jacobi_sum :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletChar -> CLong -> IO ()++-- | /acb_dirichlet_jacobi_sum_ui/ /res/ /G/ /a/ /b/ /prec/ +-- +-- Computes the Jacobi sum+-- +-- \[J_q(a,b) = \sum_{x \bmod q} \chi_q(a, x)\chi_q(b, 1-x)\]+-- +-- - the /naive/ version computes the sum as defined.+-- - the /factor/ version writes it as a product of local Jacobi sums+-- - the /gauss/ version assumes \(ab\) is primitive and uses the formula+-- \(J_q(a,b)G_q(ab) = G_q(a)G_q(b)\)+-- - the default version automatically combines the above methods.+-- - the /ui/ version only takes the Conrey numbers /a/ and /b/ as+-- parameters.+foreign import ccall "acb_dirichlet.h acb_dirichlet_jacobi_sum_ui"+ acb_dirichlet_jacobi_sum_ui :: Ptr CAcb -> Ptr CDirichletGroup -> CULong -> CULong -> CLong -> IO ()++-- foreign import ccall "acb_dirichlet.h acb_dirichlet_chi_theta_arb"+-- acb_dirichlet_chi_theta_arb :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CArb -> CLong -> IO ()++-- | /acb_dirichlet_ui_theta_arb/ /res/ /G/ /a/ /t/ /prec/ +-- +-- Compute the theta series \(\Theta_q(a,t)\) for real argument \(t>0\).+-- Beware that if \(t<1\) the functional equation+-- +-- \[t \theta(a,t) = \epsilon(\chi) \theta\left(\frac1a, \frac1t\right)\]+-- +-- should be used, which is not done automatically (to avoid recomputing+-- the Gauss sum).+-- +-- We call /theta series/ of a Dirichlet character the quadratic series+-- +-- \[\Theta_q(a) = \sum_{n\geq 0} \chi_q(a, n) n^p x^{n^2}\]+-- +-- where \(p\) is the parity of the character \(\chi_q(a,\cdot)\).+-- +-- For \(\Re(t)>0\) we write \(x(t)=\exp(-\frac{\pi}{N}t^2)\) and define+-- +-- \[\Theta_q(a,t) = \sum_{n\geq 0} \chi_q(a, n) x(t)^{n^2}.\]+foreign import ccall "acb_dirichlet.h acb_dirichlet_ui_theta_arb"+ acb_dirichlet_ui_theta_arb :: Ptr CAcb -> Ptr CDirichletGroup -> CULong -> Ptr CArb -> CLong -> IO ()++-- | /acb_dirichlet_theta_length/ /q/ /t/ /prec/ +-- +-- Compute the number of terms to be summed in the theta series of argument+-- /t/ so that the tail is less than \(2^{-\mathrm{prec}}\).+foreign import ccall "acb_dirichlet.h acb_dirichlet_theta_length"+ acb_dirichlet_theta_length :: CULong -> Ptr CArb -> CLong -> IO CULong++-- foreign import ccall "acb_dirichlet.h acb_dirichlet_qseries_powers_naive"+-- acb_dirichlet_qseries_powers_naive :: Ptr CAcb -> Ptr CArb -> CInt -> Ptr CULong -> Ptr CAcbDirichletPowers -> CLong -> CLong -> IO ()++-- -- | /acb_dirichlet_qseries_powers_smallorder/ /res/ /x/ /p/ /a/ /z/ /len/ /prec/ +-- -- +-- -- Compute the series \(\sum n^p z^{a_n} x^{n^2}\) for exponent list /a/,+-- -- precomputed powers /z/ and parity /p/ (being 0 or 1).+-- -- +-- -- The /naive/ version sums the series as defined, while the /smallorder/+-- -- variant evaluates the series on the quotient ring by a cyclotomic+-- -- polynomial before evaluating at the root of unity, ignoring its argument+-- -- /z/.+-- foreign import ccall "acb_dirichlet.h acb_dirichlet_qseries_powers_smallorder"+-- acb_dirichlet_qseries_powers_smallorder :: Ptr CAcb -> Ptr CArb -> CInt -> Ptr CULong -> Ptr CAcbDirichletPowers -> CLong -> CLong -> IO ()++-- Discrete Fourier transforms -------------------------------------------------++-- -- If \(f\) is a function \(\mathbb Z/q\mathbb Z\to \mathbb C\), its+-- -- discrete Fourier transform is the function defined on Dirichlet+-- -- characters mod \(q\) by+-- --+-- -- \[\hat f(\chi) = \sum_{x\mod q}\overline{\chi(x)}f(x)\]+-- --+-- -- See the @acb-dft@ module.+-- --+-- -- Here we take advantage of the Conrey isomorphism \(G \to \hat G\) to+-- -- consider the Fourier transform on Conrey labels as+-- --+-- -- \[g(a) = \sum_{b\bmod q}\overline{\chi_q(a,b)}f(b)\]+-- --+-- -- | /acb_dirichlet_dft_conrey/ /w/ /v/ /G/ /prec/ +-- -- +-- -- Compute the DFT of /v/ using Conrey indices. This function assumes /v/+-- -- and /w/ are vectors of size /G->phi_q/, whose values correspond to a+-- -- lexicographic ordering of Conrey logs (as obtained using+-- -- @dirichlet_char_next@ or by @dirichlet_char_index@).+-- -- +-- -- For example, if \(q=15\), the Conrey elements are stored in following+-- -- order+-- -- +-- -- > +-------+-------------+-------------------++-- -- > | index | log = [e,f] | number = 7^e 11^f |+-- -- > +=======+=============+===================++-- -- > | 0 | [0, 0] | 1 |+-- -- > +-------+-------------+-------------------++-- -- > | 1 | [0, 1] | 7 |+-- -- > +-------+-------------+-------------------++-- -- > | 2 | [0, 2] | 4 |+-- -- > +-------+-------------+-------------------++-- -- > | 3 | [0, 3] | 13 |+-- -- > +-------+-------------+-------------------++-- -- > | 4 | [0, 4] | 1 |+-- -- > +-------+-------------+-------------------++-- -- > | 5 | [1, 0] | 11 |+-- -- > +-------+-------------+-------------------++-- -- > | 6 | [1, 1] | 2 |+-- -- > +-------+-------------+-------------------++-- -- > | 7 | [1, 2] | 14 |+-- -- > +-------+-------------+-------------------++-- -- > | 8 | [1, 3] | 8 |+-- -- > +-------+-------------+-------------------++-- -- > | 9 | [1, 4] | 11 |+-- -- > +-------+-------------+-------------------++-- foreign import ccall "acb_dirichlet.h acb_dirichlet_dft_conrey"+-- acb_dirichlet_dft_conrey :: Ptr CAcb -> Ptr CAcb -> Ptr CDirichletGroup -> CLong -> IO ()++-- | /acb_dirichlet_dft/ /w/ /v/ /G/ /prec/ +-- +-- Compute the DFT of /v/ using Conrey numbers. This function assumes /v/+-- and /w/ are vectors of size /G->q/. All values at index not coprime to+-- /G->q/ are ignored.+foreign import ccall "acb_dirichlet.h acb_dirichlet_dft"+ acb_dirichlet_dft :: Ptr CAcb -> Ptr CAcb -> Ptr CDirichletGroup -> CLong -> IO ()++-- Dirichlet L-functions -------------------------------------------------------++foreign import ccall "acb_dirichlet.h acb_dirichlet_root_number_theta"+ acb_dirichlet_root_number_theta :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++-- | /acb_dirichlet_root_number/ /res/ /G/ /chi/ /prec/ +-- +-- Sets /res/ to the root number \(\epsilon(\chi)\) for a primitive+-- character /chi/, which appears in the functional equation (where \(p\)+-- is the parity of \(\chi\)):+-- +-- \[\left(\frac{q}{\pi}\right)^{\frac{s+p}2}\Gamma\left(\frac{s+p}2\right) L(s, \chi) = \epsilon(\chi) \left(\frac{q}{\pi}\right)^{\frac{1-s+p}2}\Gamma\left(\frac{1-s+p}2\right) L(1 - s, \overline\chi)\]+-- +-- - The /theta/ variant uses the evaluation at \(t=1\) of the Theta+-- series.+-- - The default version computes it via the gauss sum.+foreign import ccall "acb_dirichlet.h acb_dirichlet_root_number"+ acb_dirichlet_root_number :: Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++-- | /acb_dirichlet_l_hurwitz/ /res/ /s/ /precomp/ /G/ /chi/ /prec/ +-- +-- Computes \(L(s,\chi)\) using decomposition in terms of the Hurwitz zeta+-- function+-- +-- \[L(s,\chi) = q^{-s}\sum_{k=1}^q \chi(k) \,\zeta\!\left(s,\frac kq\right).\]+-- +-- If \(s = 1\) and \(\chi\) is non-principal, the deflated Hurwitz zeta+-- function is used to avoid poles.+-- +-- If /precomp/ is /NULL/, each Hurwitz zeta function value is computed+-- directly. If a pre-initialized /precomp/ object is provided, this will+-- be used instead to evaluate the Hurwitz zeta function.+foreign import ccall "acb_dirichlet.h acb_dirichlet_l_hurwitz"+ acb_dirichlet_l_hurwitz :: Ptr CAcb -> Ptr CAcb -> Ptr CDirichletHurwitzPrecomp -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_l_euler_product"+ acb_dirichlet_l_euler_product :: Ptr CAcb -> Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++-- | /_acb_dirichlet_euler_product_real_ui/ /res/ /s/ /chi/ /mod/ /reciprocal/ /prec/ +-- +-- Computes \(L(s,\chi)\) directly using the Euler product. This is+-- efficient if /s/ has large positive real part. As implemented, this+-- function only gives a finite result if \(\operatorname{re}(s) \ge 2\).+-- +-- An error bound is computed via @mag_hurwitz_zeta_uiui@. If /s/ is+-- complex, replace it with its real part. Since+-- +-- \[`\]+-- \[\frac{1}{L(s,\chi)} = \prod_{p} \left(1 - \frac{\chi(p)}{p^s}\right)+-- = \sum_{k=1}^{\infty} \frac{\mu(k)\chi(k)}{k^s}\]+-- +-- and the truncated product gives all smooth-index terms in the series, we+-- have+-- +-- \[`\]+-- \[\left|\prod_{p < N} \left(1 - \frac{\chi(p)}{p^s}\right) - \frac{1}{L(s,\chi)}\right|+-- \le \sum_{k=N}^{\infty} \frac{1}{k^s} = \zeta(s,N).\]+-- +-- The underscore version specialized for integer /s/ assumes that \(\chi\)+-- is a real Dirichlet character given by the explicit list /chi/ of+-- character values at 0, 1, ..., /mod/ - 1. If /reciprocal/ is set, it+-- computes \(1 / L(s,\chi)\) (this is faster if the reciprocal can be used+-- directly).+foreign import ccall "acb_dirichlet.h _acb_dirichlet_euler_product_real_ui"+ _acb_dirichlet_euler_product_real_ui :: Ptr CArb -> CULong -> CString -> CInt -> CInt -> CLong -> IO ()++-- | /acb_dirichlet_l/ /res/ /s/ /G/ /chi/ /prec/ +-- +-- Computes \(L(s,\chi)\) using a default choice of algorithm.+foreign import ccall "acb_dirichlet.h acb_dirichlet_l"+ acb_dirichlet_l :: Ptr CAcb -> Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++-- | /acb_dirichlet_l_fmpq/ /res/ /s/ /G/ /chi/ /prec/ +-- +-- Computes \(L(s,\chi)\) where /s/ is a rational number. The /afe/ version+-- uses the approximate functional equation; the default version chooses an+-- algorithm automatically.+foreign import ccall "acb_dirichlet.h acb_dirichlet_l_fmpq"+ acb_dirichlet_l_fmpq :: Ptr CAcb -> Ptr CFmpq -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++-- | /acb_dirichlet_l_vec_hurwitz/ /res/ /s/ /precomp/ /G/ /prec/ +-- +-- Compute all values \(L(s,\chi)\) for \(\chi\) mod \(q\), using the+-- Hurwitz zeta function and a discrete Fourier transform. The output /res/+-- is assumed to have length /G->phi_q/ and values are stored by+-- lexicographically ordered Conrey logs. See @acb_dirichlet_dft_conrey@.+-- +-- If /precomp/ is /NULL/, each Hurwitz zeta function value is computed+-- directly. If a pre-initialized /precomp/ object is provided, this will+-- be used instead to evaluate the Hurwitz zeta function.+foreign import ccall "acb_dirichlet.h acb_dirichlet_l_vec_hurwitz"+ acb_dirichlet_l_vec_hurwitz :: Ptr CAcb -> Ptr CAcb -> Ptr CDirichletHurwitzPrecomp -> Ptr CDirichletGroup -> CLong -> IO ()++-- | /acb_dirichlet_l_jet/ /res/ /s/ /G/ /chi/ /deflate/ /len/ /prec/ +-- +-- Computes the Taylor expansion of \(L(s,\chi)\) to length /len/, i.e.+-- \(L(s), L'(s), \ldots, L^{(len-1)}(s) / (len-1)!\). If /deflate/ is set,+-- computes the expansion of+-- +-- \[`\]+-- \[L(s,\chi) - \frac{\sum_{k=1}^q \chi(k)}{(s-1)q}\]+-- +-- instead. If /chi/ is a principal character, then this has the effect of+-- subtracting the pole with residue \(\sum_{k=1}^q \chi(k) = \phi(q) / q\)+-- that is located at \(s = 1\). In particular, when evaluated at+-- \(s = 1\), this gives the regular part of the Laurent expansion. When+-- /chi/ is non-principal, /deflate/ has no effect.+foreign import ccall "acb_dirichlet.h acb_dirichlet_l_jet"+ acb_dirichlet_l_jet :: Ptr CAcb -> Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CInt -> CLong -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h _acb_dirichlet_l_series"+ _acb_dirichlet_l_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CInt -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_l_series/ /res/ /s/ /G/ /chi/ /deflate/ /len/ /prec/ +-- +-- Sets /res/ to the power series \(L(s,\chi)\) where /s/ is a given power+-- series, truncating the result to length /len/. See @acb_dirichlet_l_jet@+-- for the meaning of the /deflate/ flag.+foreign import ccall "acb_dirichlet.h acb_dirichlet_l_series"+ acb_dirichlet_l_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CInt -> CLong -> CLong -> IO ()++-- Hardy Z-functions -----------------------------------------------------------++-- For convenience, setting both /G/ and /chi/ to /NULL/ in the following+-- methods selects the Riemann zeta function.+--+-- Currently, these methods require /chi/ to be a primitive character.+--+-- | /acb_dirichlet_hardy_theta/ /res/ /t/ /G/ /chi/ /len/ /prec/ +-- +-- Computes the phase function used to construct the Z-function. We have+-- +-- \[`\]+-- \[\theta(t) = -\frac{t}{2} \log(\pi/q) - \frac{i \log(\epsilon)}{2}+-- + \frac{\log \Gamma((s+\delta)/2) - \log \Gamma((1-s+\delta)/2)}{2i}\]+-- +-- where \(s = 1/2+it\), \(\delta\) is the parity of /chi/, and+-- \(\epsilon\) is the root number as computed by+-- @acb_dirichlet_root_number@. The first /len/ terms in the Taylor+-- expansion are written to the output.+foreign import ccall "acb_dirichlet.h acb_dirichlet_hardy_theta"+ acb_dirichlet_hardy_theta :: Ptr CAcb -> Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_hardy_z/ /res/ /t/ /G/ /chi/ /len/ /prec/ +-- +-- Computes the Hardy Z-function, also known as the Riemann-Siegel+-- Z-function \(Z(t) = e^{i \theta(t)} L(1/2+it)\), which is real-valued+-- for real /t/. The first /len/ terms in the Taylor expansion are written+-- to the output.+foreign import ccall "acb_dirichlet.h acb_dirichlet_hardy_z"+ acb_dirichlet_hardy_z :: Ptr CAcb -> Ptr CAcb -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h _acb_dirichlet_hardy_theta_series"+ _acb_dirichlet_hardy_theta_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_hardy_theta_series/ /res/ /t/ /G/ /chi/ /len/ /prec/ +-- +-- Sets /res/ to the power series \(\theta(t)\) where /t/ is a given power+-- series, truncating the result to length /len/.+foreign import ccall "acb_dirichlet.h acb_dirichlet_hardy_theta_series"+ acb_dirichlet_hardy_theta_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h _acb_dirichlet_hardy_z_series"+ _acb_dirichlet_hardy_z_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_hardy_z_series/ /res/ /t/ /G/ /chi/ /len/ /prec/ +-- +-- Sets /res/ to the power series \(Z(t)\) where /t/ is a given power+-- series, truncating the result to length /len/.+foreign import ccall "acb_dirichlet.h acb_dirichlet_hardy_z_series"+ acb_dirichlet_hardy_z_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> CLong -> IO ()++-- Gram points -----------------------------------------------------------------++-- | /acb_dirichlet_gram_point/ /res/ /n/ /G/ /chi/ /prec/ +-- +-- Sets /res/ to the /n/-th Gram point \(g_n\), defined as the unique+-- solution in \([7, \infty)\) of \(\theta(g_n) = \pi n\). Currently only+-- the Gram points corresponding to the Riemann zeta function are supported+-- and /G/ and /chi/ must both be set to /NULL/. Requires \(n \ge -1\).+foreign import ccall "acb_dirichlet.h acb_dirichlet_gram_point"+ acb_dirichlet_gram_point :: Ptr CArb -> Ptr CFmpz -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++-- Riemann zeta function zeros -------------------------------------------------++-- The following functions for counting and isolating zeros of the Riemann+-- zeta function use the ideas from the implementation of Turing\'s method+-- in mpmath < [Joh2018b]> by Juan Arias de Reyna, described in+-- < [Ari2012]>.+--+-- | /acb_dirichlet_turing_method_bound/ /p/ +-- +-- Computes an upper bound /B/ for the minimum number of consecutive good+-- Gram blocks sufficient to count nontrivial zeros of the Riemann zeta+-- function using Turing\'s method < [Tur1953]> as updated by < [Leh1970]>,+-- < [Bre1979]>, and < [Tru2011]>.+-- +-- Let \(N(T)\) denote the number of zeros (counted according to their+-- multiplicities) of \(\zeta(s)\) in the region+-- \(0 < \operatorname{Im}(s) \le T\). If at least /B/ consecutive Gram+-- blocks with union \([g_n, g_p)\) satisfy Rosser\'s rule, then+-- \(N(g_n) \le n + 1\) and \(N(g_p) \ge p + 1\).+foreign import ccall "acb_dirichlet.h acb_dirichlet_turing_method_bound"+ acb_dirichlet_turing_method_bound :: Ptr CFmpz -> IO CULong++-- | /_acb_dirichlet_definite_hardy_z/ /res/ /t/ /pprec/ +-- +-- Sets /res/ to the Hardy Z-function \(Z(t)\). The initial precision (*+-- /pprec/) is increased as necessary to determine the sign of \(Z(t)\).+-- The sign is returned.+foreign import ccall "acb_dirichlet.h _acb_dirichlet_definite_hardy_z"+ _acb_dirichlet_definite_hardy_z :: Ptr CArb -> Ptr CArf -> Ptr CLong -> IO CInt++-- | /_acb_dirichlet_isolate_gram_hardy_z_zero/ /a/ /b/ /n/ +-- +-- Uses Gram\'s law to compute an interval \((a, b)\) that contains the+-- /n/-th zero of the Hardy Z-function and no other zero. Requires+-- \(1 \le n \le 126\).+foreign import ccall "acb_dirichlet.h _acb_dirichlet_isolate_gram_hardy_z_zero"+ _acb_dirichlet_isolate_gram_hardy_z_zero :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> IO ()++-- | /_acb_dirichlet_isolate_rosser_hardy_z_zero/ /a/ /b/ /n/ +-- +-- Uses Rosser\'s rule to compute an interval \((a, b)\) that contains the+-- /n/-th zero of the Hardy Z-function and no other zero. Requires+-- \(1 \le n \le 13999526\).+foreign import ccall "acb_dirichlet.h _acb_dirichlet_isolate_rosser_hardy_z_zero"+ _acb_dirichlet_isolate_rosser_hardy_z_zero :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> IO ()++-- | /_acb_dirichlet_isolate_turing_hardy_z_zero/ /a/ /b/ /n/ +-- +-- Computes an interval \((a, b)\) that contains the /n/-th zero of the+-- Hardy Z-function and no other zero, following Turing\'s method. Requires+-- \(n \ge 2\).+foreign import ccall "acb_dirichlet.h _acb_dirichlet_isolate_turing_hardy_z_zero"+ _acb_dirichlet_isolate_turing_hardy_z_zero :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> IO ()++-- | /acb_dirichlet_isolate_hardy_z_zero/ /a/ /b/ /n/ +-- +-- Computes an interval \((a, b)\) that contains the /n/-th zero of the+-- Hardy Z-function and contains no other zero, using the most appropriate+-- underscore version of this function. Requires \(n \ge 1\).+foreign import ccall "acb_dirichlet.h acb_dirichlet_isolate_hardy_z_zero"+ acb_dirichlet_isolate_hardy_z_zero :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> IO ()++-- | /_acb_dirichlet_refine_hardy_z_zero/ /res/ /a/ /b/ /prec/ +-- +-- Sets /res/ to the unique zero of the Hardy Z-function in the interval+-- \((a, b)\).+foreign import ccall "acb_dirichlet.h _acb_dirichlet_refine_hardy_z_zero"+ _acb_dirichlet_refine_hardy_z_zero :: Ptr CArb -> Ptr CArf -> Ptr CArf -> CLong -> IO ()++-- -- | /acb_dirichlet_hardy_z_zero/ /res/ /n/ /prec/ +-- -- +-- -- Sets /res/ to the /n/-th zero of the Hardy Z-function, requiring+-- -- \(n \ge 1\).+-- foreign import ccall "acb_dirichlet.h acb_dirichlet_hardy_z_zero"+-- acb_dirichlet_hardy_z_zero :: Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- | /acb_dirichlet_hardy_z_zeros/ /res/ /n/ /len/ /prec/ +-- +-- Sets the entries of /res/ to /len/ consecutive zeros of the Hardy+-- Z-function, beginning with the /n/-th zero. Requires positive /n/.+foreign import ccall "acb_dirichlet.h acb_dirichlet_hardy_z_zeros"+ acb_dirichlet_hardy_z_zeros :: Ptr CArb -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- -- | /acb_dirichlet_zeta_zero/ /res/ /n/ /prec/ +-- -- +-- -- Sets /res/ to the /n/-th nontrivial zero of \(\zeta(s)\), requiring+-- -- \(n \ge 1\).+-- foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_zero"+-- acb_dirichlet_zeta_zero :: Ptr CAcb -> Ptr CFmpz -> CLong -> IO ()++-- | /acb_dirichlet_zeta_zeros/ /res/ /n/ /len/ /prec/ +-- +-- Sets the entries of /res/ to /len/ consecutive nontrivial zeros of+-- \(\zeta(s)\) beginning with the /n/-th zero. Requires positive /n/.+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_zeros"+ acb_dirichlet_zeta_zeros :: Ptr CAcb -> Ptr CFmpz -> CLong -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h _acb_dirichlet_exact_zeta_nzeros"+ _acb_dirichlet_exact_zeta_nzeros :: Ptr CFmpz -> Ptr CArf -> IO ()++-- | /acb_dirichlet_zeta_nzeros/ /res/ /t/ /prec/ +-- +-- Compute the number of zeros (counted according to their multiplicities)+-- of \(\zeta(s)\) in the region \(0 < \operatorname{Im}(s) \le t\).+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_nzeros"+ acb_dirichlet_zeta_nzeros :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /acb_dirichlet_backlund_s/ /res/ /t/ /prec/ +-- +-- Compute+-- \(S(t) = \frac{1}{\pi}\operatorname{arg}\zeta(\frac{1}{2} + it)\) where+-- the argument is defined by continuous variation of \(s\) in \(\zeta(s)\)+-- starting at \(s = 2\), then vertically to \(s = 2 + it\), then+-- horizontally to \(s = \frac{1}{2} + it\). In particular+-- \(\operatorname{arg}\) in this context is not the principal value of the+-- argument, and it cannot be computed directly by @acb_arg@. In practice+-- \(S(t)\) is computed as \(S(t) = N(t) - \frac{1}{\pi}\theta(t) - 1\)+-- where \(N(t)\) is @acb_dirichlet_zeta_nzeros@ and \(\theta(t)\) is+-- @acb_dirichlet_hardy_theta@.+foreign import ccall "acb_dirichlet.h acb_dirichlet_backlund_s"+ acb_dirichlet_backlund_s :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /acb_dirichlet_backlund_s_bound/ /res/ /t/ +-- +-- Compute an upper bound for \(|S(t)|\) quickly. Theorem 1 and the bounds+-- in (1.2) in < [Tru2014]> are used.+foreign import ccall "acb_dirichlet.h acb_dirichlet_backlund_s_bound"+ acb_dirichlet_backlund_s_bound :: Ptr CMag -> Ptr CArb -> IO ()++-- | /acb_dirichlet_zeta_nzeros_gram/ /res/ /n/ +-- +-- Compute \(N(g_n)\). That is, compute the number of zeros (counted+-- according to their multiplicities) of \(\zeta(s)\) in the region+-- \(0 < \operatorname{Im}(s) \le g_n\) where \(g_n\) is the /n/-th Gram+-- point. Requires \(n \ge -1\).+foreign import ccall "acb_dirichlet.h acb_dirichlet_zeta_nzeros_gram"+ acb_dirichlet_zeta_nzeros_gram :: Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /acb_dirichlet_backlund_s_gram/ /n/ +-- +-- Compute \(S(g_n)\) where \(g_n\) is the /n/-th Gram point. Requires+-- \(n \ge -1\).+foreign import ccall "acb_dirichlet.h acb_dirichlet_backlund_s_gram"+ acb_dirichlet_backlund_s_gram :: Ptr CFmpz -> IO CLong++-- Riemann zeta function zeros (Platt\'s method) -------------------------------++-- The following functions related to the Riemann zeta function use the+-- ideas and formulas described by David J. Platt in < [Pla2017]>.+--+-- | /acb_dirichlet_platt_scaled_lambda/ /res/ /t/ /prec/ +-- +-- Compute \(\Lambda(t) e^{\pi t/4}\) where+-- +-- \[`\]+-- \[\Lambda(t) = \pi^{-\frac{it}{2}}+-- \Gamma\left(\frac{\frac{1}{2}+it}{2}\right)+-- \zeta\left(\frac{1}{2} + it\right)\]+-- +-- is defined in the beginning of section 3 of < [Pla2017]>. As explained+-- in < [Pla2011]> this function has the same zeros as \(\zeta(1/2 + it)\)+-- and is real-valued by the functional equation, and the exponential+-- factor is designed to counteract the decay of the gamma factor as \(t\)+-- increases.+foreign import ccall "acb_dirichlet.h acb_dirichlet_platt_scaled_lambda"+ acb_dirichlet_platt_scaled_lambda :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_platt_scaled_lambda_vec"+ acb_dirichlet_platt_scaled_lambda_vec :: Ptr CArb -> Ptr CFmpz -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h acb_dirichlet_platt_multieval"+ acb_dirichlet_platt_multieval :: Ptr CArb -> Ptr CFmpz -> CLong -> CLong -> Ptr CArb -> Ptr CFmpz -> CLong -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_platt_multieval_threaded/ /res/ /T/ /A/ /B/ /h/ /J/ /K/ /sigma/ /prec/ +-- +-- Compute @acb_dirichlet_platt_scaled_lambda@ at \(N=AB\) points on a+-- grid, following the notation of < [Pla2017]>. The first point on the+-- grid is \(T - B/2\) and the distance between grid points is \(1/A\). The+-- product \(N=AB\) must be an even integer. The multieval versions+-- evaluate the function at all points on the grid simultaneously using+-- discrete Fourier transforms, and they require the four additional tuning+-- parameters /h/, /J/, /K/, and /sigma/. The /threaded/ multieval version+-- splits the computation over the number of threads returned by+-- /flint_get_num_threads()/, while the default multieval version chooses+-- whether to use multithreading automatically.+foreign import ccall "acb_dirichlet.h acb_dirichlet_platt_multieval_threaded"+ acb_dirichlet_platt_multieval_threaded :: Ptr CArb -> Ptr CFmpz -> CLong -> CLong -> Ptr CArb -> Ptr CFmpz -> CLong -> CLong -> CLong -> IO ()++-- | /acb_dirichlet_platt_ws_interpolation/ /res/ /deriv/ /t0/ /p/ /T/ /A/ /B/ /Ns_max/ /H/ /sigma/ /prec/ +-- +-- Compute @acb_dirichlet_platt_scaled_lambda@ at /t0/ by Gaussian-windowed+-- Whittaker-Shannon interpolation of points evaluated by+-- @acb_dirichlet_platt_scaled_lambda_vec@. The derivative is also+-- approximated if the output parameter /deriv/ is not /NULL/. /Ns_max/+-- defines the maximum number of supporting points to be used in the+-- interpolation on either side of /t0/. /H/ is the standard deviation of+-- the Gaussian window centered on /t0/ to be applied before the+-- interpolation. /sigma/ is an odd positive integer tuning parameter+-- \(\sigma \in 2\mathbb{Z}_{>0}+1\) used in computing error bounds.+foreign import ccall "acb_dirichlet.h acb_dirichlet_platt_ws_interpolation"+ acb_dirichlet_platt_ws_interpolation :: Ptr CArb -> Ptr CArf -> Ptr CArb -> Ptr CArb -> Ptr CFmpz -> CLong -> CLong -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()++foreign import ccall "acb_dirichlet.h _acb_dirichlet_platt_local_hardy_z_zeros"+ _acb_dirichlet_platt_local_hardy_z_zeros :: Ptr CArb -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CArb -> Ptr CFmpz -> CLong -> CLong -> CLong -> Ptr CArb -> CLong -> CLong -> IO CLong++foreign import ccall "acb_dirichlet.h acb_dirichlet_platt_local_hardy_z_zeros"+ acb_dirichlet_platt_local_hardy_z_zeros :: Ptr CArb -> Ptr CFmpz -> CLong -> CLong -> IO CLong++-- | /acb_dirichlet_platt_hardy_z_zeros/ /res/ /n/ /len/ /prec/ +-- +-- Sets at most the first /len/ entries of /res/ to consecutive zeros of+-- the Hardy Z-function starting with the /n/-th zero. The number of+-- obtained consecutive zeros is returned. The first two function variants+-- each make a single call to Platt\'s grid evaluation of the scaled Lambda+-- function, whereas the third variant performs as many evaluations as+-- necessary to obtain /len/ consecutive zeros. The final several+-- parameters of the underscored local variant have the same meanings as in+-- the functions @acb_dirichlet_platt_multieval@ and+-- @acb_dirichlet_platt_ws_interpolation@. The non-underscored variants+-- currently expect \(10^4 \leq n \leq 10^{23}\). The user has the option+-- of multi-threading through /flint_set_num_threads(numthreads)/.+foreign import ccall "acb_dirichlet.h acb_dirichlet_platt_hardy_z_zeros"+ acb_dirichlet_platt_hardy_z_zeros :: Ptr CArb -> Ptr CFmpz -> CLong -> CLong -> IO CLong++-- | /acb_dirichlet_platt_zeta_zeros/ /res/ /n/ /len/ /prec/ +-- +-- Sets at most the first /len/ entries of /res/ to consecutive zeros of+-- the Riemann zeta function starting with the /n/-th zero. The number of+-- obtained consecutive zeros is returned. It currently expects+-- \(10^4 \leq n \leq 10^{23}\). The user has the option of multi-threading+-- through /flint_set_num_threads(numthreads)/.+foreign import ccall "acb_dirichlet.h acb_dirichlet_platt_zeta_zeros"+ acb_dirichlet_platt_zeta_zeros :: Ptr CAcb -> Ptr CFmpz -> CLong -> CLong -> IO CLong+
+ src/Data/Number/Flint/Acb/Elliptic.hs view
@@ -0,0 +1,23 @@+{- |+This module supports computation of elliptic (doubly periodic)+functions, and their inverses, elliptic integrals. See+module [Data.Number.Flint.Acb.Modular]("Data.Number.Flint.Acb.Modular")+for the closely related modular forms and+Jacobi theta functions.++Warning: incomplete elliptic integrals have very complicated branch+structure when extended to complex variables. For some functions in this+module, branch cuts may be artifacts of the evaluation algorithm rather+than having a natural mathematical justification. The user should,+accordingly, watch out for edge cases where the functions implemented+here may differ from other systems or literature. There may also exist+points where a function should be well-defined but the implemented+algorithm fails to produce a finite result due to artificial internal+singularities.+-}++module Data.Number.Flint.Acb.Elliptic (+ module Data.Number.Flint.Acb.Elliptic.FFI+ ) where++import Data.Number.Flint.Acb.Elliptic.FFI
+ src/Data/Number/Flint/Acb/Elliptic/FFI.hsc view
@@ -0,0 +1,422 @@+{-|+module : Data.Number.Flint.Acb.Elliptic.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Acb.Elliptic.FFI (+ -- * Elliptic integrals and functions of complex variables+ -- * Complete elliptic integrals+ acb_elliptic_k+ , acb_elliptic_k_jet+ , _acb_elliptic_k_series+ , acb_elliptic_k_series+ , acb_elliptic_e+ , acb_elliptic_pi+ -- * Legendre incomplete elliptic integrals+ , acb_elliptic_f+ , acb_elliptic_e_inc+ , acb_elliptic_pi_inc+ -- * Carlson symmetric elliptic integrals+ , acb_elliptic_rf+ , acb_elliptic_rg+ , acb_elliptic_rj+ , acb_elliptic_rj_carlson+ , acb_elliptic_rj_integration+ , acb_elliptic_rc1+ -- * Weierstrass elliptic functions+ , acb_elliptic_p+ , acb_elliptic_p_prime+ , acb_elliptic_p_jet+ , _acb_elliptic_p_series+ , acb_elliptic_p_series+ , acb_elliptic_invariants+ , acb_elliptic_roots+ , acb_elliptic_inv_p+ , acb_elliptic_zeta+ , acb_elliptic_sigma+) where++-- Elliptic integrals and functions of complex variables -----------------------++import Foreign.Ptr+import Foreign.C.Types+import Foreign.C.String++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb.Types+import Data.Number.Flint.Acb.Poly++-- Complete elliptic integrals -------------------------------------------------++-- | /acb_elliptic_k/ /res/ /m/ /prec/ +-- +-- Computes the complete elliptic integral of the first kind+-- +-- \[`\]+-- \[K(m) = \int_0^{\pi/2} \frac{dt}{\sqrt{1-m \sin^2 t}}+-- = \int_0^1+-- \frac{dt}{\left(\sqrt{1-t^2}\right)\left(\sqrt{1-mt^2}\right)}\]+-- +-- using the arithmetic-geometric mean: \(K(m) = \pi / (2 M(\sqrt{1-m}))\).+foreign import ccall "acb_elliptic.h acb_elliptic_k"+ acb_elliptic_k :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_elliptic_k_jet/ /res/ /m/ /len/ /prec/ +-- +-- Sets the coefficients in the array /res/ to the power series expansion+-- of the complete elliptic integral of the first kind at the point /m/+-- truncated to length /len/, i.e. \(K(m+x) \in \mathbb{C}[[x]]\).+foreign import ccall "acb_elliptic.h acb_elliptic_k_jet"+ acb_elliptic_k_jet :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_elliptic.h _acb_elliptic_k_series"+ _acb_elliptic_k_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_elliptic_k_series/ /res/ /m/ /len/ /prec/ +-- +-- Sets /res/ to the complete elliptic integral of the first kind of the+-- power series /m/, truncated to length /len/.+foreign import ccall "acb_elliptic.h acb_elliptic_k_series"+ acb_elliptic_k_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_elliptic_e/ /res/ /m/ /prec/ +-- +-- Computes the complete elliptic integral of the second kind+-- +-- \[`\]+-- \[E(m) = \int_0^{\pi/2} \sqrt{1-m \sin^2 t} \, dt =+-- \int_0^1+-- \frac{\sqrt{1-mt^2}}{\sqrt{1-t^2}} \, dt\]+-- +-- using \(E(m) = (1-m)(2m K'(m) + K(m))\) (where the prime denotes a+-- derivative, not a complementary integral).+foreign import ccall "acb_elliptic.h acb_elliptic_e"+ acb_elliptic_e :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_elliptic_pi/ /res/ /n/ /m/ /prec/ +-- +-- Evaluates the complete elliptic integral of the third kind+-- +-- \[`\]+-- \[\Pi(n, m) = \int_0^{\pi/2}+-- \frac{dt}{(1-n \sin^2 t) \sqrt{1-m \sin^2 t}} =+-- \int_0^1+-- \frac{dt}{(1-nt^2) \sqrt{1-t^2} \sqrt{1-mt^2}}.\]+-- +-- This implementation currently uses the same algorithm as the+-- corresponding incomplete integral. It is therefore less efficient than+-- the implementations of the first two complete elliptic integrals which+-- use the AGM.+foreign import ccall "acb_elliptic.h acb_elliptic_pi"+ acb_elliptic_pi :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Legendre incomplete elliptic integrals --------------------------------------++-- | /acb_elliptic_f/ /res/ /phi/ /m/ /pi/ /prec/ +-- +-- Evaluates the Legendre incomplete elliptic integral of the first kind,+-- given by+-- +-- \[`\]+-- \[F(\phi,m) = \int_0^{\phi} \frac{dt}{\sqrt{1-m \sin^2 t}}+-- = \int_0^{\sin \phi}+-- \frac{dt}{\left(\sqrt{1-t^2}\right)\left(\sqrt{1-mt^2}\right)}\]+-- +-- on the standard strip \(-\pi/2 \le \operatorname{Re}(\phi) \le \pi/2\).+-- Outside this strip, the function extends quasiperiodically as+-- +-- \[`\]+-- \[F(\phi + n \pi, m) = 2 n K(m) + F(\phi,m), n \in \mathbb{Z}.\]+-- +-- Inside the standard strip, the function is computed via the symmetric+-- integral \(R_F\).+-- +-- If the flag /pi/ is set to 1, the variable \(\phi\) is replaced by+-- \(\pi \phi\), changing the quasiperiod to 1.+-- +-- The function reduces to a complete elliptic integral of the first kind+-- when \(\phi = \frac{\pi}{2}\); that is,+-- \(F\left(\frac{\pi}{2}, m\right) = K(m)\).+foreign import ccall "acb_elliptic.h acb_elliptic_f"+ acb_elliptic_f :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_elliptic_e_inc/ /res/ /phi/ /m/ /pi/ /prec/ +-- +-- Evaluates the Legendre incomplete elliptic integral of the second kind,+-- given by+-- +-- \[`\]+-- \[E(\phi,m) = \int_0^{\phi} \sqrt{1-m \sin^2 t} \, dt =+-- \int_0^{\sin \phi}+-- \frac{\sqrt{1-mt^2}}{\sqrt{1-t^2}} \, dt\]+-- +-- on the standard strip \(-\pi/2 \le \operatorname{Re}(\phi) \le \pi/2\).+-- Outside this strip, the function extends quasiperiodically as+-- +-- \[`\]+-- \[E(\phi + n \pi, m) = 2 n E(m) + E(\phi,m), n \in \mathbb{Z}.\]+-- +-- Inside the standard strip, the function is computed via the symmetric+-- integrals \(R_F\) and \(R_D\).+-- +-- If the flag /pi/ is set to 1, the variable \(\phi\) is replaced by+-- \(\pi \phi\), changing the quasiperiod to 1.+-- +-- The function reduces to a complete elliptic integral of the second kind+-- when \(\phi = \frac{\pi}{2}\); that is,+-- \(E\left(\frac{\pi}{2}, m\right) = E(m)\).+foreign import ccall "acb_elliptic.h acb_elliptic_e_inc"+ acb_elliptic_e_inc :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_elliptic_pi_inc/ /res/ /n/ /phi/ /m/ /pi/ /prec/ +-- +-- Evaluates the Legendre incomplete elliptic integral of the third kind,+-- given by+-- +-- \[`\]+-- \[\Pi(n, \phi, m) = \int_0^{\phi}+-- \frac{dt}{(1-n \sin^2 t) \sqrt{1-m \sin^2 t}} =+-- \int_0^{\sin \phi}+-- \frac{dt}{(1-nt^2) \sqrt{1-t^2} \sqrt{1-mt^2}}\]+-- +-- on the standard strip \(-\pi/2 \le \operatorname{Re}(\phi) \le \pi/2\).+-- Outside this strip, the function extends quasiperiodically as+-- +-- \[`\]+-- \[\Pi(n, \phi + k \pi, m) = 2 k \Pi(n,m) + \Pi(n,\phi,m), k \in \mathbb{Z}.\]+-- +-- Inside the standard strip, the function is computed via the symmetric+-- integrals \(R_F\) and \(R_J\).+-- +-- If the flag /pi/ is set to 1, the variable \(\phi\) is replaced by+-- \(\pi \phi\), changing the quasiperiod to 1.+-- +-- The function reduces to a complete elliptic integral of the third kind+-- when \(\phi = \frac{\pi}{2}\); that is,+-- \(\Pi\left(n, \frac{\pi}{2}, m\right) = \Pi(n, m)\).+foreign import ccall "acb_elliptic.h acb_elliptic_pi_inc"+ acb_elliptic_pi_inc :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- Carlson symmetric elliptic integrals ----------------------------------------++-- Carlson symmetric forms are the preferred form of incomplete elliptic+-- integrals, due to their neat properties and relatively simple+-- computation based on duplication theorems. There are five named+-- functions: \(R_F, R_G, R_J\), and \(R_C\), \(R_D\) which are special+-- cases of \(R_F\) and \(R_J\) respectively. We largely follow the+-- definitions and algorithms in < [Car1995]> and chapter 19 in+-- < [NIST2012]>.+--+-- | /acb_elliptic_rf/ /res/ /x/ /y/ /z/ /flags/ /prec/ +-- +-- Evaluates the Carlson symmetric elliptic integral of the first kind+-- +-- \[`\]+-- \[R_F(x,y,z) = \frac{1}{2}+-- \int_0^{\infty} \frac{dt}{\sqrt{(t+x)(t+y)(t+z)}}\]+-- +-- where the square root extends continuously from positive infinity. The+-- integral is well-defined for \(x,y,z \notin (-\infty,0)\), and with at+-- most one of \(x,y,z\) being zero. When some parameters are negative real+-- numbers, the function is still defined by analytic continuation.+-- +-- In general, one or more duplication steps are applied until \(x,y,z\)+-- are close enough to use a multivariate Taylor series.+-- +-- The special case+-- \(R_C(x, y) = R_F(x, y, y) = \frac{1}{2} \int_0^{\infty} (t+x)^{-1/2} (t+y)^{-1} dt\)+-- may be computed by setting /y/ and /z/ to the same variable. (This case+-- is not yet handled specially, but might be optimized in the future.)+-- +-- The /flags/ parameter is reserved for future use and currently does+-- nothing. Passing 0 results in default behavior.+foreign import ccall "acb_elliptic.h acb_elliptic_rf"+ acb_elliptic_rf :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_elliptic_rg/ /res/ /x/ /y/ /z/ /flags/ /prec/ +-- +-- Evaluates the Carlson symmetric elliptic integral of the second kind+-- +-- \[`\]+-- \[R_G(x,y,z) = \frac{1}{4} \int_0^{\infty}+-- \frac{t}{\sqrt{(t+x)(t+y)(t+z)}}+-- \left( \frac{x}{t+x} + \frac{y}{t+y} + \frac{z}{t+z}\right) dt\]+-- +-- where the square root is taken continuously as in \(R_F\). The+-- evaluation is done by expressing \(R_G\) in terms of \(R_F\) and+-- \(R_D\). There are no restrictions on the variables.+foreign import ccall "acb_elliptic.h acb_elliptic_rg"+ acb_elliptic_rg :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++foreign import ccall "acb_elliptic.h acb_elliptic_rj"+ acb_elliptic_rj :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++foreign import ccall "acb_elliptic.h acb_elliptic_rj_carlson"+ acb_elliptic_rj_carlson :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_elliptic_rj_integration/ /res/ /x/ /y/ /z/ /p/ /flags/ /prec/ +-- +-- Evaluates the Carlson symmetric elliptic integral of the third kind+-- +-- \[`\]+-- \[R_J(x,y,z,p) = \frac{3}{2}+-- \int_0^{\infty} \frac{dt}{(t+p)\sqrt{(t+x)(t+y)(t+z)}}\]+-- +-- where the square root is taken continuously as in \(R_F\).+-- +-- Three versions of this function are available: the /carlson/ version+-- applies one or more duplication steps until \(x,y,z,p\) are close enough+-- to use a multivariate Taylor series.+-- +-- The duplication algorithm is not correct for all possible combinations+-- of complex variables, since the square roots taken during the+-- computation can introduce spurious branch cuts. According to+-- < [Car1995]>, a sufficient (but not necessary) condition for correctness+-- is that /x/, /y/, /z/ have nonnegative real part and that /p/ has+-- positive real part.+-- +-- In other cases, the algorithm /might/ still be correct, but no attempt+-- is made to check this; it is up to the user to verify that the+-- duplication algorithm is appropriate for the given parameters before+-- calling this function.+-- +-- The /integration/ algorithm uses explicit numerical integration to+-- translate the parameters to the right half-plane. This is reliable but+-- can be slow.+-- +-- The default method uses the /carlson/ algorithm when it is certain to be+-- correct, and otherwise falls back to the slow /integration/ algorithm.+-- +-- The special case \(R_D(x, y, z) = R_J(x, y, z, z)\) may be computed by+-- setting /z/ and /p/ to the same variable. This case is handled specially+-- to avoid redundant arithmetic operations. In this case, the /carlson/+-- algorithm is correct for all /x/, /y/ and /z/.+-- +-- The /flags/ parameter is reserved for future use and currently does+-- nothing. Passing 0 results in default behavior.+foreign import ccall "acb_elliptic.h acb_elliptic_rj_integration"+ acb_elliptic_rj_integration :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_elliptic_rc1/ /res/ /x/ /prec/ +-- +-- This helper function computes the special case+-- \(R_C(1, 1+x) = \operatorname{atan}(\sqrt{x})/\sqrt{x} = {}_2F_1(1,1/2,3/2,-x)\),+-- which is needed in the evaluation of \(R_J\).+foreign import ccall "acb_elliptic.h acb_elliptic_rc1"+ acb_elliptic_rc1 :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Weierstrass elliptic functions ----------------------------------------------++-- Elliptic functions may be defined on a general lattice Lambda = {m+-- 2omega_1 + n 2omega_2: m, n in mathbb{Z}} with half-periods+-- \(\omega_1, \omega_2\). We simplify by setting 2omega_1 = 1, 2omega_2 =+-- tau with \(\operatorname{im}(\tau) > 0\). To evaluate the functions on a+-- general lattice, it is enough to make a linear change of variables. The+-- main reference is chapter 23 in < [NIST2012]>.+--+-- | /acb_elliptic_p/ /res/ /z/ /tau/ /prec/ +-- +-- Computes Weierstrass\'s elliptic function+-- +-- \[`\]+-- \[\wp(z, \tau) = \frac{1}{z^2} + \sum_{n^2+m^2 \ne 0}+-- \left[ \frac{1}{(z+m+n\tau)^2} - \frac{1}{(m+n\tau)^2} \right]\]+-- +-- which satisfies+-- \(\wp(z, \tau) = \wp(z + 1, \tau) = \wp(z + \tau, \tau)\). To evaluate+-- the function efficiently, we use the formula+-- +-- \[`\]+-- \[\wp(z, \tau) = \pi^2 \theta_2^2(0,\tau) \theta_3^2(0,\tau)+-- \frac{\theta_4^2(z,\tau)}{\theta_1^2(z,\tau)} -+-- \frac{\pi^2}{3} \left[ \theta_2^4(0,\tau) + \theta_3^4(0,\tau)\right].\]+foreign import ccall "acb_elliptic.h acb_elliptic_p"+ acb_elliptic_p :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_elliptic_p_prime/ /res/ /z/ /tau/ /prec/ +-- +-- Computes the derivative \(\wp'(z, \tau)\) of Weierstrass\'s elliptic+-- function \(\wp(z, \tau)\).+foreign import ccall "acb_elliptic.h acb_elliptic_p_prime"+ acb_elliptic_p_prime :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_elliptic_p_jet/ /res/ /z/ /tau/ /len/ /prec/ +-- +-- Computes the formal power series+-- \(\wp(z + x, \tau) \in \mathbb{C}[[x]]\), truncated to length /len/. In+-- particular, with /len/ = 2, simultaneously computes+-- \(\wp(z, \tau), \wp'(z, \tau)\) which together generate the field of+-- elliptic functions with periods 1 and \(\tau\).+foreign import ccall "acb_elliptic.h acb_elliptic_p_jet"+ acb_elliptic_p_jet :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_elliptic.h _acb_elliptic_p_series"+ _acb_elliptic_p_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_elliptic_p_series/ /res/ /z/ /tau/ /len/ /prec/ +-- +-- Sets /res/ to the Weierstrass elliptic function of the power series /z/,+-- with periods 1 and /tau/, truncated to length /len/.+foreign import ccall "acb_elliptic.h acb_elliptic_p_series"+ acb_elliptic_p_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_elliptic_invariants/ /g2/ /g3/ /tau/ /prec/ +-- +-- Computes the lattice invariants \(g_2, g_3\). The Weierstrass elliptic+-- function satisfies the differential equation+-- \([\wp'(z, \tau)]^2 = 4 [\wp(z,\tau)]^3 - g_2 \wp(z,\tau) - g_3\). Up to+-- constant factors, the lattice invariants are the first two Eisenstein+-- series (see @acb_modular_eisenstein@).+foreign import ccall "acb_elliptic.h acb_elliptic_invariants"+ acb_elliptic_invariants :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_elliptic_roots/ /e1/ /e2/ /e3/ /tau/ /prec/ +-- +-- Computes the lattice roots \(e_1, e_2, e_3\), which are the roots of the+-- polynomial \(4z^3 - g_2 z - g_3\).+foreign import ccall "acb_elliptic.h acb_elliptic_roots"+ acb_elliptic_roots :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_elliptic_inv_p/ /res/ /z/ /tau/ /prec/ +-- +-- Computes the inverse of the Weierstrass elliptic function, which+-- satisfies \(\wp(\wp^{-1}(z, \tau), \tau) = z\). This function is given+-- by the elliptic integral+-- +-- \[`\]+-- \[\wp^{-1}(z, \tau) = \frac{1}{2} \int_z^{\infty} \frac{dt}{\sqrt{(t-e_1)(t-e_2)(t-e_3)}}+-- = R_F(z-e_1,z-e_2,z-e_3).\]+foreign import ccall "acb_elliptic.h acb_elliptic_inv_p"+ acb_elliptic_inv_p :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_elliptic_zeta/ /res/ /z/ /tau/ /prec/ +-- +-- Computes the Weierstrass zeta function+-- +-- \[`\]+-- \[\zeta(z, \tau) = \frac{1}{z} + \sum_{n^2+m^2 \ne 0}+-- \left[ \frac{1}{z-m-n\tau} + \frac{1}{m+n\tau} + \frac{z}{(m+n\tau)^2} \right]\]+-- +-- which is quasiperiodic with+-- \(\zeta(z + 1, \tau) = \zeta(z, \tau) + \zeta(1/2, \tau)\) and+-- \(\zeta(z + \tau, \tau) = \zeta(z, \tau) + \zeta(\tau/2, \tau)\).+foreign import ccall "acb_elliptic.h acb_elliptic_zeta"+ acb_elliptic_zeta :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_elliptic_sigma/ /res/ /z/ /tau/ /prec/ +-- +-- Computes the Weierstrass sigma function+-- +-- \[`\]+-- \[\sigma(z, \tau) = z \prod_{n^2+m^2 \ne 0}+-- \left[ \left(1-\frac{z}{m+n\tau}\right)+-- \exp\left(\frac{z}{m+n\tau} + \frac{z^2}{2(m+n\tau)^2} \right) \right]\]+-- +-- which is quasiperiodic with+-- \(\sigma(z + 1, \tau) = -e^{2 \zeta(1/2, \tau) (z+1/2)} \sigma(z, \tau)\)+-- and+-- \(\sigma(z + \tau, \tau) = -e^{2 \zeta(\tau/2, \tau) (z+\tau/2)} \sigma(z, \tau)\).+foreign import ccall "acb_elliptic.h acb_elliptic_sigma"+ acb_elliptic_sigma :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()+
+ src/Data/Number/Flint/Acb/FFI.hsc view
@@ -0,0 +1,1903 @@+{-|+module : Data.Number.Flint.Acb.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Acb.FFI (+ -- * Complex numbers+ -- * Types+ Acb (..)+ , CAcb (..)+ , newAcb+ , withAcb+ , withNewAcb+ , withAcbRe+ , withAcbIm+ -- * Memory management+ , acb_init+ , acb_clear+ , _acb_vec_init+ , _acb_vec_clear+ , acb_allocated_bytes+ , _acb_vec_allocated_bytes+ , _acb_vec_estimate_allocated_bytes+ -- * Basic manipulation+ , acb_zero+ , acb_one+ , acb_onei+ , acb_set+ , acb_set_ui+ , acb_set_si+ , acb_set_d+ , acb_set_fmpz+ , acb_set_arb+ , acb_set_si_si+ , acb_set_d_d+ , acb_set_fmpz_fmpz+ , acb_set_arb_arb+ , acb_set_fmpq+ , acb_set_round+ , acb_set_round_fmpz+ , acb_set_round_arb+ , acb_swap+ , acb_add_error_arf+ , acb_add_error_mag+ , acb_add_error_arb+ , acb_get_mid+ -- * Input and output+ , acb_get_str+ , acb_get_strd+ , acb_get_strn+ , acb_print+ , acb_fprint+ , acb_printd+ , acb_fprintd+ , acb_printn+ , acb_fprintn+ -- * Random number generation+ , acb_randtest+ , acb_randtest_special+ , acb_randtest_precise+ , acb_randtest_param+ -- * Precision and comparisons+ , acb_is_zero+ , acb_is_one+ , acb_is_finite+ , acb_is_exact+ , acb_is_int+ , acb_is_int_2exp_si+ , acb_equal+ , acb_equal_si+ , acb_eq+ , acb_ne+ , acb_overlaps+ , acb_union+ , acb_get_abs_ubound_arf+ , acb_get_abs_lbound_arf+ , acb_get_rad_ubound_arf+ , acb_get_mag+ , acb_get_mag_lower+ , acb_contains_fmpq+ , acb_contains_fmpz+ , acb_contains+ , acb_contains_zero+ , acb_contains_int+ , acb_contains_interior+ , acb_rel_error_bits+ , acb_rel_accuracy_bits+ , acb_rel_one_accuracy_bits+ , acb_bits+ , acb_indeterminate+ , acb_trim+ , acb_is_real+ , acb_get_unique_fmpz+ -- * Complex parts+ , acb_get_real+ , acb_get_imag+ , acb_arg+ , acb_abs+ , acb_sgn+ , acb_csgn+ -- * Arithmetic+ , acb_neg+ , acb_neg_round+ , acb_conj+ , acb_add_ui+ , acb_add_si+ , acb_add_fmpz+ , acb_add_arb+ , acb_add+ , acb_sub_ui+ , acb_sub_si+ , acb_sub_fmpz+ , acb_sub_arb+ , acb_sub+ , acb_mul_onei+ , acb_div_onei+ , acb_mul_ui+ , acb_mul_si+ , acb_mul_fmpz+ , acb_mul_arb+ , acb_mul+ , acb_mul_2exp_si+ , acb_mul_2exp_fmpz+ , acb_sqr+ , acb_cube+ , acb_addmul+ , acb_addmul_ui+ , acb_addmul_si+ , acb_addmul_fmpz+ , acb_addmul_arb+ , acb_submul+ , acb_submul_ui+ , acb_submul_si+ , acb_submul_fmpz+ , acb_submul_arb+ , acb_inv+ , acb_div_ui+ , acb_div_si+ , acb_div_fmpz+ , acb_div_arb+ , acb_div+ -- * Dot product+ , acb_dot_precise+ , acb_approx_dot+ , acb_dot_ui+ -- * Mathematical constants+ , acb_const_pi+ -- * Powers and roots+ , acb_sqrt+ , acb_sqrt_analytic+ , acb_rsqrt+ , acb_rsqrt_analytic+ , acb_quadratic_roots_fmpz+ , acb_root_ui+ , acb_pow_fmpz+ , acb_pow_ui+ , acb_pow_si+ , acb_pow_arb+ , acb_pow+ , acb_pow_analytic+ , acb_unit_root+ -- * Exponentials and logarithms+ , acb_exp+ , acb_exp_pi_i+ , acb_exp_invexp+ , acb_expm1+ , acb_log+ , acb_log_analytic+ , acb_log1p+ -- * Trigonometric functions+ , acb_sin+ , acb_cos+ , acb_sin_cos+ , acb_tan+ , acb_cot+ , acb_sin_pi+ , acb_cos_pi+ , acb_sin_cos_pi+ , acb_tan_pi+ , acb_cot_pi+ , acb_sec+ , acb_csc+ , acb_csc_pi+ , acb_sinc+ , acb_sinc_pi+ -- * Inverse trigonometric functions+ , acb_asin+ , acb_acos+ , acb_atan+ -- * Hyperbolic functions+ , acb_sinh+ , acb_cosh+ , acb_sinh_cosh+ , acb_tanh+ , acb_coth+ , acb_sech+ , acb_csch+ -- * Inverse hyperbolic functions+ , acb_asinh+ , acb_acosh+ , acb_atanh+ -- * Lambert W function+ , acb_lambertw_asymp+ , acb_lambertw_check_branch+ , acb_lambertw_bound_deriv+ , acb_lambertw+ -- * Rising factorials+ , acb_rising_ui+ -- * Gamma function+ , acb_gamma+ , acb_rgamma+ , acb_lgamma+ , acb_digamma+ , acb_log_sin_pi+ , acb_polygamma+ , acb_barnes_g+ , acb_log_barnes_g+ -- * Zeta function+ , acb_zeta+ , acb_hurwitz_zeta+ , acb_bernoulli_poly_ui+ -- * Polylogarithms+ , acb_polylog+ , acb_polylog_si+ -- * Arithmetic-geometric mean+ , acb_agm1+ , acb_agm1_cpx+ , acb_agm+ -- * Other special functions+ , acb_chebyshev_t_ui+ , acb_chebyshev_u_ui+ , acb_chebyshev_t2_ui+ , acb_chebyshev_u2_ui+ -- * Piecewise real functions+ , acb_real_abs+ , acb_real_sgn+ , acb_real_heaviside+ , acb_real_floor+ , acb_real_ceil+ , acb_real_max+ , acb_real_min+ , acb_real_sqrtpos+ -- * Vector functions+ , _acb_vec_zero+ , _acb_vec_is_zero+ , _acb_vec_is_real+ , _acb_vec_set+ , _acb_vec_set_round+ , _acb_vec_swap+ , _acb_vec_neg+ , _acb_vec_add+ , _acb_vec_sub+ , _acb_vec_scalar_submul+ , _acb_vec_scalar_addmul+ , _acb_vec_scalar_mul+ , _acb_vec_scalar_mul_ui+ , _acb_vec_scalar_mul_2exp_si+ , _acb_vec_scalar_mul_onei+ , _acb_vec_scalar_div_ui+ , _acb_vec_scalar_div+ , _acb_vec_scalar_mul_arb+ , _acb_vec_scalar_div_arb+ , _acb_vec_scalar_mul_fmpz+ , _acb_vec_scalar_div_fmpz+ , _acb_vec_bits+ , _acb_vec_set_powers+ , _acb_vec_unit_roots+ , _acb_vec_add_error_arf_vec+ , _acb_vec_add_error_mag_vec+ , _acb_vec_indeterminate+ , _acb_vec_trim+ , _acb_vec_get_unique_fmpz_vec+ , _acb_vec_sort_pretty+) where ++-- Complex numbers -------------------------------------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Alloc (free)+import Foreign.Marshal.Array (advancePtr)++import Data.Typeable++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb.Types++#include <flint/acb.h>++-- Types -----------------------------------------------------------------------++-- | Create new `Acb`+newAcb = do+ x <- mallocForeignPtr+ withForeignPtr x acb_init+ addForeignPtrFinalizer p_acb_clear x+ return $ Acb x++-- | Apply function `f` to `Acb`+withAcb (Acb p) f = do+ withForeignPtr p $ \fp -> (Acb p,) <$> f fp++-- | Apply function `f` to new `Acb`+withNewAcb f = do+ x <- newAcb+ withAcb x f++-- | Apply function `f` to real part of `Acb`+withAcbRe :: Acb -> (Ptr CArb -> IO t) -> IO (Acb, t)+withAcbRe (Acb p) f = do+ withForeignPtr p $ \fp -> do+ withForeignPtr p $ \fp -> (Acb p,) <$> f (castPtr fp)++-- | Apply function `f` to imaginary part of `Acb`+withAcbIm :: Acb -> (Ptr CArb -> IO t) -> IO (Acb, t)+withAcbIm (Acb p) f = do+ withForeignPtr p $ \fp -> do+ withForeignPtr p $ \fp -> (Acb p,) <$> f (castPtr fp `advancePtr` 1)++instance Storable CAcb where+ sizeOf _ = #{size acb_t}+ alignment _ = #{alignment acb_t}+ peek = error "CAcb.peek not defined."+ poke = error "CAcb.poke not defined."+ +-- Memory management -----------------------------------------------------------++-- | /acb_init/ /x/ +-- +-- Initializes the variable /x/ for use, and sets its value to zero.+foreign import ccall "acb.h acb_init"+ acb_init :: Ptr CAcb -> IO ()++-- | /acb_clear/ /x/ +-- +-- Clears the variable /x/, freeing or recycling its allocated memory.+foreign import ccall "acb.h acb_clear"+ acb_clear :: Ptr CAcb -> IO ()++foreign import ccall "acb.h &acb_clear"+ p_acb_clear :: FunPtr (Ptr CAcb -> IO ())++-- | /_acb_vec_init/ /n/ +-- +-- Returns a pointer to an array of /n/ initialized /acb_struct/:s.+foreign import ccall "acb.h _acb_vec_init"+ _acb_vec_init :: CLong -> IO (Ptr CAcb)++-- | /_acb_vec_clear/ /v/ /n/ +-- +-- Clears an array of /n/ initialized /acb_struct/:s.+foreign import ccall "acb.h _acb_vec_clear"+ _acb_vec_clear :: Ptr CAcb -> CLong -> IO ()++-- | /acb_allocated_bytes/ /x/ +-- +-- Returns the total number of bytes heap-allocated internally by this+-- object. The count excludes the size of the structure itself. Add+-- @sizeof(acb_struct)@ to get the size of the object as a whole.+foreign import ccall "acb.h acb_allocated_bytes"+ acb_allocated_bytes :: Ptr CAcb -> IO CLong++-- | /_acb_vec_allocated_bytes/ /vec/ /len/ +-- +-- Returns the total number of bytes allocated for this vector, i.e. the+-- space taken up by the vector itself plus the sum of the internal heap+-- allocation sizes for all its member elements.+foreign import ccall "acb.h _acb_vec_allocated_bytes"+ _acb_vec_allocated_bytes :: Ptr CAcb -> CLong -> IO CLong++-- | /_acb_vec_estimate_allocated_bytes/ /len/ /prec/ +-- +-- Estimates the number of bytes that need to be allocated for a vector of+-- /len/ elements with /prec/ bits of precision, including the space for+-- internal limb data. See comments for+-- @_arb_vec_estimate_allocated_bytes@.+foreign import ccall "acb.h _acb_vec_estimate_allocated_bytes"+ _acb_vec_estimate_allocated_bytes :: CLong -> CLong -> IO CDouble++-- Basic manipulation ----------------------------------------------------------++foreign import ccall "acb.h acb_zero"+ acb_zero :: Ptr CAcb -> IO ()++foreign import ccall "acb.h acb_one"+ acb_one :: Ptr CAcb -> IO ()++-- | /acb_onei/ /z/ +-- +-- Sets /z/ respectively to 0, 1, \(i = \sqrt{-1}\).+foreign import ccall "acb.h acb_onei"+ acb_onei :: Ptr CAcb -> IO ()++foreign import ccall "acb.h acb_set"+ acb_set :: Ptr CAcb -> Ptr CAcb -> IO ()++foreign import ccall "acb.h acb_set_ui"+ acb_set_ui :: Ptr CAcb -> CULong -> IO ()++foreign import ccall "acb.h acb_set_si"+ acb_set_si :: Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_set_d"+ acb_set_d :: Ptr CAcb -> CDouble -> IO ()++foreign import ccall "acb.h acb_set_fmpz"+ acb_set_fmpz :: Ptr CAcb -> Ptr CFmpz -> IO ()++-- | /acb_set_arb/ /z/ /c/ +-- +-- Sets /z/ to the value of /x/.+foreign import ccall "acb.h acb_set_arb"+ acb_set_arb :: Ptr CAcb -> Ptr CArb -> IO ()++foreign import ccall "acb.h acb_set_si_si"+ acb_set_si_si :: Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb.h acb_set_d_d"+ acb_set_d_d :: Ptr CAcb -> CDouble -> CDouble -> IO ()++foreign import ccall "acb.h acb_set_fmpz_fmpz"+ acb_set_fmpz_fmpz :: Ptr CAcb -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /acb_set_arb_arb/ /z/ /x/ /y/ +-- +-- Sets the real and imaginary part of /z/ to the values /x/ and /y/+-- respectively+foreign import ccall "acb.h acb_set_arb_arb"+ acb_set_arb_arb :: Ptr CAcb -> Ptr CArb -> Ptr CArb -> IO ()++foreign import ccall "acb.h acb_set_fmpq"+ acb_set_fmpq :: Ptr CAcb -> Ptr CFmpq -> CLong -> IO ()++foreign import ccall "acb.h acb_set_round"+ acb_set_round :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_set_round_fmpz"+ acb_set_round_fmpz :: Ptr CAcb -> Ptr CFmpz -> CLong -> IO ()++-- | /acb_set_round_arb/ /z/ /x/ /prec/ +-- +-- Sets /z/ to /x/, rounded to /prec/ bits.+foreign import ccall "acb.h acb_set_round_arb"+ acb_set_round_arb :: Ptr CAcb -> Ptr CArb -> CLong -> IO ()++-- | /acb_swap/ /z/ /x/ +-- +-- Swaps /z/ and /x/ efficiently.+foreign import ccall "acb.h acb_swap"+ acb_swap :: Ptr CAcb -> Ptr CAcb -> IO ()++foreign import ccall "acb.h acb_add_error_arf"+ acb_add_error_arf :: Ptr CAcb -> Ptr CArf -> IO ()++foreign import ccall "acb.h acb_add_error_mag"+ acb_add_error_mag :: Ptr CAcb -> Ptr CMag -> IO ()++-- | /acb_add_error_arb/ /x/ /err/ +-- +-- Adds /err/ to the error bounds of both the real and imaginary parts of+-- /x/, modifying /x/ in-place.+foreign import ccall "acb.h acb_add_error_arb"+ acb_add_error_arb :: Ptr CAcb -> Ptr CArb -> IO ()++-- | /acb_get_mid/ /m/ /x/ +-- +-- Sets /m/ to the midpoint of /x/.+foreign import ccall "acb.h acb_get_mid"+ acb_get_mid :: Ptr CAcb -> Ptr CAcb -> IO ()++-- Input and output ------------------------------------------------------------++foreign import ccall "acb.h acb_get_str"+ acb_get_str :: Ptr CAcb -> IO CString++foreign import ccall "acb.h acb_get_strd"+ acb_get_strd :: Ptr CAcb -> CLong -> IO CString++foreign import ccall "acb.h acb_get_strn"+ acb_get_strn :: Ptr CAcb -> CLong -> ArbStrOption -> IO CString++-- The /acb_print.../ functions print to standard output, while+-- /acb_fprint.../ functions print to the stream /file/.+--+acb_print :: Ptr CAcb -> IO ()+acb_print x = do+ cstr <- acb_get_str x+ str <- peekCString cstr+ free cstr+ putStr str++-- | /acb_fprint/ /file/ /x/ +-- +-- Prints the internal representation of /x/.+foreign import ccall "acb.h acb_fprint"+ acb_fprint :: Ptr CFile -> Ptr CAcb -> IO ()++-- | /acb_printd/ /file/ /x/ /digits/ +-- +-- Prints /x/ in decimal to stdout. The printed value of the radius is+-- not adjusted to compensate for the fact that the binary-to-decimal+-- conversion of both the midpoint and the radius introduces+-- additional error.+acb_printd :: Ptr CAcb -> CLong -> IO ()+acb_printd x prec = do+ cstr <- acb_get_strd x prec+ str <- peekCString cstr+ free cstr+ putStr str++-- | /acb_fprintd/ /file/ /x/ /digits/ +-- +-- Prints /x/ in decimal to stream /file/. The printed value of the+-- radius is not adjusted to compensate for the fact that the+-- binary-to-decimal conversion of both the midpoint and the radius+-- introduces additional error.+foreign import ccall "acb.h acb_fprintd"+ acb_fprintd :: Ptr CFile -> Ptr CAcb -> CLong -> IO ()++acb_printn :: Ptr CAcb -> CLong -> ArbStrOption -> IO ()+acb_printn x prec opts = do+ cstr <- acb_get_strn x prec opts+ str <- peekCString cstr+ free cstr+ putStr str++-- | /acb_fprintn/ /file/ /x/ /digits/ /flags/ +-- +-- Prints a nice decimal representation of /x/, using the format of+-- @arb_get_str@ (or the corresponding @arb_printn@) for the real and+-- imaginary parts.+-- +-- By default, the output shows the midpoint of both the real and imaginary+-- parts with a guaranteed error of at most one unit in the last decimal+-- place. In addition, explicit error bounds are printed so that the+-- displayed decimal interval is guaranteed to enclose /x/.+-- +-- Any flags understood by @arb_get_str@ can be passed via /flags/ to+-- control the format of the real and imaginary parts.+foreign import ccall "acb.h acb_fprintn"+ acb_fprintn :: Ptr CFile -> Ptr CAcb -> CLong -> ArbStrOption -> IO ()++-- Random number generation ----------------------------------------------------++-- | /acb_randtest/ /z/ /state/ /prec/ /mag_bits/ +-- +-- Generates a random complex number by generating separate random real and+-- imaginary parts.+foreign import ccall "acb.h acb_randtest"+ acb_randtest :: Ptr CAcb -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /acb_randtest_special/ /z/ /state/ /prec/ /mag_bits/ +-- +-- Generates a random complex number by generating separate random real and+-- imaginary parts. Also generates NaNs and infinities.+foreign import ccall "acb.h acb_randtest_special"+ acb_randtest_special :: Ptr CAcb -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /acb_randtest_precise/ /z/ /state/ /prec/ /mag_bits/ +-- +-- Generates a random complex number with precise real and imaginary parts.+foreign import ccall "acb.h acb_randtest_precise"+ acb_randtest_precise :: Ptr CAcb -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /acb_randtest_param/ /z/ /state/ /prec/ /mag_bits/ +-- +-- Generates a random complex number, with very high probability of+-- generating integers and half-integers.+foreign import ccall "acb.h acb_randtest_param"+ acb_randtest_param :: Ptr CAcb -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- Precision and comparisons ---------------------------------------------------++-- | /acb_is_zero/ /z/ +-- +-- Returns nonzero iff /z/ is zero.+foreign import ccall "acb.h acb_is_zero"+ acb_is_zero :: Ptr CAcb -> IO CInt++-- | /acb_is_one/ /z/ +-- +-- Returns nonzero iff /z/ is exactly 1.+foreign import ccall "acb.h acb_is_one"+ acb_is_one :: Ptr CAcb -> IO CInt++-- | /acb_is_finite/ /z/ +-- +-- Returns nonzero iff /z/ certainly is finite.+foreign import ccall "acb.h acb_is_finite"+ acb_is_finite :: Ptr CAcb -> IO CInt++-- | /acb_is_exact/ /z/ +-- +-- Returns nonzero iff /z/ is exact.+foreign import ccall "acb.h acb_is_exact"+ acb_is_exact :: Ptr CAcb -> IO CInt++-- | /acb_is_int/ /z/ +-- +-- Returns nonzero iff /z/ is an exact integer.+foreign import ccall "acb.h acb_is_int"+ acb_is_int :: Ptr CAcb -> IO CInt++-- | /acb_is_int_2exp_si/ /x/ /e/ +-- +-- Returns nonzero iff /z/ exactly equals \(n 2^e\) for some integer /n/.+foreign import ccall "acb.h acb_is_int_2exp_si"+ acb_is_int_2exp_si :: Ptr CAcb -> CLong -> IO CInt++-- | /acb_equal/ /x/ /y/ +-- +-- Returns nonzero iff /x/ and /y/ are identical as sets, i.e. if the real+-- and imaginary parts are equal as balls.+-- +-- Note that this is not the same thing as testing whether both /x/ and /y/+-- certainly represent the same complex number, unless either /x/ or /y/ is+-- exact (and neither contains NaN). To test whether both operands /might/+-- represent the same mathematical quantity, use @acb_overlaps@ or+-- @acb_contains@, depending on the circumstance.+foreign import ccall "acb.h acb_equal"+ acb_equal :: Ptr CAcb -> Ptr CAcb -> IO CInt++-- | /acb_equal_si/ /x/ /y/ +-- +-- Returns nonzero iff /x/ is equal to the integer /y/.+foreign import ccall "acb.h acb_equal_si"+ acb_equal_si :: Ptr CAcb -> CLong -> IO CInt++-- | /acb_eq/ /x/ /y/ +-- +-- Returns nonzero iff /x/ and /y/ are certainly equal, as determined by+-- testing that @arb_eq@ holds for both the real and imaginary parts.+foreign import ccall "acb.h acb_eq"+ acb_eq :: Ptr CAcb -> Ptr CAcb -> IO CInt++-- | /acb_ne/ /x/ /y/ +-- +-- Returns nonzero iff /x/ and /y/ are certainly not equal, as determined+-- by testing that @arb_ne@ holds for either the real or imaginary parts.+foreign import ccall "acb.h acb_ne"+ acb_ne :: Ptr CAcb -> Ptr CAcb -> IO CInt++-- | /acb_overlaps/ /x/ /y/ +-- +-- Returns nonzero iff /x/ and /y/ have some point in common.+foreign import ccall "acb.h acb_overlaps"+ acb_overlaps :: Ptr CAcb -> Ptr CAcb -> IO CInt++-- | /acb_union/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ to a complex interval containing both /x/ and /y/.+foreign import ccall "acb.h acb_union"+ acb_union :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_get_abs_ubound_arf/ /u/ /z/ /prec/ +-- +-- Sets /u/ to an upper bound for the absolute value of /z/, computed using+-- a working precision of /prec/ bits.+foreign import ccall "acb.h acb_get_abs_ubound_arf"+ acb_get_abs_ubound_arf :: Ptr CArf -> Ptr CAcb -> CLong -> IO ()++-- | /acb_get_abs_lbound_arf/ /u/ /z/ /prec/ +-- +-- Sets /u/ to a lower bound for the absolute value of /z/, computed using+-- a working precision of /prec/ bits.+foreign import ccall "acb.h acb_get_abs_lbound_arf"+ acb_get_abs_lbound_arf :: Ptr CArf -> Ptr CAcb -> CLong -> IO ()++-- | /acb_get_rad_ubound_arf/ /u/ /z/ /prec/ +-- +-- Sets /u/ to an upper bound for the error radius of /z/ (the value is+-- currently not computed tightly).+foreign import ccall "acb.h acb_get_rad_ubound_arf"+ acb_get_rad_ubound_arf :: Ptr CArf -> Ptr CAcb -> CLong -> IO ()++-- | /acb_get_mag/ /u/ /x/ +-- +-- Sets /u/ to an upper bound for the absolute value of /x/.+foreign import ccall "acb.h acb_get_mag"+ acb_get_mag :: Ptr CMag -> Ptr CAcb -> IO ()++-- | /acb_get_mag_lower/ /u/ /x/ +-- +-- Sets /u/ to a lower bound for the absolute value of /x/.+foreign import ccall "acb.h acb_get_mag_lower"+ acb_get_mag_lower :: Ptr CMag -> Ptr CAcb -> IO ()++foreign import ccall "acb.h acb_contains_fmpq"+ acb_contains_fmpq :: Ptr CAcb -> Ptr CFmpq -> IO CInt++foreign import ccall "acb.h acb_contains_fmpz"+ acb_contains_fmpz :: Ptr CAcb -> Ptr CFmpz -> IO CInt++-- | /acb_contains/ /x/ /y/ +-- +-- Returns nonzero iff /y/ is contained in /x/.+foreign import ccall "acb.h acb_contains"+ acb_contains :: Ptr CAcb -> Ptr CAcb -> IO CInt++-- | /acb_contains_zero/ /x/ +-- +-- Returns nonzero iff zero is contained in /x/.+foreign import ccall "acb.h acb_contains_zero"+ acb_contains_zero :: Ptr CAcb -> IO CInt++-- | /acb_contains_int/ /x/ +-- +-- Returns nonzero iff the complex interval represented by /x/ contains an+-- integer.+foreign import ccall "acb.h acb_contains_int"+ acb_contains_int :: Ptr CAcb -> IO CInt++-- | /acb_contains_interior/ /x/ /y/ +-- +-- Tests if /y/ is contained in the interior of /x/. This predicate always+-- evaluates to false if /x/ and /y/ are both real-valued, since an+-- imaginary part of 0 is not considered contained in the interior of the+-- point interval 0. More generally, the same problem occurs for intervals+-- with an exact real or imaginary part. Such intervals must be handled+-- specially by the user where a different interpretation is intended.+foreign import ccall "acb.h acb_contains_interior"+ acb_contains_interior :: Ptr CAcb -> Ptr CAcb -> IO CInt++-- | /acb_rel_error_bits/ /x/ +-- +-- Returns the effective relative error of /x/ measured in bits. This is+-- computed as if calling @arb_rel_error_bits@ on the real ball whose+-- midpoint is the larger out of the real and imaginary midpoints of /x/,+-- and whose radius is the larger out of the real and imaginary radiuses of+-- /x/.+foreign import ccall "acb.h acb_rel_error_bits"+ acb_rel_error_bits :: Ptr CAcb -> IO CLong++-- | /acb_rel_accuracy_bits/ /x/ +-- +-- Returns the effective relative accuracy of /x/ measured in bits, equal+-- to the negative of the return value from @acb_rel_error_bits@.+foreign import ccall "acb.h acb_rel_accuracy_bits"+ acb_rel_accuracy_bits :: Ptr CAcb -> IO CLong++-- | /acb_rel_one_accuracy_bits/ /x/ +-- +-- Given a ball with midpoint /m/ and radius /r/, returns an approximation+-- of the relative accuracy of \([\max(1,|m|) \pm r]\) measured in bits.+foreign import ccall "acb.h acb_rel_one_accuracy_bits"+ acb_rel_one_accuracy_bits :: Ptr CAcb -> IO CLong++-- | /acb_bits/ /x/ +-- +-- Returns the maximum of /arb_bits/ applied to the real and imaginary+-- parts of /x/, i.e. the minimum precision sufficient to represent /x/+-- exactly.+foreign import ccall "acb.h acb_bits"+ acb_bits :: Ptr CAcb -> IO CLong++-- | /acb_indeterminate/ /x/ +-- +-- Sets /x/ to+-- \([\operatorname{NaN} \pm \infty] + [\operatorname{NaN} \pm \infty]i\),+-- representing an indeterminate result.+foreign import ccall "acb.h acb_indeterminate"+ acb_indeterminate :: Ptr CAcb -> IO ()++-- | /acb_trim/ /y/ /x/ +-- +-- Sets /y/ to a a copy of /x/ with both the real and imaginary parts+-- trimmed (see @arb_trim@).+foreign import ccall "acb.h acb_trim"+ acb_trim :: Ptr CAcb -> Ptr CAcb -> IO ()++-- | /acb_is_real/ /x/ +-- +-- Returns nonzero iff the imaginary part of /x/ is zero. It does not test+-- whether the real part of /x/ also is finite.+foreign import ccall "acb.h acb_is_real"+ acb_is_real :: Ptr CAcb -> IO CInt++-- | /acb_get_unique_fmpz/ /z/ /x/ +-- +-- If /x/ contains a unique integer, sets /z/ to that value and returns+-- nonzero. Otherwise (if /x/ represents no integers or more than one+-- integer), returns zero.+foreign import ccall "acb.h acb_get_unique_fmpz"+ acb_get_unique_fmpz :: Ptr CFmpz -> Ptr CAcb -> IO CInt++-- Complex parts ---------------------------------------------------------------++-- | /acb_get_real/ /re/ /z/ +-- +-- Sets /re/ to the real part of /z/.+foreign import ccall "acb.h acb_get_real"+ acb_get_real :: Ptr CArb -> Ptr CAcb -> IO ()++-- | /acb_get_imag/ /im/ /z/ +-- +-- Sets /im/ to the imaginary part of /z/.+foreign import ccall "acb.h acb_get_imag"+ acb_get_imag :: Ptr CArb -> Ptr CAcb -> IO ()++-- | /acb_arg/ /r/ /z/ /prec/ +-- +-- Sets /r/ to a real interval containing the complex argument (phase) of+-- /z/. We define the complex argument have a discontinuity on+-- \((-\infty,0]\), with the special value \(\operatorname{arg}(0) = 0\),+-- and \(\operatorname{arg}(a+0i) = \pi\) for \(a < 0\). Equivalently, if+-- \(z = a+bi\), the argument is given by \(\operatorname{atan2}(b,a)\)+-- (see @arb_atan2@).+foreign import ccall "acb.h acb_arg"+ acb_arg :: Ptr CArb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_abs/ /r/ /z/ /prec/ +-- +-- Sets /r/ to the absolute value of /z/.+foreign import ccall "acb.h acb_abs"+ acb_abs :: Ptr CArb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_sgn/ /r/ /z/ /prec/ +-- +-- Sets /r/ to the complex sign of /z/, defined as 0 if /z/ is exactly zero+-- and the projection onto the unit circle \(z / |z| = \exp(i \arg(z))\)+-- otherwise.+foreign import ccall "acb.h acb_sgn"+ acb_sgn :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_csgn/ /r/ /z/ +-- +-- Sets /r/ to the extension of the real sign function taking the value 1+-- for /z/ strictly in the right half plane, -1 for /z/ strictly in the+-- left half plane, and the sign of the imaginary part when /z/ is on the+-- imaginary axis. Equivalently,+-- \(\operatorname{csgn}(z) = z / \sqrt{z^2}\) except that the value is 0+-- when /z/ is exactly zero.+foreign import ccall "acb.h acb_csgn"+ acb_csgn :: Ptr CArb -> Ptr CAcb -> IO ()++-- Arithmetic ------------------------------------------------------------------++foreign import ccall "acb.h acb_neg"+ acb_neg :: Ptr CAcb -> Ptr CAcb -> IO ()++-- | /acb_neg_round/ /z/ /x/ /prec/ +-- +-- Sets /z/ to the negation of /x/.+foreign import ccall "acb.h acb_neg_round"+ acb_neg_round :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_conj/ /z/ /x/ +-- +-- Sets /z/ to the complex conjugate of /x/.+foreign import ccall "acb.h acb_conj"+ acb_conj :: Ptr CAcb -> Ptr CAcb -> IO ()++foreign import ccall "acb.h acb_add_ui"+ acb_add_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()++foreign import ccall "acb.h acb_add_si"+ acb_add_si :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb.h acb_add_fmpz"+ acb_add_fmpz :: Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "acb.h acb_add_arb"+ acb_add_arb :: Ptr CAcb -> Ptr CAcb -> Ptr CArb -> CLong -> IO ()++-- | /acb_add/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ to the sum of /x/ and /y/.+foreign import ccall "acb.h acb_add"+ acb_add :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_sub_ui"+ acb_sub_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()++foreign import ccall "acb.h acb_sub_si"+ acb_sub_si :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb.h acb_sub_fmpz"+ acb_sub_fmpz :: Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "acb.h acb_sub_arb"+ acb_sub_arb :: Ptr CAcb -> Ptr CAcb -> Ptr CArb -> CLong -> IO ()++-- | /acb_sub/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ to the difference of /x/ and /y/.+foreign import ccall "acb.h acb_sub"+ acb_sub :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_mul_onei/ /z/ /x/ +-- +-- Sets /z/ to /x/ multiplied by the imaginary unit.+foreign import ccall "acb.h acb_mul_onei"+ acb_mul_onei :: Ptr CAcb -> Ptr CAcb -> IO ()++-- | /acb_div_onei/ /z/ /x/ +-- +-- Sets /z/ to /x/ divided by the imaginary unit.+foreign import ccall "acb.h acb_div_onei"+ acb_div_onei :: Ptr CAcb -> Ptr CAcb -> IO ()++foreign import ccall "acb.h acb_mul_ui"+ acb_mul_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()++foreign import ccall "acb.h acb_mul_si"+ acb_mul_si :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb.h acb_mul_fmpz"+ acb_mul_fmpz :: Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> CLong -> IO ()++-- | /acb_mul_arb/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ to the product of /x/ and /y/.+foreign import ccall "acb.h acb_mul_arb"+ acb_mul_arb :: Ptr CAcb -> Ptr CAcb -> Ptr CArb -> CLong -> IO ()++-- | /acb_mul/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ to the product of /x/ and /y/. If at least one part of /x/ or+-- /y/ is zero, the operations is reduced to two real multiplications. If+-- /x/ and /y/ are the same pointers, they are assumed to represent the+-- same mathematical quantity and the squaring formula is used.+foreign import ccall "acb.h acb_mul"+ acb_mul :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_mul_2exp_si"+ acb_mul_2exp_si :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_mul_2exp_fmpz/ /z/ /x/ /e/ +-- +-- Sets /z/ to /x/ multiplied by \(2^e\), without rounding.+foreign import ccall "acb.h acb_mul_2exp_fmpz"+ acb_mul_2exp_fmpz :: Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> IO ()++-- | /acb_sqr/ /z/ /x/ /prec/ +-- +-- Sets /z/ to /x/ squared.+foreign import ccall "acb.h acb_sqr"+ acb_sqr :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_cube/ /z/ /x/ /prec/ +-- +-- Sets /z/ to /x/ cubed, computed efficiently using two real squarings,+-- two real multiplications, and scalar operations.+foreign import ccall "acb.h acb_cube"+ acb_cube :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_addmul"+ acb_addmul :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_addmul_ui"+ acb_addmul_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()++foreign import ccall "acb.h acb_addmul_si"+ acb_addmul_si :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb.h acb_addmul_fmpz"+ acb_addmul_fmpz :: Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> CLong -> IO ()++-- | /acb_addmul_arb/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ to /z/ plus the product of /x/ and /y/.+foreign import ccall "acb.h acb_addmul_arb"+ acb_addmul_arb :: Ptr CAcb -> Ptr CAcb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "acb.h acb_submul"+ acb_submul :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_submul_ui"+ acb_submul_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()++foreign import ccall "acb.h acb_submul_si"+ acb_submul_si :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb.h acb_submul_fmpz"+ acb_submul_fmpz :: Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> CLong -> IO ()++-- | /acb_submul_arb/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ to /z/ minus the product of /x/ and /y/.+foreign import ccall "acb.h acb_submul_arb"+ acb_submul_arb :: Ptr CAcb -> Ptr CAcb -> Ptr CArb -> CLong -> IO ()++-- | /acb_inv/ /z/ /x/ /prec/ +-- +-- Sets /z/ to the multiplicative inverse of /x/.+foreign import ccall "acb.h acb_inv"+ acb_inv :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_div_ui"+ acb_div_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()++foreign import ccall "acb.h acb_div_si"+ acb_div_si :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb.h acb_div_fmpz"+ acb_div_fmpz :: Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "acb.h acb_div_arb"+ acb_div_arb :: Ptr CAcb -> Ptr CAcb -> Ptr CArb -> CLong -> IO ()++-- | /acb_div/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ to the quotient of /x/ and /y/.+foreign import ccall "acb.h acb_div"+ acb_div :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Dot product -----------------------------------------------------------------++-- | /acb_dot_precise/ /res/ /s/ /subtract/ /x/ /xstep/ /y/ /ystep/ /len/ /prec/ +-- +-- Computes the dot product of the vectors /x/ and /y/, setting /res/ to+-- \(s + (-1)^{subtract} \sum_{i=0}^{len-1} x_i y_i\).+-- +-- The initial term /s/ is optional and can be omitted by passing /NULL/+-- (equivalently, \(s = 0\)). The parameter /subtract/ must be 0 or 1. The+-- length /len/ is allowed to be negative, which is equivalent to a length+-- of zero. The parameters /xstep/ or /ystep/ specify a step length for+-- traversing subsequences of the vectors /x/ and /y/; either can be+-- negative to step in the reverse direction starting from the initial+-- pointer. Aliasing is allowed between /res/ and /s/ but not between /res/+-- and the entries of /x/ and /y/.+-- +-- The default version determines the optimal precision for each term and+-- performs all internal calculations using mpn arithmetic with minimal+-- overhead. This is the preferred way to compute a dot product; it is+-- generally much faster and more precise than a simple loop.+-- +-- The /simple/ version performs fused multiply-add operations in a simple+-- loop. This can be used for testing purposes and is also used as a+-- fallback by the default version when the exponents are out of range for+-- the optimized code.+-- +-- The /precise/ version computes the dot product exactly up to the final+-- rounding. This can be extremely slow and is only intended for testing.+foreign import ccall "acb.h acb_dot_precise"+ acb_dot_precise :: Ptr CAcb -> Ptr CAcb -> CInt -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_approx_dot/ /res/ /s/ /subtract/ /x/ /xstep/ /y/ /ystep/ /len/ /prec/ +-- +-- Computes an approximate dot product /without error bounds/. The radii of+-- the inputs are ignored (only the midpoints are read) and only the+-- midpoint of the output is written.+foreign import ccall "acb.h acb_approx_dot"+ acb_approx_dot :: Ptr CAcb -> Ptr CAcb -> CInt -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_dot_ui/ /res/ /initial/ /subtract/ /x/ /xstep/ /y/ /ystep/ /len/ /prec/ +-- +-- Equivalent to @acb_dot@, but with integers in the array /y/. The /uiui/+-- and /siui/ versions take an array of double-limb integers as input; the+-- /siui/ version assumes that these represent signed integers in two\'s+-- complement form.+foreign import ccall "acb.h acb_dot_ui"+ acb_dot_ui :: Ptr CAcb -> Ptr CAcb -> CInt -> Ptr CAcb -> CLong -> Ptr CULong -> CLong -> CLong -> CLong -> IO ()++-- Mathematical constants ------------------------------------------------------++-- | /acb_const_pi/ /y/ /prec/ +-- +-- Sets /y/ to the constant \(\pi\).+foreign import ccall "acb.h acb_const_pi"+ acb_const_pi :: Ptr CAcb -> CLong -> IO ()++-- Powers and roots ------------------------------------------------------------++-- | /acb_sqrt/ /r/ /z/ /prec/ +-- +-- Sets /r/ to the square root of /z/. If either the real or imaginary part+-- is exactly zero, only a single real square root is needed. Generally, we+-- use the formula \(\sqrt{a+bi} = u/2 + ib/u, u = \sqrt{2(|a+bi|+a)}\),+-- requiring two real square root extractions.+foreign import ccall "acb.h acb_sqrt"+ acb_sqrt :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_sqrt_analytic/ /r/ /z/ /analytic/ /prec/ +-- +-- Computes the square root. If /analytic/ is set, gives a NaN-containing+-- result if /z/ touches the branch cut.+foreign import ccall "acb.h acb_sqrt_analytic"+ acb_sqrt_analytic :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_rsqrt/ /r/ /z/ /prec/ +-- +-- Sets /r/ to the reciprocal square root of /z/. If either the real or+-- imaginary part is exactly zero, only a single real reciprocal square+-- root is needed. Generally, we use the formula+-- \(1/\sqrt{a+bi} = ((a+r) - bi)/v, r = |a+bi|, v = \sqrt{r |a+bi+r|^2}\),+-- requiring one real square root and one real reciprocal square root.+foreign import ccall "acb.h acb_rsqrt"+ acb_rsqrt :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_rsqrt_analytic/ /r/ /z/ /analytic/ /prec/ +-- +-- Computes the reciprocal square root. If /analytic/ is set, gives a+-- NaN-containing result if /z/ touches the branch cut.+foreign import ccall "acb.h acb_rsqrt_analytic"+ acb_rsqrt_analytic :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_quadratic_roots_fmpz/ /r1/ /r2/ /a/ /b/ /c/ /prec/ +-- +-- Sets /r1/ and /r2/ to the roots of the quadratic polynomial+-- \(ax^2 + bx + c\). Requires that /a/ is nonzero. This function is+-- implemented so that both roots are computed accurately even when direct+-- use of the quadratic formula would lose accuracy.+foreign import ccall "acb.h acb_quadratic_roots_fmpz"+ acb_quadratic_roots_fmpz :: Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /acb_root_ui/ /r/ /z/ /k/ /prec/ +-- +-- Sets /r/ to the principal /k/-th root of /z/.+foreign import ccall "acb.h acb_root_ui"+ acb_root_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()++foreign import ccall "acb.h acb_pow_fmpz"+ acb_pow_fmpz :: Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "acb.h acb_pow_ui"+ acb_pow_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()++-- | /acb_pow_si/ /y/ /b/ /e/ /prec/ +-- +-- Sets \(y = b^e\) using binary exponentiation (with an initial division+-- if \(e < 0\)). Note that these functions can get slow if the exponent is+-- extremely large (in such cases @acb_pow@ may be superior).+foreign import ccall "acb.h acb_pow_si"+ acb_pow_si :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb.h acb_pow_arb"+ acb_pow_arb :: Ptr CAcb -> Ptr CAcb -> Ptr CArb -> CLong -> IO ()++-- | /acb_pow/ /z/ /x/ /y/ /prec/ +-- +-- Sets \(z = x^y\), computed using binary exponentiation if \(y\) if a+-- small exact integer, as \(z = (x^{1/2})^{2y}\) if \(y\) is a small exact+-- half-integer, and generally as \(z = \exp(y \log x)\).+foreign import ccall "acb.h acb_pow"+ acb_pow :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_pow_analytic/ /r/ /x/ /y/ /analytic/ /prec/ +-- +-- Computes the power \(x^y\). If /analytic/ is set, gives a NaN-containing+-- result if /x/ touches the branch cut (unless /y/ is an integer).+foreign import ccall "acb.h acb_pow_analytic"+ acb_pow_analytic :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_unit_root/ /res/ /order/ /prec/ +-- +-- Sets /res/ to \(\exp(\frac{2i\pi}{\mathrm{order}})\) to precision+-- /prec/.+foreign import ccall "acb.h acb_unit_root"+ acb_unit_root :: Ptr CAcb -> CULong -> CLong -> IO ()++-- Exponentials and logarithms -------------------------------------------------++-- | /acb_exp/ /y/ /z/ /prec/ +-- +-- Sets /y/ to the exponential function of /z/, computed as+-- \(\exp(a+bi) = \exp(a) \left( \cos(b) + \sin(b) i \right)\).+foreign import ccall "acb.h acb_exp"+ acb_exp :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_exp_pi_i/ /y/ /z/ /prec/ +-- +-- Sets /y/ to \(\exp(\pi i z)\).+foreign import ccall "acb.h acb_exp_pi_i"+ acb_exp_pi_i :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_exp_invexp/ /s/ /t/ /z/ /prec/ +-- +-- Sets \(s = \exp(z)\) and \(t = \exp(-z)\).+foreign import ccall "acb.h acb_exp_invexp"+ acb_exp_invexp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_expm1/ /res/ /z/ /prec/ +-- +-- Sets /res/ to \(\exp(z)-1\), using a more accurate method when+-- \(z \approx 0\).+foreign import ccall "acb.h acb_expm1"+ acb_expm1 :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_log/ /y/ /z/ /prec/ +-- +-- Sets /y/ to the principal branch of the natural logarithm of /z/,+-- computed as+-- \(\log(a+bi) = \frac{1}{2} \log(a^2 + b^2) + i \operatorname{arg}(a+bi)\).+foreign import ccall "acb.h acb_log"+ acb_log :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_log_analytic/ /r/ /z/ /analytic/ /prec/ +-- +-- Computes the natural logarithm. If /analytic/ is set, gives a+-- NaN-containing result if /z/ touches the branch cut.+foreign import ccall "acb.h acb_log_analytic"+ acb_log_analytic :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_log1p/ /z/ /x/ /prec/ +-- +-- Sets \(z = \log(1+x)\), computed accurately when \(x \approx 0\).+foreign import ccall "acb.h acb_log1p"+ acb_log1p :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Trigonometric functions -----------------------------------------------------++foreign import ccall "acb.h acb_sin"+ acb_sin :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_cos"+ acb_cos :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_sin_cos/ /s/ /c/ /z/ /prec/ +-- +-- Sets \(s = \sin(z)\), \(c = \cos(z)\), evaluated as+-- \(\sin(a+bi) = \sin(a)\cosh(b) + i \cos(a)\sinh(b)\),+-- \(\cos(a+bi) = \cos(a)\cosh(b) - i \sin(a)\sinh(b)\).+foreign import ccall "acb.h acb_sin_cos"+ acb_sin_cos :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_tan/ /s/ /z/ /prec/ +-- +-- Sets \(s = \tan(z) = \sin(z) / \cos(z)\). For large imaginary parts, the+-- function is evaluated in a numerically stable way as \(\pm i\) plus a+-- decreasing exponential factor.+foreign import ccall "acb.h acb_tan"+ acb_tan :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_cot/ /s/ /z/ /prec/ +-- +-- Sets \(s = \cot(z) = \cos(z) / \sin(z)\). For large imaginary parts, the+-- function is evaluated in a numerically stable way as \(\pm i\) plus a+-- decreasing exponential factor.+foreign import ccall "acb.h acb_cot"+ acb_cot :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_sin_pi"+ acb_sin_pi :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_cos_pi"+ acb_cos_pi :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_sin_cos_pi/ /s/ /c/ /z/ /prec/ +-- +-- Sets \(s = \sin(\pi z)\), \(c = \cos(\pi z)\), evaluating the+-- trigonometric factors of the real and imaginary part accurately via+-- @arb_sin_cos_pi@.+foreign import ccall "acb.h acb_sin_cos_pi"+ acb_sin_cos_pi :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_tan_pi/ /s/ /z/ /prec/ +-- +-- Sets \(s = \tan(\pi z)\). Uses the same algorithm as @acb_tan@, but+-- evaluates the sine and cosine accurately via @arb_sin_cos_pi@.+foreign import ccall "acb.h acb_tan_pi"+ acb_tan_pi :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_cot_pi/ /s/ /z/ /prec/ +-- +-- Sets \(s = \cot(\pi z)\). Uses the same algorithm as @acb_cot@, but+-- evaluates the sine and cosine accurately via @arb_sin_cos_pi@.+foreign import ccall "acb.h acb_cot_pi"+ acb_cot_pi :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_sec/ /res/ /z/ /prec/ +-- +-- Computes \(\sec(z) = 1 / \cos(z)\).+foreign import ccall "acb.h acb_sec"+ acb_sec :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_csc/ /res/ /z/ /prec/ +-- +-- Computes \(\csc(x) = 1 / \sin(z)\).+foreign import ccall "acb.h acb_csc"+ acb_csc :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_csc_pi/ /res/ /z/ /prec/ +-- +-- Computes \(\csc(\pi x) = 1 / \sin(\pi z)\). Evaluates the sine+-- accurately via @acb_sin_pi@.+foreign import ccall "acb.h acb_csc_pi"+ acb_csc_pi :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_sinc/ /s/ /z/ /prec/ +-- +-- Sets \(s = \operatorname{sinc}(x) = \sin(z) / z\).+foreign import ccall "acb.h acb_sinc"+ acb_sinc :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_sinc_pi/ /s/ /z/ /prec/ +-- +-- Sets \(s = \operatorname{sinc}(\pi x) = \sin(\pi z) / (\pi z)\).+foreign import ccall "acb.h acb_sinc_pi"+ acb_sinc_pi :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Inverse trigonometric functions ---------------------------------------------++-- | /acb_asin/ /res/ /z/ /prec/ +-- +-- Sets /res/ to \(\operatorname{asin}(z) = -i \log(iz + \sqrt{1-z^2})\).+foreign import ccall "acb.h acb_asin"+ acb_asin :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_acos/ /res/ /z/ /prec/ +-- +-- Sets /res/ to+-- \(\operatorname{acos}(z) = \tfrac{1}{2} \pi - \operatorname{asin}(z)\).+foreign import ccall "acb.h acb_acos"+ acb_acos :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_atan/ /res/ /z/ /prec/ +-- +-- Sets /res/ to+-- \(\operatorname{atan}(z) = \tfrac{1}{2} i (\log(1-iz)-\log(1+iz))\).+foreign import ccall "acb.h acb_atan"+ acb_atan :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Hyperbolic functions --------------------------------------------------------++foreign import ccall "acb.h acb_sinh"+ acb_sinh :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_cosh"+ acb_cosh :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_sinh_cosh"+ acb_sinh_cosh :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_tanh"+ acb_tanh :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_coth/ /s/ /z/ /prec/ +-- +-- Respectively computes \(\sinh(z) = -i\sin(iz)\),+-- \(\cosh(z) = \cos(iz)\), \(\tanh(z) = -i\tan(iz)\),+-- \(\coth(z) = i\cot(iz)\).+foreign import ccall "acb.h acb_coth"+ acb_coth :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_sech/ /res/ /z/ /prec/ +-- +-- Computes \(\operatorname{sech}(z) = 1 / \cosh(z)\).+foreign import ccall "acb.h acb_sech"+ acb_sech :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_csch/ /res/ /z/ /prec/ +-- +-- Computes \(\operatorname{csch}(z) = 1 / \sinh(z)\).+foreign import ccall "acb.h acb_csch"+ acb_csch :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Inverse hyperbolic functions ------------------------------------------------++-- | /acb_asinh/ /res/ /z/ /prec/ +-- +-- Sets /res/ to \(\operatorname{asinh}(z) = -i \operatorname{asin}(iz)\).+foreign import ccall "acb.h acb_asinh"+ acb_asinh :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_acosh/ /res/ /z/ /prec/ +-- +-- Sets /res/ to+-- \(\operatorname{acosh}(z) = \log(z + \sqrt{z+1} \sqrt{z-1})\).+foreign import ccall "acb.h acb_acosh"+ acb_acosh :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_atanh/ /res/ /z/ /prec/ +-- +-- Sets /res/ to \(\operatorname{atanh}(z) = -i \operatorname{atan}(iz)\).+foreign import ccall "acb.h acb_atanh"+ acb_atanh :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Lambert W function ----------------------------------------------------------++-- | /acb_lambertw_asymp/ /res/ /z/ /k/ /L/ /M/ /prec/ +-- +-- Sets /res/ to the Lambert W function \(W_k(z)\) computed using /L/ and+-- /M/ terms in the bivariate series giving the asymptotic expansion at+-- zero or infinity. This algorithm is valid everywhere, but the error+-- bound is only finite when \(|\log(z)|\) is sufficiently large.+foreign import ccall "acb.h acb_lambertw_asymp"+ acb_lambertw_asymp :: Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> CLong -> CLong -> CLong -> IO ()++-- | /acb_lambertw_check_branch/ /w/ /k/ /prec/ +-- +-- Tests if /w/ definitely lies in the image of the branch \(W_k(z)\). This+-- function is used internally to verify that a computed approximation of+-- the Lambert W function lies on the intended branch. Note that this will+-- necessarily evaluate to false for points exactly on (or overlapping) the+-- branch cuts, where a different algorithm has to be used.+foreign import ccall "acb.h acb_lambertw_check_branch"+ acb_lambertw_check_branch :: Ptr CAcb -> Ptr CFmpz -> CLong -> IO CInt++-- | /acb_lambertw_bound_deriv/ /res/ /z/ /ez1/ /k/ +-- +-- Sets /res/ to an upper bound for \(|W_k'(z)|\). The input /ez1/ should+-- contain the precomputed value of \(ez+1\).+-- +-- Along the real line, the directional derivative of \(W_k(z)\) is+-- understood to be taken. As a result, the user must handle the branch cut+-- discontinuity separately when using this function to bound perturbations+-- in the value of \(W_k(z)\).+foreign import ccall "acb.h acb_lambertw_bound_deriv"+ acb_lambertw_bound_deriv :: Ptr CMag -> Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> IO ()++-- | /acb_lambertw/ /res/ /z/ /k/ /flags/ /prec/ +-- +-- Sets /res/ to the Lambert W function \(W_k(z)\) where the index /k/+-- selects the branch (with \(k = 0\) giving the principal branch). The+-- placement of branch cuts follows < [CGHJK1996]>.+-- +-- If /flags/ is nonzero, nonstandard branch cuts are used.+-- +-- If /flags/ is set to /ACB_LAMBERTW_LEFT/, computes+-- \(W_{\mathrm{left}|k}(z)\) which corresponds to \(W_k(z)\) in the upper+-- half plane and \(W_{k+1}(z)\) in the lower half plane, connected+-- continuously to the left of the branch points. In other words, the+-- branch cut on \((-\infty,0)\) is rotated counterclockwise to+-- \((0,+\infty)\). (For \(k = -1\) and \(k = 0\), there is also a branch+-- cut on \((-1/e,0)\), continuous from below instead of from above to+-- maintain counterclockwise continuity.)+-- +-- If /flags/ is set to /ACB_LAMBERTW_MIDDLE/, computes+-- \(W_{\mathrm{middle}}(z)\) which corresponds to \(W_{-1}(z)\) in the+-- upper half plane and \(W_{1}(z)\) in the lower half plane, connected+-- continuously through \((-1/e,0)\) with branch cuts on \((-\infty,-1/e)\)+-- and \((0,+\infty)\). \(W_{\mathrm{middle}}(z)\) extends the real+-- analytic function \(W_{-1}(x)\) defined on \((-1/e,0)\) to a complex+-- analytic function, whereas the standard branch \(W_{-1}(z)\) has a+-- branch cut along the real segment.+-- +-- The algorithm used to compute the Lambert W function is described in+-- < [Joh2017b]>.+foreign import ccall "acb.h acb_lambertw"+ acb_lambertw :: Ptr CAcb -> Ptr CAcb -> Ptr CFmpz -> CInt -> CLong -> IO ()++-- Rising factorials -----------------------------------------------------------++-- | /acb_rising_ui/ /z/ /x/ /n/ /prec/ +-- +-- Computes the rising factorial \(z = x (x+1) (x+2) \cdots (x+n-1)\).+-- These functions are aliases for @acb_hypgeom_rising_ui@ and+-- @acb_hypgeom_rising@.+foreign import ccall "acb.h acb_rising_ui"+ acb_rising_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()++++++++-- Gamma function --------------------------------------------------------------++-- | /acb_gamma/ /y/ /x/ /prec/ +-- +-- Computes the gamma function \(y = \Gamma(x)\). This is an alias for+-- @acb_hypgeom_gamma@.+foreign import ccall "acb.h acb_gamma"+ acb_gamma :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_rgamma/ /y/ /x/ /prec/ +-- +-- Computes the reciprocal gamma function \(y = 1/\Gamma(x)\), avoiding+-- division by zero at the poles of the gamma function. This is an alias+-- for @acb_hypgeom_rgamma@.+foreign import ccall "acb.h acb_rgamma"+ acb_rgamma :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_lgamma/ /y/ /x/ /prec/ +-- +-- Computes the logarithmic gamma function \(y = \log \Gamma(x)\). This is+-- an alias for @acb_hypgeom_lgamma@.+-- +-- The branch cut of the logarithmic gamma function is placed on the+-- negative half-axis, which means that+-- \(\log \Gamma(z) + \log z = \log \Gamma(z+1)\) holds for all \(z\),+-- whereas \(\log \Gamma(z) \ne \log(\Gamma(z))\) in general. In the left+-- half plane, the reflection formula with correct branch structure is+-- evaluated via @acb_log_sin_pi@.+foreign import ccall "acb.h acb_lgamma"+ acb_lgamma :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_digamma/ /y/ /x/ /prec/ +-- +-- Computes the digamma function+-- \(y = \psi(x) = (\log \Gamma(x))' = \Gamma'(x) / \Gamma(x)\).+foreign import ccall "acb.h acb_digamma"+ acb_digamma :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_log_sin_pi/ /res/ /z/ /prec/ +-- +-- Computes the logarithmic sine function defined by+-- +-- \[`\]+-- \[S(z) = \log(\pi) - \log \Gamma(z) + \log \Gamma(1-z)\]+-- +-- which is equal to+-- +-- \[`\]+-- \[S(z) = \int_{1/2}^z \pi \cot(\pi t) dt\]+-- +-- where the path of integration goes through the upper half plane if+-- \(0 < \arg(z) \le \pi\) and through the lower half plane if+-- \(-\pi < \arg(z) \le 0\). Equivalently,+-- +-- \[`\]+-- \[S(z) = \log(\sin(\pi(z-n))) \mp n \pi i, \quad n = \lfloor \operatorname{re}(z) \rfloor\]+-- +-- where the negative sign is taken if \(0 < \arg(z) \le \pi\) and the+-- positive sign is taken otherwise (if the interval \(\arg(z)\) does not+-- certainly satisfy either condition, the union of both cases is+-- computed). After subtracting /n/, we have+-- \(0 \le \operatorname{re}(z) < 1\). In this strip, we use use+-- \(S(z) = \log(\sin(\pi(z)))\) if the imaginary part of /z/ is small.+-- Otherwise, we use \(S(z) = i \pi (z-1/2) + \log((1+e^{-2i\pi z})/2)\) in+-- the lower half-plane and the conjugated expression in the upper+-- half-plane to avoid exponent overflow.+-- +-- The function is evaluated at the midpoint and the propagated error is+-- computed from \(S'(z)\) to get a continuous change when \(z\) is+-- non-real and \(n\) spans more than one possible integer value.+foreign import ccall "acb.h acb_log_sin_pi"+ acb_log_sin_pi :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_polygamma/ /res/ /s/ /z/ /prec/ +-- +-- Sets /res/ to the value of the generalized polygamma function+-- \(\psi(s,z)\).+-- +-- If /s/ is a nonnegative order, this is simply the /s/-order derivative+-- of the digamma function. If \(s = 0\), this function simply calls the+-- digamma function internally. For integers \(s \ge 1\), it calls the+-- Hurwitz zeta function. Note that for small integers \(s \ge 1\), it can+-- be faster to use @acb_poly_digamma_series@ and read off the+-- coefficients.+-- +-- The generalization to other values of /s/ is due to Espinosa and Moll+-- < [EM2004]>:+-- +-- \[`\]+-- \[\psi(s,z) = \frac{\zeta'(s+1,z) + (\gamma + \psi(-s)) \zeta(s+1,z)}{\Gamma(-s)}\]+foreign import ccall "acb.h acb_polygamma"+ acb_polygamma :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_barnes_g"+ acb_barnes_g :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_log_barnes_g/ /res/ /z/ /prec/ +-- +-- Computes Barnes /G/-function or the logarithmic Barnes /G/-function,+-- respectively. The logarithmic version has branch cuts on the negative+-- real axis and is continuous elsewhere in the complex plane, in analogy+-- with the logarithmic gamma function. The functional equation+-- +-- \[`\]+-- \[\log G(z+1) = \log \Gamma(z) + \log G(z).\]+-- +-- holds for all /z/.+-- +-- For small integers, we directly use the recurrence relation+-- \(G(z+1) = \Gamma(z) G(z)\) together with the initial value+-- \(G(1) = 1\). For general /z/, we use the formula+-- +-- \[`\]+-- \[\log G(z) = (z-1) \log \Gamma(z) - \zeta'(-1,z) + \zeta'(-1).\]+foreign import ccall "acb.h acb_log_barnes_g"+ acb_log_barnes_g :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Zeta function ---------------------------------------------------------------++-- | /acb_zeta/ /z/ /s/ /prec/ +-- +-- Sets /z/ to the value of the Riemann zeta function \(\zeta(s)\). Note:+-- for computing derivatives with respect to \(s\), use+-- @acb_poly_zeta_series@ or related methods.+-- +-- This is a wrapper of @acb_dirichlet_zeta@.+foreign import ccall "acb.h acb_zeta"+ acb_zeta :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hurwitz_zeta/ /z/ /s/ /a/ /prec/ +-- +-- Sets /z/ to the value of the Hurwitz zeta function \(\zeta(s, a)\).+-- Note: for computing derivatives with respect to \(s\), use+-- @acb_poly_zeta_series@ or related methods.+-- +-- This is a wrapper of @acb_dirichlet_hurwitz@.+foreign import ccall "acb.h acb_hurwitz_zeta"+ acb_hurwitz_zeta :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_bernoulli_poly_ui/ /res/ /n/ /x/ /prec/ +-- +-- Sets /res/ to the value of the Bernoulli polynomial \(B_n(x)\).+-- +-- Warning: this function is only fast if either /n/ or /x/ is a small+-- integer.+-- +-- This function reads Bernoulli numbers from the global cache if they are+-- already cached, but does not automatically extend the cache by itself.+foreign import ccall "acb.h acb_bernoulli_poly_ui"+ acb_bernoulli_poly_ui :: Ptr CAcb -> CULong -> Ptr CAcb -> CLong -> IO ()++-- Polylogarithms --------------------------------------------------------------++foreign import ccall "acb.h acb_polylog"+ acb_polylog :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_polylog_si/ /w/ /s/ /z/ /prec/ +-- +-- Sets /w/ to the polylogarithm \(\operatorname{Li}_s(z)\).+foreign import ccall "acb.h acb_polylog_si"+ acb_polylog_si :: Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++-- Arithmetic-geometric mean ---------------------------------------------------++-- See @algorithms_agm@ for implementation details.+--+-- | /acb_agm1/ /m/ /z/ /prec/ +-- +-- Sets /m/ to the arithmetic-geometric mean+-- \(M(z) = \operatorname{agm}(1,z)\), defined such that the function is+-- continuous in the complex plane except for a branch cut along the+-- negative half axis (where it is continuous from above). This corresponds+-- to always choosing an \"optimal\" branch for the square root in the+-- arithmetic-geometric mean iteration.+foreign import ccall "acb.h acb_agm1"+ acb_agm1 :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_agm1_cpx/ /m/ /z/ /len/ /prec/ +-- +-- Sets the coefficients in the array /m/ to the power series expansion of+-- the arithmetic-geometric mean at the point /z/ truncated to length+-- /len/, i.e. \(M(z+x) \in \mathbb{C}[[x]]\).+foreign import ccall "acb.h acb_agm1_cpx"+ acb_agm1_cpx :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_agm/ /m/ /x/ /y/ /prec/ +-- +-- Sets /m/ to the arithmetic-geometric mean of /x/ and /y/. The square+-- roots in the AGM iteration are chosen so as to form the \"optimal\" AGM+-- sequence. This gives a well-defined function of /x/ and /y/ except when+-- \(x / y\) is a negative real number, in which case there are two optimal+-- AGM sequences. In that case, an arbitrary but consistent choice is made+-- (if a decision cannot be made due to inexact arithmetic, the union of+-- both choices is returned).+foreign import ccall "acb.h acb_agm"+ acb_agm :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Other special functions -----------------------------------------------------++foreign import ccall "acb.h acb_chebyshev_t_ui"+ acb_chebyshev_t_ui :: Ptr CAcb -> CULong -> Ptr CAcb -> CLong -> IO ()++-- | /acb_chebyshev_u_ui/ /a/ /n/ /x/ /prec/ +-- +-- Evaluates the Chebyshev polynomial of the first kind \(a = T_n(x)\) or+-- the Chebyshev polynomial of the second kind \(a = U_n(x)\).+foreign import ccall "acb.h acb_chebyshev_u_ui"+ acb_chebyshev_u_ui :: Ptr CAcb -> CULong -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h acb_chebyshev_t2_ui"+ acb_chebyshev_t2_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> Ptr CAcb -> CLong -> IO ()++-- | /acb_chebyshev_u2_ui/ /a/ /b/ /n/ /x/ /prec/ +-- +-- Simultaneously evaluates \(a = T_n(x), b = T_{n-1}(x)\) or+-- \(a = U_n(x), b = U_{n-1}(x)\). Aliasing between /a/, /b/ and /x/ is not+-- permitted.+foreign import ccall "acb.h acb_chebyshev_u2_ui"+ acb_chebyshev_u2_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> Ptr CAcb -> CLong -> IO ()++-- Piecewise real functions ----------------------------------------------------++-- The following methods extend common piecewise real functions to+-- piecewise complex analytic functions, useful together with the+-- @acb_calc.h \<acb-calc>@ module. If /analytic/ is set, evaluation on a+-- discontinuity or non-analytic point gives a NaN result.+--+-- | /acb_real_abs/ /res/ /z/ /analytic/ /prec/ +-- +-- The absolute value is extended to \(+z\) in the right half plane and+-- \(-z\) in the left half plane, with a discontinuity on the vertical line+-- \(\operatorname{Re}(z) = 0\).+foreign import ccall "acb.h acb_real_abs"+ acb_real_abs :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_real_sgn/ /res/ /z/ /analytic/ /prec/ +-- +-- The sign function is extended to \(+1\) in the right half plane and+-- \(-1\) in the left half plane, with a discontinuity on the vertical line+-- \(\operatorname{Re}(z) = 0\). If /analytic/ is not set, this is+-- effectively the same function as @acb_csgn@.+foreign import ccall "acb.h acb_real_sgn"+ acb_real_sgn :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_real_heaviside/ /res/ /z/ /analytic/ /prec/ +-- +-- The Heaviside step function (or unit step function) is extended to+-- \(+1\) in the right half plane and \(0\) in the left half plane, with a+-- discontinuity on the vertical line \(\operatorname{Re}(z) = 0\).+foreign import ccall "acb.h acb_real_heaviside"+ acb_real_heaviside :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_real_floor/ /res/ /z/ /analytic/ /prec/ +-- +-- The floor function is extended to a piecewise constant function equal to+-- \(n\) in the strips with real part \((n,n+1)\), with discontinuities on+-- the vertical lines \(\operatorname{Re}(z) = n\).+foreign import ccall "acb.h acb_real_floor"+ acb_real_floor :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_real_ceil/ /res/ /z/ /analytic/ /prec/ +-- +-- The ceiling function is extended to a piecewise constant function equal+-- to \(n+1\) in the strips with real part \((n,n+1)\), with+-- discontinuities on the vertical lines \(\operatorname{Re}(z) = n\).+foreign import ccall "acb.h acb_real_ceil"+ acb_real_ceil :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_real_max/ /res/ /x/ /y/ /analytic/ /prec/ +-- +-- The real function \(\max(x,y)\) is extended to a piecewise analytic+-- function of two variables by returning \(x\) when+-- \(\operatorname{Re}(x) \ge \operatorname{Re}(y)\) and returning \(y\)+-- when \(\operatorname{Re}(x) < \operatorname{Re}(y)\), with+-- discontinuities where \(\operatorname{Re}(x) = \operatorname{Re}(y)\).+foreign import ccall "acb.h acb_real_max"+ acb_real_max :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_real_min/ /res/ /x/ /y/ /analytic/ /prec/ +-- +-- The real function \(\min(x,y)\) is extended to a piecewise analytic+-- function of two variables by returning \(x\) when+-- \(\operatorname{Re}(x) \le \operatorname{Re}(y)\) and returning \(y\)+-- when \(\operatorname{Re}(x) > \operatorname{Re}(y)\), with+-- discontinuities where \(\operatorname{Re}(x) = \operatorname{Re}(y)\).+foreign import ccall "acb.h acb_real_min"+ acb_real_min :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_real_sqrtpos/ /res/ /z/ /analytic/ /prec/ +-- +-- Extends the real square root function on \([0,+\infty)\) to the usual+-- complex square root on the cut plane. Like @arb_sqrtpos@, only the+-- nonnegative part of /z/ is considered if /z/ is purely real and+-- /analytic/ is not set. This is useful for integrating \(\sqrt{f(x)}\)+-- where it is known that \(f(x) \ge 0\): unlike @acb_sqrt_analytic@, no+-- spurious imaginary terms \([\pm \varepsilon] i\) are created when the+-- balls computed for \(f(x)\) straddle zero.+foreign import ccall "acb.h acb_real_sqrtpos"+ acb_real_sqrtpos :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- Vector functions ------------------------------------------------------------++-- | /_acb_vec_zero/ /A/ /n/ +-- +-- Sets all entries in /vec/ to zero.+foreign import ccall "acb.h _acb_vec_zero"+ _acb_vec_zero :: Ptr CAcb -> CLong -> IO ()++-- | /_acb_vec_is_zero/ /vec/ /len/ +-- +-- Returns nonzero iff all entries in /x/ are zero.+foreign import ccall "acb.h _acb_vec_is_zero"+ _acb_vec_is_zero :: Ptr CAcb -> CLong -> IO CInt++-- | /_acb_vec_is_real/ /v/ /len/ +-- +-- Returns nonzero iff all entries in /x/ have zero imaginary part.+foreign import ccall "acb.h _acb_vec_is_real"+ _acb_vec_is_real :: Ptr CAcb -> CLong -> IO CInt++-- | /_acb_vec_set/ /res/ /vec/ /len/ +-- +-- Sets /res/ to a copy of /vec/.+foreign import ccall "acb.h _acb_vec_set"+ _acb_vec_set :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /_acb_vec_set_round/ /res/ /vec/ /len/ /prec/ +-- +-- Sets /res/ to a copy of /vec/, rounding each entry to /prec/ bits.+foreign import ccall "acb.h _acb_vec_set_round"+ _acb_vec_set_round :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /_acb_vec_swap/ /vec1/ /vec2/ /len/ +-- +-- Swaps the entries of /vec1/ and /vec2/.+foreign import ccall "acb.h _acb_vec_swap"+ _acb_vec_swap :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_neg"+ _acb_vec_neg :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_add"+ _acb_vec_add :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_sub"+ _acb_vec_sub :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_scalar_submul"+ _acb_vec_scalar_submul :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_scalar_addmul"+ _acb_vec_scalar_addmul :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_scalar_mul"+ _acb_vec_scalar_mul :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_scalar_mul_ui"+ _acb_vec_scalar_mul_ui :: Ptr CAcb -> Ptr CAcb -> CLong -> CULong -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_scalar_mul_2exp_si"+ _acb_vec_scalar_mul_2exp_si :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_scalar_mul_onei"+ _acb_vec_scalar_mul_onei :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_scalar_div_ui"+ _acb_vec_scalar_div_ui :: Ptr CAcb -> Ptr CAcb -> CLong -> CULong -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_scalar_div"+ _acb_vec_scalar_div :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_scalar_mul_arb"+ _acb_vec_scalar_mul_arb :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CArb -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_scalar_div_arb"+ _acb_vec_scalar_div_arb :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CArb -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_scalar_mul_fmpz"+ _acb_vec_scalar_mul_fmpz :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /_acb_vec_scalar_div_fmpz/ /res/ /vec/ /len/ /c/ /prec/ +-- +-- Performs the respective scalar operation elementwise.+foreign import ccall "acb.h _acb_vec_scalar_div_fmpz"+ _acb_vec_scalar_div_fmpz :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /_acb_vec_bits/ /vec/ /len/ +-- +-- Returns the maximum of @arb_bits@ for all entries in /vec/.+foreign import ccall "acb.h _acb_vec_bits"+ _acb_vec_bits :: Ptr CAcb -> CLong -> IO CLong++-- | /_acb_vec_set_powers/ /xs/ /x/ /len/ /prec/ +-- +-- Sets /xs/ to the powers \(1, x, x^2, \ldots, x^{len-1}\).+foreign import ccall "acb.h _acb_vec_set_powers"+ _acb_vec_set_powers :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /_acb_vec_unit_roots/ /z/ /order/ /len/ /prec/ +-- +-- Sets /z/ to the powers \(1,z,z^2,\dots z^{\mathrm{len}-1}\) where+-- \(z=\exp(\frac{2i\pi}{\mathrm{order}})\) to precision /prec/. /order/+-- can be taken negative.+-- +-- In order to avoid precision loss, this function does not simply compute+-- powers of a primitive root.+foreign import ccall "acb.h _acb_vec_unit_roots"+ _acb_vec_unit_roots :: Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb.h _acb_vec_add_error_arf_vec"+ _acb_vec_add_error_arf_vec :: Ptr CAcb -> Ptr CArf -> CLong -> IO ()++-- | /_acb_vec_add_error_mag_vec/ /res/ /err/ /len/ +-- +-- Adds the magnitude of each entry in /err/ to the radius of the+-- corresponding entry in /res/.+foreign import ccall "acb.h _acb_vec_add_error_mag_vec"+ _acb_vec_add_error_mag_vec :: Ptr CAcb -> Ptr CMag -> CLong -> IO ()++-- | /_acb_vec_indeterminate/ /vec/ /len/ +-- +-- Applies @acb_indeterminate@ elementwise.+foreign import ccall "acb.h _acb_vec_indeterminate"+ _acb_vec_indeterminate :: Ptr CAcb -> CLong -> IO ()++-- | /_acb_vec_trim/ /res/ /vec/ /len/ +-- +-- Applies @acb_trim@ elementwise.+foreign import ccall "acb.h _acb_vec_trim"+ _acb_vec_trim :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /_acb_vec_get_unique_fmpz_vec/ /res/ /vec/ /len/ +-- +-- Calls @acb_get_unique_fmpz@ elementwise and returns nonzero if all+-- entries can be rounded uniquely to integers. If any entry in /vec/+-- cannot be rounded uniquely to an integer, returns zero.+foreign import ccall "acb.h _acb_vec_get_unique_fmpz_vec"+ _acb_vec_get_unique_fmpz_vec :: Ptr CFmpz -> Ptr CAcb -> CLong -> IO CInt++-- | /_acb_vec_sort_pretty/ /vec/ /len/ +-- +-- Sorts the vector of complex numbers based on the real and imaginary+-- parts. This is intended to reveal structure when printing a set of+-- complex numbers, not to apply an order relation in a rigorous way.+foreign import ccall "acb.h _acb_vec_sort_pretty"+ _acb_vec_sort_pretty :: Ptr CAcb -> CLong -> IO ()+
+ src/Data/Number/Flint/Acb/Hypgeom.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Acb.Hypgeom (+ module Data.Number.Flint.Acb.Hypgeom.FFI+ ) where++import Data.Number.Flint.Acb.Hypgeom.FFI
+ src/Data/Number/Flint/Acb/Hypgeom/FFI.hsc view
@@ -0,0 +1,1736 @@+{-|+module : Data.Number.Flint.Acb.HypGeom.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Acb.Hypgeom.FFI (+ -- * Hypergeometric functions of complex variables+ -- * Rising factorials+ acb_hypgeom_rising_ui_forward+ , acb_hypgeom_rising_ui_bs+ , acb_hypgeom_rising_ui_rs+ , acb_hypgeom_rising_ui_rec+ , acb_hypgeom_rising_ui+ , acb_hypgeom_rising+ , acb_hypgeom_rising_ui_jet_powsum+ , acb_hypgeom_rising_ui_jet_bs+ , acb_hypgeom_rising_ui_jet_rs+ , acb_hypgeom_rising_ui_jet+ , acb_hypgeom_log_rising_ui+ , acb_hypgeom_log_rising_ui_jet+ -- * Gamma function+ , acb_hypgeom_gamma_stirling_sum_horner+ , acb_hypgeom_gamma_stirling_sum_improved+ , acb_hypgeom_gamma_stirling+ , acb_hypgeom_gamma_taylor+ , acb_hypgeom_gamma+ , acb_hypgeom_rgamma+ , acb_hypgeom_lgamma+ -- * Convergent series+ , acb_hypgeom_pfq_bound_factor+ , acb_hypgeom_pfq_choose_n+ , acb_hypgeom_pfq_sum_forward+ , acb_hypgeom_pfq_sum_rs+ , acb_hypgeom_pfq_sum_bs+ , acb_hypgeom_pfq_sum_fme+ , acb_hypgeom_pfq_sum+ , acb_hypgeom_pfq_sum_bs_invz+ , acb_hypgeom_pfq_sum_invz+ , acb_hypgeom_pfq_direct+ , acb_hypgeom_pfq_series_sum_forward+ , acb_hypgeom_pfq_series_sum_bs+ , acb_hypgeom_pfq_series_sum_rs+ , acb_hypgeom_pfq_series_sum+ , acb_hypgeom_pfq_series_direct+ -- * Asymptotic series+ , acb_hypgeom_u_asymp+ , acb_hypgeom_u_use_asymp+ -- * Generalized hypergeometric function+ , acb_hypgeom_pfq+ -- * Confluent hypergeometric functions+ , acb_hypgeom_u_1f1_series+ , acb_hypgeom_u_1f1+ , acb_hypgeom_u+ , acb_hypgeom_m_asymp+ , acb_hypgeom_m_1f1+ , acb_hypgeom_m+ , acb_hypgeom_1f1+ , acb_hypgeom_0f1_asymp+ , acb_hypgeom_0f1_direct+ , acb_hypgeom_0f1+ -- * Error functions and Fresnel integrals+ , acb_hypgeom_erf_propagated_error+ , acb_hypgeom_erf_1f1a+ , acb_hypgeom_erf_1f1b+ , acb_hypgeom_erf_asymp+ , acb_hypgeom_erf+ , _acb_hypgeom_erf_series+ , acb_hypgeom_erf_series+ , acb_hypgeom_erfc+ , _acb_hypgeom_erfc_series+ , acb_hypgeom_erfc_series+ , acb_hypgeom_erfi+ , _acb_hypgeom_erfi_series+ , acb_hypgeom_erfi_series+ , acb_hypgeom_fresnel+ , _acb_hypgeom_fresnel_series+ , acb_hypgeom_fresnel_series+ -- * Bessel functions+ , acb_hypgeom_bessel_j_asymp+ , acb_hypgeom_bessel_j_0f1+ , acb_hypgeom_bessel_j+ , acb_hypgeom_bessel_y+ , acb_hypgeom_bessel_jy+ -- * Modified Bessel functions+ , acb_hypgeom_bessel_i_asymp+ , acb_hypgeom_bessel_i_0f1+ , acb_hypgeom_bessel_i+ , acb_hypgeom_bessel_i_scaled+ , acb_hypgeom_bessel_k_asymp+ , acb_hypgeom_bessel_k_0f1_series+ , acb_hypgeom_bessel_k_0f1+ , acb_hypgeom_bessel_k+ , acb_hypgeom_bessel_k_scaled+ -- * Airy functions+ , acb_hypgeom_airy_direct+ , acb_hypgeom_airy_asymp+ , acb_hypgeom_airy_bound+ , acb_hypgeom_airy+ , acb_hypgeom_airy_jet+ , _acb_hypgeom_airy_series+ , acb_hypgeom_airy_series+ -- * Coulomb wave functions+ , acb_hypgeom_coulomb+ , acb_hypgeom_coulomb_jet+ , _acb_hypgeom_coulomb_series+ , acb_hypgeom_coulomb_series+ -- * Incomplete gamma and beta functions+ , acb_hypgeom_gamma_upper_asymp+ , acb_hypgeom_gamma_upper_1f1a+ , acb_hypgeom_gamma_upper_1f1b+ , acb_hypgeom_gamma_upper_singular+ , acb_hypgeom_gamma_upper+ , _acb_hypgeom_gamma_upper_series+ , acb_hypgeom_gamma_upper_series+ , acb_hypgeom_gamma_lower+ , _acb_hypgeom_gamma_lower_series+ , acb_hypgeom_gamma_lower_series+ , acb_hypgeom_beta_lower+ , _acb_hypgeom_beta_lower_series+ , acb_hypgeom_beta_lower_series+ -- * Exponential and trigonometric integrals+ , acb_hypgeom_expint+ , acb_hypgeom_ei_asymp+ , acb_hypgeom_ei_2f2+ , acb_hypgeom_ei+ , _acb_hypgeom_ei_series+ , acb_hypgeom_ei_series+ , acb_hypgeom_si_asymp+ , acb_hypgeom_si_1f2+ , acb_hypgeom_si+ , _acb_hypgeom_si_series+ , acb_hypgeom_si_series+ , acb_hypgeom_ci_asymp+ , acb_hypgeom_ci_2f3+ , acb_hypgeom_ci+ , _acb_hypgeom_ci_series+ , acb_hypgeom_ci_series+ , acb_hypgeom_shi+ , _acb_hypgeom_shi_series+ , acb_hypgeom_shi_series+ , acb_hypgeom_chi_asymp+ , acb_hypgeom_chi_2f3+ , acb_hypgeom_chi+ , _acb_hypgeom_chi_series+ , acb_hypgeom_chi_series+ , acb_hypgeom_li+ , _acb_hypgeom_li_series+ , acb_hypgeom_li_series+ -- * Gauss hypergeometric function+ , acb_hypgeom_2f1_continuation+ , acb_hypgeom_2f1_series_direct+ , acb_hypgeom_2f1_direct+ , acb_hypgeom_2f1_transform+ , acb_hypgeom_2f1_transform_limit+ , acb_hypgeom_2f1_corner+ , acb_hypgeom_2f1_choose+ , acb_hypgeom_2f1+ -- * Orthogonal polynomials and functions+ , acb_hypgeom_chebyshev_t+ , acb_hypgeom_chebyshev_u+ , acb_hypgeom_jacobi_p+ , acb_hypgeom_gegenbauer_c+ , acb_hypgeom_laguerre_l+ , acb_hypgeom_hermite_h+ , acb_hypgeom_legendre_p+ , acb_hypgeom_legendre_q+ , acb_hypgeom_legendre_p_uiui_rec+ , acb_hypgeom_spherical_y+ -- * Dilogarithm+ , acb_hypgeom_dilog_zero_taylor+ , acb_hypgeom_dilog_zero+ , acb_hypgeom_dilog_transform+ , acb_hypgeom_dilog_continuation+ , acb_hypgeom_dilog_bitburst+ , acb_hypgeom_dilog+) where ++-- Hypergeometric functions of complex variables -------------------------------++import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr )++import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb+import Data.Number.Flint.Acb.Types+import Data.Number.Flint.Acb.Poly++-- Rising factorials -----------------------------------------------------------++-- | /acb_hypgeom_rising_ui_forward/ /res/ /x/ /n/ /prec/ +foreign import ccall "acb_hypgeom.h acb_hypgeom_rising_ui_forward"+ acb_hypgeom_rising_ui_forward :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()+-- | /acb_hypgeom_rising_ui_bs/ /res/ /x/ /n/ /prec/ +foreign import ccall "acb_hypgeom.h acb_hypgeom_rising_ui_bs"+ acb_hypgeom_rising_ui_bs :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()+-- | /acb_hypgeom_rising_ui_rs/ /res/ /x/ /n/ /m/ /prec/ +foreign import ccall "acb_hypgeom.h acb_hypgeom_rising_ui_rs"+ acb_hypgeom_rising_ui_rs :: Ptr CAcb -> Ptr CAcb -> CULong -> CULong -> CLong -> IO ()+-- | /acb_hypgeom_rising_ui_rec/ /res/ /x/ /n/ /prec/ +foreign import ccall "acb_hypgeom.h acb_hypgeom_rising_ui_rec"+ acb_hypgeom_rising_ui_rec :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()+-- | /acb_hypgeom_rising_ui/ /res/ /x/ /n/ /prec/ +foreign import ccall "acb_hypgeom.h acb_hypgeom_rising_ui"+ acb_hypgeom_rising_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()+-- | /acb_hypgeom_rising/ /res/ /x/ /n/ /prec/ +--+-- Computes the rising factorial \((x)_n\).+-- +-- The /forward/ version uses the forward recurrence. The /bs/ version uses+-- binary splitting. The /rs/ version uses rectangular splitting. It takes+-- an extra tuning parameter /m/ which can be set to zero to choose+-- automatically. The /rec/ version chooses an algorithm automatically,+-- avoiding use of the gamma function (so that it can be used in the+-- computation of the gamma function). The default versions (/rising_ui/+-- and /rising_ui/) choose an algorithm automatically and may additionally+-- fall back on the gamma function.+foreign import ccall "acb_hypgeom.h acb_hypgeom_rising"+ acb_hypgeom_rising :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_rising_ui_jet_powsum/ /res/ /x/ /n/ /len/ /prec/ +foreign import ccall "acb_hypgeom.h acb_hypgeom_rising_ui_jet_powsum"+ acb_hypgeom_rising_ui_jet_powsum :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> CLong -> IO ()+-- | /acb_hypgeom_rising_ui_jet_bs/ /res/ /x/ /n/ /len/ /prec/ +foreign import ccall "acb_hypgeom.h acb_hypgeom_rising_ui_jet_bs"+ acb_hypgeom_rising_ui_jet_bs :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> CLong -> IO ()+-- | /acb_hypgeom_rising_ui_jet_rs/ /res/ /x/ /n/ /m/ /len/ /prec/ +foreign import ccall "acb_hypgeom.h acb_hypgeom_rising_ui_jet_rs"+ acb_hypgeom_rising_ui_jet_rs :: Ptr CAcb -> Ptr CAcb -> CULong -> CULong -> CLong -> CLong -> IO ()+-- | /acb_hypgeom_rising_ui_jet/ /res/ /x/ /n/ /len/ /prec/ +--+-- Computes the jet of the rising factorial \((x)_n\), truncated to length+-- /len/. In other words, constructs the polynomial+-- \((X + x)_n \in \mathbb{R}[X]\), truncated if+-- \(\operatorname{len} < n + 1\) (and zero-extended if+-- \(\operatorname{len} > n + 1\)).+-- +-- The /powsum/ version computes the sequence of powers of /x/ and forms+-- integral linear combinations of these. The /bs/ version uses binary+-- splitting. The /rs/ version uses rectangular splitting. It takes an+-- extra tuning parameter /m/ which can be set to zero to choose+-- automatically. The default version chooses an algorithm automatically.+foreign import ccall "acb_hypgeom.h acb_hypgeom_rising_ui_jet"+ acb_hypgeom_rising_ui_jet :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_log_rising_ui/ /res/ /x/ /n/ /prec/ +--+-- Computes the log-rising factorial+-- \(\log \, (x)_n = \sum_{k=0}^{n-1} \log(x+k)\).+-- +-- This first computes the ordinary rising factorial and then determines+-- the branch correction \(2 \pi i m\) with respect to the principal+-- logarithm. The correction is computed using Hare\'s algorithm in+-- floating-point arithmetic if this is safe; otherwise, a direct+-- computation of \(\sum_{k=0}^{n-1} \arg(x+k)\) is used as a fallback.+foreign import ccall "acb_hypgeom.h acb_hypgeom_log_rising_ui"+ acb_hypgeom_log_rising_ui :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> IO ()++-- | /acb_hypgeom_log_rising_ui_jet/ /res/ /x/ /n/ /len/ /prec/ +--+-- Computes the jet of the log-rising factorial \(\log \, (x)_n\),+-- truncated to length /len/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_log_rising_ui_jet"+ acb_hypgeom_log_rising_ui_jet :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> CLong -> IO ()++-- Gamma function --------------------------------------------------------------++-- | /acb_hypgeom_gamma_stirling_sum_horner/ /s/ /z/ /N/ /prec/ +foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_stirling_sum_horner"+ acb_hypgeom_gamma_stirling_sum_horner :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()+-- | /acb_hypgeom_gamma_stirling_sum_improved/ /s/ /z/ /N/ /K/ /prec/ +--+-- Sets /res/ to the final sum in the Stirling series for the gamma+-- function truncated before the term with index /N/, i.e. computes+-- \(\sum_{n=1}^{N-1} B_{2n} / (2n(2n-1) z^{2n-1})\). The /horner/ version+-- uses Horner scheme with gradual precision adjustments. The /improved/+-- version uses rectangular splitting for the low-index terms and reexpands+-- the high-index terms as hypergeometric polynomials, using a splitting+-- parameter /K/ (which can be set to 0 to use a default value).+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_stirling_sum_improved"+ acb_hypgeom_gamma_stirling_sum_improved :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_gamma_stirling/ /res/ /x/ /reciprocal/ /prec/ +--+-- Sets /res/ to the gamma function of /x/ computed using the Stirling+-- series together with argument reduction. If /reciprocal/ is set, the+-- reciprocal gamma function is computed instead.+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_stirling"+ acb_hypgeom_gamma_stirling :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_gamma_taylor/ /res/ /x/ /reciprocal/ /prec/ +--+-- Attempts to compute the gamma function of /x/ using Taylor series+-- together with argument reduction. This is only supported if /x/ and+-- /prec/ are both small enough. If successful, returns 1; otherwise, does+-- nothing and returns 0. If /reciprocal/ is set, the reciprocal gamma+-- function is computed instead.+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_taylor"+ acb_hypgeom_gamma_taylor :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO CInt++-- | /acb_hypgeom_gamma/ /res/ /x/ /prec/ +--+-- Sets /res/ to the gamma function of /x/ computed using a default+-- algorithm choice.+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma"+ acb_hypgeom_gamma :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_rgamma/ /res/ /x/ /prec/ +--+-- Sets /res/ to the reciprocal gamma function of /x/ computed using a+-- default algorithm choice.+foreign import ccall "acb_hypgeom.h acb_hypgeom_rgamma"+ acb_hypgeom_rgamma :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_lgamma/ /res/ /x/ /prec/ +--+-- Sets /res/ to the principal branch of the log-gamma function of /x/+-- computed using a default algorithm choice.+foreign import ccall "acb_hypgeom.h acb_hypgeom_lgamma"+ acb_hypgeom_lgamma :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Convergent series -----------------------------------------------------------++-- In this section, we define+--+-- \[`\]+-- \[T(k) = \frac{\prod_{i=0}^{p-1} (a_i)_k}{\prod_{i=0}^{q-1} (b_i)_k} z^k\]+--+-- and+--+-- \[`\]+-- \[{}_pf_{q}(a_0,\ldots,a_{p-1}; b_0 \ldots b_{q-1}; z) = {}_{p+1}F_{q}(a_0,\ldots,a_{p-1},1; b_0 \ldots b_{q-1}; z) = \sum_{k=0}^{\infty} T(k)\]+--+-- For the conventional generalized hypergeometric function {}_pF_{q},+-- compute \({}_pf_{q+1}\) with the explicit parameter \(b_q = 1\), or+-- remove a 1 from the \(a_i\) parameters if there is one.+--+-- | /acb_hypgeom_pfq_bound_factor/ /C/ /a/ /p/ /b/ /q/ /z/ /n/ +--+-- Computes a factor /C/ such that+-- \(\left|\sum_{k=n}^{\infty} T(k)\right| \le C |T(n)|\). See+-- @algorithms_hypergeometric_convergent@. As currently implemented, the+-- bound becomes infinite when \(n\) is too small, even if the series+-- converges.+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_bound_factor"+ acb_hypgeom_pfq_bound_factor :: Ptr CMag -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> Ptr CAcb -> CULong -> IO ()++-- | /acb_hypgeom_pfq_choose_n/ /a/ /p/ /b/ /q/ /z/ /prec/ +--+-- Heuristically attempts to choose a number of terms /n/ to sum of a+-- hypergeometric series at a working precision of /prec/ bits.+-- +-- Uses double precision arithmetic internally. As currently implemented,+-- it can fail to produce a good result if the parameters are extremely+-- large or extremely close to nonpositive integers.+-- +-- Numerical cancellation is assumed to be significant, so truncation is+-- done when the current term is /prec/ bits smaller than the largest+-- encountered term.+-- +-- This function will also attempt to pick a reasonable truncation point+-- for divergent series.+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_choose_n"+ acb_hypgeom_pfq_choose_n :: Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO CLong++-- | /acb_hypgeom_pfq_sum_forward/ /s/ /t/ /a/ /p/ /b/ /q/ /z/ /n/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_sum_forward"+ acb_hypgeom_pfq_sum_forward :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_sum_rs/ /s/ /t/ /a/ /p/ /b/ /q/ /z/ /n/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_sum_rs"+ acb_hypgeom_pfq_sum_rs :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_sum_bs/ /s/ /t/ /a/ /p/ /b/ /q/ /z/ /n/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_sum_bs"+ acb_hypgeom_pfq_sum_bs :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_sum_fme/ /s/ /t/ /a/ /p/ /b/ /q/ /z/ /n/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_sum_fme"+ acb_hypgeom_pfq_sum_fme :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_sum/ /s/ /t/ /a/ /p/ /b/ /q/ /z/ /n/ /prec/ +--+-- Computes \(s = \sum_{k=0}^{n-1} T(k)\) and \(t = T(n)\). Does not allow+-- aliasing between input and output variables. We require \(n \ge 0\).+-- +-- The /forward/ version computes the sum using forward recurrence.+-- +-- The /bs/ version computes the sum using binary splitting.+-- +-- The /rs/ version computes the sum in reverse order using rectangular+-- splitting. It only computes a magnitude bound for the value of /t/.+-- +-- The /fme/ version uses fast multipoint evaluation.+-- +-- The default version automatically chooses an algorithm depending on the+-- inputs.+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_sum"+ acb_hypgeom_pfq_sum :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_sum_bs_invz/ /s/ /t/ /a/ /p/ /b/ /q/ /w/ /n/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_sum_bs_invz"+ acb_hypgeom_pfq_sum_bs_invz :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_sum_invz/ /s/ /t/ /a/ /p/ /b/ /q/ /z/ /w/ /n/ /prec/ +--+-- Like @acb_hypgeom_pfq_sum@, but taking advantage of \(w = 1/z\) possibly+-- having few bits.+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_sum_invz"+ acb_hypgeom_pfq_sum_invz :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_direct/ /res/ /a/ /p/ /b/ /q/ /z/ /n/ /prec/ +--+-- Computes+-- +-- \[{}_pf_{q}(z)+-- = \sum_{k=0}^{\infty} T(k)+-- = \sum_{k=0}^{n-1} T(k) + \varepsilon\]+-- +-- directly from the defining series, including a rigorous bound for the+-- truncation error \(\varepsilon\) in the output.+-- +-- If \(n < 0\), this function chooses a number of terms automatically+-- using @acb_hypgeom_pfq_choose_n@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_direct"+ acb_hypgeom_pfq_direct :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_series_sum_forward/ /s/ /t/ /a/ /p/ /b/ /q/ /z/ /regularized/ /n/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_series_sum_forward"+ acb_hypgeom_pfq_series_sum_forward :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr (Ptr CAcbPoly) -> CLong -> Ptr (Ptr CAcbPoly) -> CLong -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_series_sum_bs/ /s/ /t/ /a/ /p/ /b/ /q/ /z/ /regularized/ /n/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_series_sum_bs"+ acb_hypgeom_pfq_series_sum_bs :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr (Ptr CAcbPoly) -> CLong -> Ptr (Ptr CAcbPoly) -> CLong -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_series_sum_rs/ /s/ /t/ /a/ /p/ /b/ /q/ /z/ /regularized/ /n/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_series_sum_rs"+ acb_hypgeom_pfq_series_sum_rs :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr (Ptr CAcbPoly) -> CLong -> Ptr (Ptr CAcbPoly) -> CLong -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_series_sum/ /s/ /t/ /a/ /p/ /b/ /q/ /z/ /regularized/ /n/ /len/ /prec/ +--+-- Computes \(s = \sum_{k=0}^{n-1} T(k)\) and \(t = T(n)\) given parameters+-- and argument that are power series. Does not allow aliasing between+-- input and output variables. We require \(n \ge 0\) and that /len/ is+-- positive.+-- +-- If /regularized/ is set, the regularized sum is computed, avoiding+-- division by zero at the poles of the gamma function.+-- +-- The /forward/, /bs/, /rs/ and default versions use forward recurrence,+-- binary splitting, rectangular splitting, and an automatic algorithm+-- choice.+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_series_sum"+ acb_hypgeom_pfq_series_sum :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr (Ptr CAcbPoly) -> CLong -> Ptr (Ptr CAcbPoly) -> CLong -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_pfq_series_direct/ /res/ /a/ /p/ /b/ /q/ /z/ /regularized/ /n/ /len/ /prec/ +--+-- Computes \({}_pf_{q}(z)\) directly using the defining series, given+-- parameters and argument that are power series. The result is a power+-- series of length /len/. We require that /len/ is positive.+-- +-- An error bound is computed automatically as a function of the number of+-- terms /n/. If \(n < 0\), the number of terms is chosen automatically.+-- +-- If /regularized/ is set, the regularized hypergeometric function is+-- computed instead.+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq_series_direct"+ acb_hypgeom_pfq_series_direct :: Ptr CAcbPoly -> Ptr (Ptr CAcbPoly) -> CLong -> Ptr (Ptr CAcbPoly) -> CLong -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> CLong -> IO ()++-- Asymptotic series -----------------------------------------------------------++-- U(a,b,z) is the confluent hypergeometric function of the second kind+-- with the principal branch cut, and \(U^{*} = z^a U(a,b,z)\). For details+-- about how error bounds are computed, see+-- @algorithms_hypergeometric_asymptotic_confluent@.+--+-- | /acb_hypgeom_u_asymp/ /res/ /a/ /b/ /z/ /n/ /prec/ +--+-- Sets /res/ to \(U^{*}(a,b,z)\) computed using /n/ terms of the+-- asymptotic series, with a rigorous bound for the error included in the+-- output. We require \(n \ge 0\).+foreign import ccall "acb_hypgeom.h acb_hypgeom_u_asymp"+ acb_hypgeom_u_asymp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_u_use_asymp/ /z/ /prec/ +--+-- Heuristically determines whether the asymptotic series can be used to+-- evaluate \(U(a,b,z)\) to /prec/ accurate bits (assuming that /a/ and /b/+-- are small).+foreign import ccall "acb_hypgeom.h acb_hypgeom_u_use_asymp"+ acb_hypgeom_u_use_asymp :: Ptr CAcb -> CLong -> IO CInt++-- Generalized hypergeometric function -----------------------------------------++-- | /acb_hypgeom_pfq/ /res/ /a/ /p/ /b/ /q/ /z/ /regularized/ /prec/ +--+-- Computes the generalized hypergeometric function \({}_pF_{q}(z)\), or+-- the regularized version if /regularized/ is set.+-- +-- This function automatically delegates to a specialized implementation+-- when the order (/p/, /q/) is one of (0,0), (1,0), (0,1), (1,1), (2,1).+-- Otherwise, it falls back to direct summation.+-- +-- While this is a top-level function meant to take care of special cases+-- automatically, it does not generally perform the optimization of+-- deleting parameters that appear in both /a/ and /b/. This can be done+-- ahead of time by the user in applications where duplicate parameters are+-- likely to occur.+foreign import ccall "acb_hypgeom.h acb_hypgeom_pfq"+ acb_hypgeom_pfq :: Ptr CAcbPoly -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> Ptr CAcb -> CInt -> CLong -> IO ()++-- Confluent hypergeometric functions ------------------------------------------++-- | /acb_hypgeom_u_1f1_series/ /res/ /a/ /b/ /z/ /len/ /prec/ +--+-- Computes \(U(a,b,z)\) as a power series truncated to length /len/, given+-- \(a, b, z \in \mathbb{C}[[x]]\). If \(b[0] \in \mathbb{Z}\), it computes+-- one extra derivative and removes the singularity (it is then assumed+-- that \(b[1] \ne 0\)). As currently implemented, the output is+-- indeterminate if \(b\) is nonexact and contains an integer.+foreign import ccall "acb_hypgeom.h acb_hypgeom_u_1f1_series"+ acb_hypgeom_u_1f1_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_u_1f1/ /res/ /a/ /b/ /z/ /prec/ +--+-- Computes \(U(a,b,z)\) as a sum of two convergent hypergeometric series.+-- If \(b \in \mathbb{Z}\), it computes the limit value via+-- @acb_hypgeom_u_1f1_series@. As currently implemented, the output is+-- indeterminate if \(b\) is nonexact and contains an integer.+foreign import ccall "acb_hypgeom.h acb_hypgeom_u_1f1"+ acb_hypgeom_u_1f1 :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_u/ /res/ /a/ /b/ /z/ /prec/ +--+-- Computes \(U(a,b,z)\) using an automatic algorithm choice. The function+-- @acb_hypgeom_u_asymp@ is used if \(a\) or \(a-b+1\) is a nonpositive+-- integer (in which case the asymptotic series terminates), or if /z/ is+-- sufficiently large. Otherwise @acb_hypgeom_u_1f1@ is used.+foreign import ccall "acb_hypgeom.h acb_hypgeom_u"+ acb_hypgeom_u :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_m_asymp/ /res/ /a/ /b/ /z/ /regularized/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_m_asymp"+ acb_hypgeom_m_asymp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_m_1f1/ /res/ /a/ /b/ /z/ /regularized/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_m_1f1"+ acb_hypgeom_m_1f1 :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_m/ /res/ /a/ /b/ /z/ /regularized/ /prec/ +--+-- Computes the confluent hypergeometric function+-- \(M(a,b,z) = {}_1F_1(a,b,z)\), or+-- \(\mathbf{M}(a,b,z) = \frac{1}{\Gamma(b)} {}_1F_1(a,b,z)\) if+-- /regularized/ is set.+foreign import ccall "acb_hypgeom.h acb_hypgeom_m"+ acb_hypgeom_m :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_1f1/ /res/ /a/ /b/ /z/ /regularized/ /prec/ +--+-- Alias for @acb_hypgeom_m@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_1f1"+ acb_hypgeom_1f1 :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_0f1_asymp/ /res/ /a/ /z/ /regularized/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_0f1_asymp"+ acb_hypgeom_0f1_asymp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_0f1_direct/ /res/ /a/ /z/ /regularized/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_0f1_direct"+ acb_hypgeom_0f1_direct :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_0f1/ /res/ /a/ /z/ /regularized/ /prec/ +--+-- Computes the confluent hypergeometric function \({}_0F_1(a,z)\), or+-- \(\frac{1}{\Gamma(a)} {}_0F_1(a,z)\) if /regularized/ is set, using+-- asymptotic expansions, direct summation, or an automatic algorithm+-- choice. The /asymp/ version uses the asymptotic expansions of Bessel+-- functions, together with the connection formulas+-- +-- \[`\]+-- \[\frac{{}_0F_1(a,z)}{\Gamma(a)} = (-z)^{(1-a)/2} J_{a-1}(2 \sqrt{-z}) =+-- z^{(1-a)/2} I_{a-1}(2 \sqrt{z}).\]+-- +-- The Bessel-/J/ function is used in the left half-plane and the+-- Bessel-/I/ function is used in the right half-plane, to avoid loss of+-- accuracy due to evaluating the square root on the branch cut.+foreign import ccall "acb_hypgeom.h acb_hypgeom_0f1"+ acb_hypgeom_0f1 :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- Error functions and Fresnel integrals ---------------------------------------++-- | /acb_hypgeom_erf_propagated_error/ /re/ /im/ /z/ +--+-- Sets /re/ and /im/ to upper bounds for the error in the real and+-- imaginary part resulting from approximating the error function of /z/ by+-- the error function evaluated at the midpoint of /z/. Uses the first+-- derivative.+foreign import ccall "acb_hypgeom.h acb_hypgeom_erf_propagated_error"+ acb_hypgeom_erf_propagated_error :: Ptr CMag -> Ptr CMag -> Ptr CAcb -> IO ()++-- | /acb_hypgeom_erf_1f1a/ /res/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_erf_1f1a"+ acb_hypgeom_erf_1f1a :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_erf_1f1b/ /res/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_erf_1f1b"+ acb_hypgeom_erf_1f1b :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_erf_asymp/ /res/ /z/ /complementary/ /prec/ /prec2/ +--+-- Computes the error function respectively using+-- +-- \[+-- \begin{aligned}+-- \operatorname{erf}(z) &= \frac{2z}{\sqrt{\pi}}+-- {}_1F_1(\tfrac{1}{2}, \tfrac{3}{2}, -z^2)\\+-- \operatorname{erf}(z) &= \frac{2z e^{-z^2}}{\sqrt{\pi}}+-- {}_1F_1(1, \tfrac{3}{2}, z^2)\\+-- \operatorname{erf}(z) &= \frac{z}{\sqrt{z^2}}+-- \left(1 - \frac{e^{-z^2}}{\sqrt{\pi}}+-- U(\tfrac{1}{2}, \tfrac{1}{2}, z^2)\right) =+-- \frac{z}{\sqrt{z^2}} - \frac{e^{-z^2}}{z \sqrt{\pi}}+-- U^{*}(\tfrac{1}{2}, \tfrac{1}{2}, z^2).+-- \end{aligned}+-- \]+-- +-- The /asymp/ version takes a second precision to use for the /U/ term. It+-- also takes an extra flag /complementary/, computing the complementary+-- error function if set.+foreign import ccall "acb_hypgeom.h acb_hypgeom_erf_asymp"+ acb_hypgeom_erf_asymp :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_erf/ /res/ /z/ /prec/ +--+-- Computes the error function using an automatic algorithm choice. If /z/+-- is too small to use the asymptotic expansion, a working precision+-- sufficient to circumvent cancellation in the hypergeometric series is+-- determined automatically, and a bound for the propagated error is+-- computed with @acb_hypgeom_erf_propagated_error@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_erf"+ acb_hypgeom_erf :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /_acb_hypgeom_erf_series/ /res/ /z/ /zlen/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_erf_series"+ _acb_hypgeom_erf_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_erf_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the error function of the power series /z/, truncated to length+-- /len/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_erf_series"+ acb_hypgeom_erf_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_erfc/ /res/ /z/ /prec/ +--+-- Computes the complementary error function+-- \(\operatorname{erfc}(z) = 1 - \operatorname{erf}(z)\). This function+-- avoids catastrophic cancellation for large positive /z/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_erfc"+ acb_hypgeom_erfc :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /_acb_hypgeom_erfc_series/ /res/ /z/ /zlen/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_erfc_series"+ _acb_hypgeom_erfc_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_erfc_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the complementary error function of the power series /z/,+-- truncated to length /len/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_erfc_series"+ acb_hypgeom_erfc_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_erfi/ /res/ /z/ /prec/ +--+-- Computes the imaginary error function+-- \(\operatorname{erfi}(z) = -i\operatorname{erf}(iz)\). This is a trivial+-- wrapper of @acb_hypgeom_erf@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_erfi"+ acb_hypgeom_erfi :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /_acb_hypgeom_erfi_series/ /res/ /z/ /zlen/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_erfi_series"+ _acb_hypgeom_erfi_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_erfi_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the imaginary error function of the power series /z/, truncated+-- to length /len/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_erfi_series"+ acb_hypgeom_erfi_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_fresnel/ /res1/ /res2/ /z/ /normalized/ /prec/ +--+-- Sets /res1/ to the Fresnel sine integral \(S(z)\) and /res2/ to the+-- Fresnel cosine integral \(C(z)\). Optionally, just a single function can+-- be computed by passing /NULL/ as the other output variable. The+-- definition \(S(z) = \int_0^z \sin(t^2) dt\) is used if /normalized/ is+-- 0, and \(S(z) = \int_0^z \sin(\tfrac{1}{2} \pi t^2) dt\) is used if+-- /normalized/ is 1 (the latter is the Abramowitz & Stegun convention).+-- \(C(z)\) is defined analogously.+foreign import ccall "acb_hypgeom.h acb_hypgeom_fresnel"+ acb_hypgeom_fresnel :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /_acb_hypgeom_fresnel_series/ /res1/ /res2/ /z/ /zlen/ /normalized/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_fresnel_series"+ _acb_hypgeom_fresnel_series :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CInt -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_fresnel_series/ /res1/ /res2/ /z/ /normalized/ /len/ /prec/ +--+-- Sets /res1/ to the Fresnel sine integral and /res2/ to the Fresnel+-- cosine integral of the power series /z/, truncated to length /len/.+-- Optionally, just a single function can be computed by passing /NULL/ as+-- the other output variable.+foreign import ccall "acb_hypgeom.h acb_hypgeom_fresnel_series"+ acb_hypgeom_fresnel_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> IO ()++-- Bessel functions ------------------------------------------------------------++-- | /acb_hypgeom_bessel_j_asymp/ /res/ /nu/ /z/ /prec/ +--+-- Computes the Bessel function of the first kind via+-- @acb_hypgeom_u_asymp@. For all complex \(\nu, z\), we have+-- +-- \[`\]+-- \[J_{\nu}(z) = \frac{z^{\nu}}{2^{\nu} e^{iz} \Gamma(\nu+1)}+-- {}_1F_1(\nu+\tfrac{1}{2}, 2\nu+1, 2iz) = A_{+} B_{+} + A_{-} B_{-}\]+-- +-- where+-- +-- \[`\]+-- \[A_{\pm} = z^{\nu} (z^2)^{-\tfrac{1}{2}-\nu} (\mp i z)^{\tfrac{1}{2}+\nu} (2 \pi)^{-1/2} = (\pm iz)^{-1/2-\nu} z^{\nu} (2 \pi)^{-1/2}\]+-- +-- \[`\]+-- \[B_{\pm} = e^{\pm i z} U^{*}(\nu+\tfrac{1}{2}, 2\nu+1, \mp 2iz).\]+-- +-- Nicer representations of the factors \(A_{\pm}\) can be given depending+-- conditionally on the parameters. If+-- \(\nu + \tfrac{1}{2} = n \in \mathbb{Z}\), we have+-- \(A_{\pm} = (\pm i)^{n} (2 \pi z)^{-1/2}\). And if+-- \(\operatorname{Re}(z) > 0\), we have+-- \(A_{\pm} = \exp(\mp i [(2\nu+1)/4] \pi) (2 \pi z)^{-1/2}\).+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_j_asymp"+ acb_hypgeom_bessel_j_asymp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_bessel_j_0f1/ /res/ /nu/ /z/ /prec/ +--+-- Computes the Bessel function of the first kind from+-- +-- \[`\]+-- \[J_{\nu}(z) = \frac{1}{\Gamma(\nu+1)} \left(\frac{z}{2}\right)^{\nu}+-- {}_0F_1\left(\nu+1, -\frac{z^2}{4}\right).\]+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_j_0f1"+ acb_hypgeom_bessel_j_0f1 :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_bessel_j/ /res/ /nu/ /z/ /prec/ +--+-- Computes the Bessel function of the first kind \(J_{\nu}(z)\) using an+-- automatic algorithm choice.+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_j"+ acb_hypgeom_bessel_j :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_bessel_y/ /res/ /nu/ /z/ /prec/ +--+-- Computes the Bessel function of the second kind \(Y_{\nu}(z)\) from the+-- formula+-- +-- \[`\]+-- \[Y_{\nu}(z) = \frac{\cos(\nu \pi) J_{\nu}(z) - J_{-\nu}(z)}{\sin(\nu \pi)}\]+-- +-- unless \(\nu = n\) is an integer in which case the limit value+-- +-- \[`\]+-- \[Y_n(z) = -\frac{2}{\pi} \left( i^n K_n(iz) ++-- \left[\log(iz)-\log(z)\right] J_n(z) \right)\]+-- +-- is computed. As currently implemented, the output is indeterminate if+-- \(\nu\) is nonexact and contains an integer.+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_y"+ acb_hypgeom_bessel_y :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_bessel_jy/ /res1/ /res2/ /nu/ /z/ /prec/ +--+-- Sets /res1/ to \(J_{\nu}(z)\) and /res2/ to \(Y_{\nu}(z)\), computed+-- simultaneously. From these values, the user can easily construct the+-- Bessel functions of the third kind (Hankel functions)+-- \(H_{\nu}^{(1)}(z), H_{\nu}^{(2)}(z) = J_{\nu}(z) \pm i Y_{\nu}(z)\).+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_jy"+ acb_hypgeom_bessel_jy :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Modified Bessel functions ---------------------------------------------------++-- | /acb_hypgeom_bessel_i_asymp/ /res/ /nu/ /z/ /scaled/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_i_asymp"+ acb_hypgeom_bessel_i_asymp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_bessel_i_0f1/ /res/ /nu/ /z/ /scaled/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_i_0f1"+ acb_hypgeom_bessel_i_0f1 :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_bessel_i/ /res/ /nu/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_i"+ acb_hypgeom_bessel_i :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_bessel_i_scaled/ /res/ /nu/ /z/ /prec/ +--+-- Computes the modified Bessel function of the first kind+-- \(I_{\nu}(z) = z^{\nu} (iz)^{-\nu} J_{\nu}(iz)\) respectively using+-- asymptotic series (see @acb_hypgeom_bessel_j_asymp@), the convergent+-- series+-- +-- \[`\]+-- \[I_{\nu}(z) = \frac{1}{\Gamma(\nu+1)} \left(\frac{z}{2}\right)^{\nu}+-- {}_0F_1\left(\nu+1, \frac{z^2}{4}\right),\]+-- +-- or an automatic algorithm choice.+-- +-- The /scaled/ version computes the function \(e^{-z} I_{\nu}(z)\). The+-- /asymp/ and /0f1/ functions implement both variants and allow choosing+-- with a flag.+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_i_scaled"+ acb_hypgeom_bessel_i_scaled :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_bessel_k_asymp/ /res/ /nu/ /z/ /scaled/ /prec/ +--+-- Computes the modified Bessel function of the second kind via via+-- @acb_hypgeom_u_asymp@. For all \(\nu\) and all \(z \ne 0\), we have+-- +-- \[`\]+-- \[K_{\nu}(z) = \left(\frac{2z}{\pi}\right)^{-1/2} e^{-z}+-- U^{*}(\nu+\tfrac{1}{2}, 2\nu+1, 2z).\]+-- +-- If /scaled/ is set, computes the function \(e^{z} K_{\nu}(z)\).+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_k_asymp"+ acb_hypgeom_bessel_k_asymp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_bessel_k_0f1_series/ /res/ /nu/ /z/ /scaled/ /len/ /prec/ +--+-- Computes the modified Bessel function of the second kind \(K_{\nu}(z)\)+-- as a power series truncated to length /len/, given+-- \(\nu, z \in \mathbb{C}[[x]]\). Uses the formula+-- +-- \[`\]+-- \[K_{\nu}(z) = \frac{1}{2} \frac{\pi}{\sin(\pi \nu)} \left[+-- \left(\frac{z}{2}\right)^{-\nu}+-- {}_0{\widetilde F}_1\left(1-\nu, \frac{z^2}{4}\right)+-- -+-- \left(\frac{z}{2}\right)^{\nu}+-- {}_0{\widetilde F}_1\left(1+\nu, \frac{z^2}{4}\right)+-- \right].\]+-- +-- If \(\nu[0] \in \mathbb{Z}\), it computes one extra derivative and+-- removes the singularity (it is then assumed that \(\nu[1] \ne 0\)). As+-- currently implemented, the output is indeterminate if \(\nu[0]\) is+-- nonexact and contains an integer.+-- +-- If /scaled/ is set, computes the function \(e^{z} K_{\nu}(z)\).+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_k_0f1_series"+ acb_hypgeom_bessel_k_0f1_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_bessel_k_0f1/ /res/ /nu/ /z/ /scaled/ /prec/ +--+-- Computes the modified Bessel function of the second kind from+-- +-- \[`\]+-- \[K_{\nu}(z) = \frac{1}{2} \left[+-- \left(\frac{z}{2}\right)^{-\nu}+-- \Gamma(\nu)+-- {}_0F_1\left(1-\nu, \frac{z^2}{4}\right)+-- -+-- \left(\frac{z}{2}\right)^{\nu}+-- \frac{\pi}{\nu \sin(\pi \nu) \Gamma(\nu)}+-- {}_0F_1\left(\nu+1, \frac{z^2}{4}\right)+-- \right]\]+-- +-- if \(\nu \notin \mathbb{Z}\). If \(\nu \in \mathbb{Z}\), it computes the+-- limit value via @acb_hypgeom_bessel_k_0f1_series@. As currently+-- implemented, the output is indeterminate if \(\nu\) is nonexact and+-- contains an integer.+-- +-- If /scaled/ is set, computes the function \(e^{z} K_{\nu}(z)\).+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_k_0f1"+ acb_hypgeom_bessel_k_0f1 :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_bessel_k/ /res/ /nu/ /z/ /prec/ +--+-- Computes the modified Bessel function of the second kind \(K_{\nu}(z)\)+-- using an automatic algorithm choice.+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_k"+ acb_hypgeom_bessel_k :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_bessel_k_scaled/ /res/ /nu/ /z/ /prec/ +--+-- Computes the function \(e^{z} K_{\nu}(z)\).+foreign import ccall "acb_hypgeom.h acb_hypgeom_bessel_k_scaled"+ acb_hypgeom_bessel_k_scaled :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Airy functions --------------------------------------------------------------++-- The Airy functions are linearly independent solutions of the+-- differential equation \(y'' - zy = 0\). All solutions are entire+-- functions. The standard solutions are denoted+-- \(\operatorname{Ai}(z), \operatorname{Bi}(z)\). For negative /z/, both+-- functions are oscillatory. For positive /z/, the first function+-- decreases exponentially while the second increases exponentially.+--+-- The Airy functions can be expressed in terms of Bessel functions of+-- fractional order, but this is inconvenient since such formulas only hold+-- piecewise (due to the Stokes phenomenon). Computation of the Airy+-- functions can also be optimized more than Bessel functions in general.+-- We therefore provide a dedicated interface for evaluating Airy+-- functions.+--+-- The following methods optionally compute (operatorname{Ai}(z),+-- operatorname{Ai}\'(z), operatorname{Bi}(z), operatorname{Bi}\'(z))+-- simultaneously. Any of the four function values can be omitted by+-- passing /NULL/ for the unwanted output variables, speeding up the+-- evaluation.+--+-- | /acb_hypgeom_airy_direct/ /ai/ /ai_prime/ /bi/ /bi_prime/ /z/ /n/ /prec/ +--+-- Computes the Airy functions using direct series expansions truncated at+-- /n/ terms. Error bounds are included in the output.+foreign import ccall "acb_hypgeom.h acb_hypgeom_airy_direct"+ acb_hypgeom_airy_direct :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_airy_asymp/ /ai/ /ai_prime/ /bi/ /bi_prime/ /z/ /n/ /prec/ +--+-- Computes the Airy functions using asymptotic expansions truncated at /n/+-- terms. Error bounds are included in the output. For details about how+-- the error bounds are computed, see+-- @algorithms_hypergeometric_asymptotic_airy@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_airy_asymp"+ acb_hypgeom_airy_asymp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_airy_bound/ /ai/ /ai_prime/ /bi/ /bi_prime/ /z/ +--+-- Computes bounds for the Airy functions using first-order asymptotic+-- expansions together with error bounds. This function uses some shortcuts+-- to make it slightly faster than calling @acb_hypgeom_airy_asymp@ with+-- \(n = 1\).+foreign import ccall "acb_hypgeom.h acb_hypgeom_airy_bound"+ acb_hypgeom_airy_bound :: Ptr CMag -> Ptr CMag -> Ptr CMag -> Ptr CMag -> Ptr CAcb -> IO ()++-- | /acb_hypgeom_airy/ /ai/ /ai_prime/ /bi/ /bi_prime/ /z/ /prec/ +--+-- Computes Airy functions using an automatic algorithm choice.+-- +-- We use @acb_hypgeom_airy_asymp@ whenever this gives full accuracy and+-- @acb_hypgeom_airy_direct@ otherwise. In the latter case, we first use+-- hardware double precision arithmetic to determine an accurate estimate+-- of the working precision needed to compute the Airy functions accurately+-- for given /z/. This estimate is obtained by comparing the leading-order+-- asymptotic estimate of the Airy functions with the magnitude of the+-- largest term in the power series. The estimate is generic in the sense+-- that it does not take into account vanishing near the roots of the+-- functions. We subsequently evaluate the power series at the midpoint of+-- /z/ and bound the propagated error using derivatives. Derivatives are+-- bounded using @acb_hypgeom_airy_bound@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_airy"+ acb_hypgeom_airy :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_airy_jet/ /ai/ /bi/ /z/ /len/ /prec/ +--+-- Writes to /ai/ and /bi/ the respective Taylor expansions of the Airy+-- functions at the point /z/, truncated to length /len/. Either of the+-- outputs can be /NULL/ to avoid computing that function. The variable /z/+-- is not allowed to be aliased with the outputs. To simplify the+-- implementation, this method does not compute the series expansions of+-- the primed versions directly; these are easily obtained by computing one+-- extra coefficient and differentiating the output with+-- @_acb_poly_derivative@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_airy_jet"+ acb_hypgeom_airy_jet :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /_acb_hypgeom_airy_series/ /ai/ /ai_prime/ /bi/ /bi_prime/ /z/ /zlen/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_airy_series"+ _acb_hypgeom_airy_series :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_airy_series/ /ai/ /ai_prime/ /bi/ /bi_prime/ /z/ /len/ /prec/ +--+-- Computes the Airy functions evaluated at the power series /z/, truncated+-- to length /len/. As with the other Airy methods, any of the outputs can+-- be /NULL/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_airy_series"+ acb_hypgeom_airy_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- Coulomb wave functions ------------------------------------------------------++-- Coulomb wave functions are solutions of the Coulomb wave equation+--+-- \[`\]+-- \[y'' + \left(1 - \frac{2 \eta}{z} - \frac{\ell(\ell+1)}{z^2}\right) y = 0\]+--+-- which is the radial Schrödinger equation for a charged particle in a+-- Coulomb potential \(1/z\), where \(\ell\) is the orbital angular+-- momentum and eta is the Sommerfeld parameter. The standard solutions are+-- named \(F_{\ell}(\eta,z)\) (regular at the origin \(z = 0\)) and+-- \(G_{\ell}(\eta,z)\) (irregular at the origin). The irregular solutions+-- H^{pm}_{ell}(eta,z) = G_{ell}(eta,z) pm i F_{ell}(eta,z) are also used.+--+-- Coulomb wave functions are special cases of confluent hypergeometric+-- functions. The normalization constants and connection formulas are+-- discussed in < [DYF1999]>, < [Gas2018]>, < [Mic2007]> and chapter 33 in+-- < [NIST2012]>. In this implementation, we define the analytic+-- continuations of all the functions so that the branch cut with respect+-- to /z/ is placed on the negative real axis. Precise definitions are+-- given in <http://fungrim.org/topic/Coulomb_wave_functions/>+--+-- The following methods optionally compute F_{ell}(eta,z), G_{ell}(eta,z),+-- H^{+}_{ell}(eta,z), H^{-}_{ell}(eta,z) simultaneously. Any of the four+-- function values can be omitted by passing /NULL/ for the unwanted output+-- variables. The redundant functions \(H^{\pm}\) are provided explicitly+-- since taking the linear combination of /F/ and /G/ suffers from+-- cancellation in parts of the complex plane.+--+-- | /acb_hypgeom_coulomb/ /F/ /G/ /Hpos/ /Hneg/ /l/ /eta/ /z/ /prec/ +--+-- Writes to /F/, /G/, /Hpos/, /Hneg/ the values of the respective Coulomb+-- wave functions. Any of the outputs can be /NULL/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_coulomb"+ acb_hypgeom_coulomb :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_coulomb_jet/ /F/ /G/ /Hpos/ /Hneg/ /l/ /eta/ /z/ /len/ /prec/ +--+-- Writes to /F/, /G/, /Hpos/, /Hneg/ the respective Taylor expansions of+-- the Coulomb wave functions at the point /z/, truncated to length /len/.+-- Any of the outputs can be /NULL/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_coulomb_jet"+ acb_hypgeom_coulomb_jet :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /_acb_hypgeom_coulomb_series/ /F/ /G/ /Hpos/ /Hneg/ /l/ /eta/ /z/ /zlen/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_coulomb_series"+ _acb_hypgeom_coulomb_series :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_coulomb_series/ /F/ /G/ /Hpos/ /Hneg/ /l/ /eta/ /z/ /len/ /prec/ +--+-- Computes the Coulomb wave functions evaluated at the power series /z/,+-- truncated to length /len/. Any of the outputs can be /NULL/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_coulomb_series"+ acb_hypgeom_coulomb_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcb -> Ptr CAcb -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- Incomplete gamma and beta functions -----------------------------------------++-- | /acb_hypgeom_gamma_upper_asymp/ /res/ /s/ /z/ /regularized/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_upper_asymp"+ acb_hypgeom_gamma_upper_asymp :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_gamma_upper_1f1a/ /res/ /s/ /z/ /regularized/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_upper_1f1a"+ acb_hypgeom_gamma_upper_1f1a :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_gamma_upper_1f1b/ /res/ /s/ /z/ /regularized/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_upper_1f1b"+ acb_hypgeom_gamma_upper_1f1b :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_gamma_upper_singular/ /res/ /s/ /z/ /regularized/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_upper_singular"+ acb_hypgeom_gamma_upper_singular :: Ptr CAcb -> CLong -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_gamma_upper/ /res/ /s/ /z/ /regularized/ /prec/ +--+-- If /regularized/ is 0, computes the upper incomplete gamma function+-- \(\Gamma(s,z)\).+-- +-- If /regularized/ is 1, computes the regularized upper incomplete gamma+-- function \(Q(s,z) = \Gamma(s,z) / \Gamma(s)\).+-- +-- If /regularized/ is 2, computes the generalized exponential integral+-- \(z^{-s} \Gamma(s,z) = E_{1-s}(z)\) instead (this option is mainly+-- intended for internal use; @acb_hypgeom_expint@ is the intended+-- interface for computing the exponential integral).+-- +-- The different methods respectively implement the formulas+-- +-- \[`\]+-- \[\Gamma(s,z) = e^{-z} U(1-s,1-s,z)\]+-- +-- \[`\]+-- \[\Gamma(s,z) = \Gamma(s) - \frac{z^s}{s} {}_1F_1(s, s+1, -z)\]+-- +-- \[`\]+-- \[\Gamma(s,z) = \Gamma(s) - \frac{z^s e^{-z}}{s} {}_1F_1(1, s+1, z)\]+-- +-- \[`\]+-- \[\Gamma(s,z) = \frac{(-1)^n}{n!} (\psi(n+1) - \log(z))+-- + \frac{(-1)^n}{(n+1)!} z \, {}_2F_2(1,1,2,2+n,-z)+-- - z^{-n} \sum_{k=0}^{n-1} \frac{(-z)^k}{(k-n) k!},+-- \quad n = -s \in \mathbb{Z}_{\ge 0}\]+-- +-- and an automatic algorithm choice. The automatic version also handles+-- other special input such as \(z = 0\) and \(s = 1, 2, 3\). The+-- /singular/ version evaluates the finite sum directly and therefore+-- assumes that /s/ is not too large.+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_upper"+ acb_hypgeom_gamma_upper :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /_acb_hypgeom_gamma_upper_series/ /res/ /s/ /z/ /zlen/ /regularized/ /n/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_gamma_upper_series"+ _acb_hypgeom_gamma_upper_series :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CInt -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_gamma_upper_series/ /res/ /s/ /z/ /regularized/ /n/ /prec/ +--+-- Sets /res/ to an upper incomplete gamma function where /s/ is a constant+-- and /z/ is a power series, truncated to length /n/. The /regularized/+-- argument has the same interpretation as in @acb_hypgeom_gamma_upper@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_upper_series"+ acb_hypgeom_gamma_upper_series :: Ptr CAcbPoly -> Ptr CAcb -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_gamma_lower/ /res/ /s/ /z/ /regularized/ /prec/ +--+-- If /regularized/ is 0, computes the lower incomplete gamma function+-- \(\gamma(s,z) = \frac{z^s}{s} {}_1F_1(s, s+1, -z)\).+-- +-- If /regularized/ is 1, computes the regularized lower incomplete gamma+-- function \(P(s,z) = \gamma(s,z) / \Gamma(s)\).+-- +-- If /regularized/ is 2, computes a further regularized lower incomplete+-- gamma function \(\gamma^{*}(s,z) = z^{-s} P(s,z)\).+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_lower"+ acb_hypgeom_gamma_lower :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /_acb_hypgeom_gamma_lower_series/ /res/ /s/ /z/ /zlen/ /regularized/ /n/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_gamma_lower_series"+ _acb_hypgeom_gamma_lower_series :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CInt -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_gamma_lower_series/ /res/ /s/ /z/ /regularized/ /n/ /prec/ +--+-- Sets /res/ to an lower incomplete gamma function where /s/ is a constant+-- and /z/ is a power series, truncated to length /n/. The /regularized/+-- argument has the same interpretation as in @acb_hypgeom_gamma_lower@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_gamma_lower_series"+ acb_hypgeom_gamma_lower_series :: Ptr CAcbPoly -> Ptr CAcb -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_beta_lower/ /res/ /a/ /b/ /z/ /regularized/ /prec/ +--+-- Computes the (lower) incomplete beta function, defined by+-- \(B(a,b;z) = \int_0^z t^{a-1} (1-t)^{b-1}\), optionally the regularized+-- incomplete beta function \(I(a,b;z) = B(a,b;z) / B(a,b;1)\).+-- +-- In general, the integral must be interpreted using analytic+-- continuation. The precise definitions for all parameter values are+-- +-- \[`\]+-- \[B(a,b;z) = \frac{z^a}{a} {}_2F_1(a, 1-b, a+1, z)\]+-- +-- \[`\]+-- \[I(a,b;z) = \frac{\Gamma(a+b)}{\Gamma(b)} z^a {}_2{\widetilde F}_1(a, 1-b, a+1, z).\]+-- +-- Note that both functions with this definition are undefined for+-- nonpositive integer /a/, and /I/ is undefined for nonpositive integer+-- \(a + b\).+foreign import ccall "acb_hypgeom.h acb_hypgeom_beta_lower"+ acb_hypgeom_beta_lower :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /_acb_hypgeom_beta_lower_series/ /res/ /a/ /b/ /z/ /zlen/ /regularized/ /n/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_beta_lower_series"+ _acb_hypgeom_beta_lower_series :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CInt -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_beta_lower_series/ /res/ /a/ /b/ /z/ /regularized/ /n/ /prec/ +--+-- Sets /res/ to the lower incomplete beta function \(B(a,b;z)\)+-- (optionally the regularized version \(I(a,b;z)\)) where /a/ and /b/ are+-- constants and /z/ is a power series, truncating the result to length+-- /n/. The underscore method requires positive lengths and does not+-- support aliasing.+foreign import ccall "acb_hypgeom.h acb_hypgeom_beta_lower_series"+ acb_hypgeom_beta_lower_series :: Ptr CAcbPoly -> Ptr CAcb -> Ptr CAcb -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> IO ()++-- Exponential and trigonometric integrals -------------------------------------++-- The branch cut conventions of the following functions match Mathematica.+--+-- | /acb_hypgeom_expint/ /res/ /s/ /z/ /prec/ +--+-- Computes the generalized exponential integral \(E_s(z)\). This is a+-- trivial wrapper of @acb_hypgeom_gamma_upper@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_expint"+ acb_hypgeom_expint :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_ei_asymp/ /res/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_ei_asymp"+ acb_hypgeom_ei_asymp :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_ei_2f2/ /res/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_ei_2f2"+ acb_hypgeom_ei_2f2 :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_ei/ /res/ /z/ /prec/ +--+-- Computes the exponential integral \(\operatorname{Ei}(z)\), respectively+-- using+-- +-- \[`\]+-- \[\operatorname{Ei}(z) = -e^z U(1,1,-z) - \log(-z)+-- + \frac{1}{2} \left(\log(z) - \log\left(\frac{1}{z}\right) \right)\]+-- +-- \[`\]+-- \[\operatorname{Ei}(z) = z {}_2F_2(1, 1; 2, 2; z) + \gamma+-- + \frac{1}{2} \left(\log(z) - \log\left(\frac{1}{z}\right) \right)\]+-- +-- and an automatic algorithm choice.+foreign import ccall "acb_hypgeom.h acb_hypgeom_ei"+ acb_hypgeom_ei :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /_acb_hypgeom_ei_series/ /res/ /z/ /zlen/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_ei_series"+ _acb_hypgeom_ei_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_ei_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the exponential integral of the power series /z/, truncated to+-- length /len/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_ei_series"+ acb_hypgeom_ei_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_si_asymp/ /res/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_si_asymp"+ acb_hypgeom_si_asymp :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_si_1f2/ /res/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_si_1f2"+ acb_hypgeom_si_1f2 :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_si/ /res/ /z/ /prec/ +--+-- Computes the sine integral \(\operatorname{Si}(z)\), respectively using+-- +-- \[`\]+-- \[\operatorname{Si}(z) = \frac{i}{2} \left[+-- e^{iz} U(1,1,-iz) - e^{-iz} U(1,1,iz) + +-- \log(-iz) - \log(iz) \right]\]+-- +-- \[`\]+-- \[\operatorname{Si}(z) = z {}_1F_2(\tfrac{1}{2}; \tfrac{3}{2}, \tfrac{3}{2}; -\tfrac{z^2}{4})\]+-- +-- and an automatic algorithm choice.+foreign import ccall "acb_hypgeom.h acb_hypgeom_si"+ acb_hypgeom_si :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /_acb_hypgeom_si_series/ /res/ /z/ /zlen/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_si_series"+ _acb_hypgeom_si_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_si_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the sine integral of the power series /z/, truncated to length+-- /len/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_si_series"+ acb_hypgeom_si_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_ci_asymp/ /res/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_ci_asymp"+ acb_hypgeom_ci_asymp :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_ci_2f3/ /res/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_ci_2f3"+ acb_hypgeom_ci_2f3 :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_ci/ /res/ /z/ /prec/ +--+-- Computes the cosine integral \(\operatorname{Ci}(z)\), respectively+-- using+-- +-- \[`\]+-- \[\operatorname{Ci}(z) = \log(z) - \frac{1}{2} \left[+-- e^{iz} U(1,1,-iz) + e^{-iz} U(1,1,iz) + +-- \log(-iz) + \log(iz) \right]\]+-- +-- \[`\]+-- \[\operatorname{Ci}(z) = -\tfrac{z^2}{4}+-- {}_2F_3(1, 1; 2, 2, \tfrac{3}{2}; -\tfrac{z^2}{4})+-- + \log(z) + \gamma\]+-- +-- and an automatic algorithm choice.+foreign import ccall "acb_hypgeom.h acb_hypgeom_ci"+ acb_hypgeom_ci :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /_acb_hypgeom_ci_series/ /res/ /z/ /zlen/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_ci_series"+ _acb_hypgeom_ci_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_ci_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the cosine integral of the power series /z/, truncated to+-- length /len/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_ci_series"+ acb_hypgeom_ci_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_shi/ /res/ /z/ /prec/ +--+-- Computes the hyperbolic sine integral+-- \(\operatorname{Shi}(z) = -i \operatorname{Si}(iz)\). This is a trivial+-- wrapper of @acb_hypgeom_si@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_shi"+ acb_hypgeom_shi :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /_acb_hypgeom_shi_series/ /res/ /z/ /zlen/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_shi_series"+ _acb_hypgeom_shi_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_shi_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the hyperbolic sine integral of the power series /z/, truncated+-- to length /len/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_shi_series"+ acb_hypgeom_shi_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_chi_asymp/ /res/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_chi_asymp"+ acb_hypgeom_chi_asymp :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_chi_2f3/ /res/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_chi_2f3"+ acb_hypgeom_chi_2f3 :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_chi/ /res/ /z/ /prec/ +--+-- Computes the hyperbolic cosine integral \(\operatorname{Chi}(z)\),+-- respectively using+-- +-- \[`\]+-- \[\operatorname{Chi}(z) = -\frac{1}{2} \left[+-- e^{z} U(1,1,-z) + e^{-z} U(1,1,z) + +-- \log(-z) - \log(z) \right]\]+-- +-- \[`\]+-- \[\operatorname{Chi}(z) = \tfrac{z^2}{4}+-- {}_2F_3(1, 1; 2, 2, \tfrac{3}{2}; \tfrac{z^2}{4})+-- + \log(z) + \gamma\]+-- +-- and an automatic algorithm choice.+foreign import ccall "acb_hypgeom.h acb_hypgeom_chi"+ acb_hypgeom_chi :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /_acb_hypgeom_chi_series/ /res/ /z/ /zlen/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_chi_series"+ _acb_hypgeom_chi_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_chi_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the hyperbolic cosine integral of the power series /z/,+-- truncated to length /len/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_chi_series"+ acb_hypgeom_chi_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_li/ /res/ /z/ /offset/ /prec/ +--+-- If /offset/ is zero, computes the logarithmic integral+-- \(\operatorname{li}(z) = \operatorname{Ei}(\log(z))\).+-- +-- If /offset/ is nonzero, computes the offset logarithmic integral+-- \(\operatorname{Li}(z) = \operatorname{li}(z) - \operatorname{li}(2)\).+foreign import ccall "acb_hypgeom.h acb_hypgeom_li"+ acb_hypgeom_li :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /_acb_hypgeom_li_series/ /res/ /z/ /zlen/ /offset/ /len/ /prec/ +--+foreign import ccall "acb_hypgeom.h _acb_hypgeom_li_series"+ _acb_hypgeom_li_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CInt -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_li_series/ /res/ /z/ /offset/ /len/ /prec/ +--+-- Computes the logarithmic integral (optionally the offset version) of the+-- power series /z/, truncated to length /len/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_li_series"+ acb_hypgeom_li_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> IO ()++-- Gauss hypergeometric function -----------------------------------------------++-- The following methods compute the Gauss hypergeometric function+--+-- \[`\]+-- \[F(z) = {}_2F_1(a,b,c,z) = \sum_{k=0}^{\infty} \frac{(a)_k (b)_k}{(c)_k} \frac{z^k}{k!}\]+--+-- or the regularized version operatorname{mathbf{F}}(z) =+-- operatorname{mathbf{F}}(a,b,c,z) = {}_2F_1(a,b,c,z) \/ Gamma(c) if the+-- flag /regularized/ is set.+--+-- | /acb_hypgeom_2f1_continuation/ /res0/ /res1/ /a/ /b/ /c/ /z0/ /z1/ /f0/ /f1/ /prec/ +--+-- Given \(F(z_0), F'(z_0)\) in /f0/, /f1/, sets /res0/ and /res1/ to+-- \(F(z_1), F'(z_1)\) by integrating the hypergeometric differential+-- equation along a straight-line path. The evaluation points should be+-- well-isolated from the singular points 0 and 1.+foreign import ccall "acb_hypgeom.h acb_hypgeom_2f1_continuation"+ acb_hypgeom_2f1_continuation :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_2f1_series_direct/ /res/ /a/ /b/ /c/ /z/ /regularized/ /len/ /prec/ +--+-- Computes \(F(z)\) of the given power series truncated to length /len/,+-- using direct summation of the hypergeometric series.+foreign import ccall "acb_hypgeom.h acb_hypgeom_2f1_series_direct"+ acb_hypgeom_2f1_series_direct :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CInt -> CLong -> CLong -> IO ()++-- | /acb_hypgeom_2f1_direct/ /res/ /a/ /b/ /c/ /z/ /regularized/ /prec/ +--+-- Computes \(F(z)\) using direct summation of the hypergeometric series.+foreign import ccall "acb_hypgeom.h acb_hypgeom_2f1_direct"+ acb_hypgeom_2f1_direct :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_2f1_transform/ /res/ /a/ /b/ /c/ /z/ /flags/ /which/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_2f1_transform"+ acb_hypgeom_2f1_transform :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_2f1_transform_limit/ /res/ /a/ /b/ /c/ /z/ /regularized/ /which/ /prec/ +--+-- Computes \(F(z)\) using an argument transformation determined by the+-- flag /which/. Legal values are 1 for \(z/(z-1)\), 2 for \(1/z\), 3 for+-- \(1/(1-z)\), 4 for \(1-z\), and 5 for \(1-1/z\).+-- +-- The /transform_limit/ version assumes that /which/ is not 1. If /which/+-- is 2 or 3, it assumes that \(b-a\) represents an exact integer. If+-- /which/ is 4 or 5, it assumes that \(c-a-b\) represents an exact+-- integer. In these cases, it computes the correct limit value.+-- +-- See @acb_hypgeom_2f1@ for the meaning of /flags/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_2f1_transform_limit"+ acb_hypgeom_2f1_transform_limit :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_2f1_corner/ /res/ /a/ /b/ /c/ /z/ /regularized/ /prec/ +--+-- Computes \(F(z)\) near the corner cases \(\exp(\pm \pi i \sqrt{3})\) by+-- analytic continuation.+foreign import ccall "acb_hypgeom.h acb_hypgeom_2f1_corner"+ acb_hypgeom_2f1_corner :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_2f1_choose/ /z/ +--+-- Chooses a method to compute the function based on the location of /z/ in+-- the complex plane. If the return value is 0, direct summation should be+-- used. If the return value is 1 to 5, the transformation with this index+-- in @acb_hypgeom_2f1_transform@ should be used. If the return value is 6,+-- the corner case algorithm should be used.+foreign import ccall "acb_hypgeom.h acb_hypgeom_2f1_choose"+ acb_hypgeom_2f1_choose :: Ptr CAcb -> IO CInt++-- | /acb_hypgeom_2f1/ /res/ /a/ /b/ /c/ /z/ /flags/ /prec/ +--+-- Computes \(F(z)\) or \(\operatorname{\mathbf{F}}(z)\) using an automatic+-- algorithm choice.+-- +-- The following bit fields can be set in /flags/:+-- +-- - /ACB_HYPGEOM_2F1_REGULARIZED/ - computes the regularized+-- hypergeometric function \(\operatorname{\mathbf{F}}(z)\). Setting+-- /flags/ to 1 is the same as just toggling this option.+-- - /ACB_HYPGEOM_2F1_AB/ - \(a-b\) is an integer.+-- - /ACB_HYPGEOM_2F1_ABC/ - \(a+b-c\) is an integer.+-- - /ACB_HYPGEOM_2F1_AC/ - \(a-c\) is an integer.+-- - /ACB_HYPGEOM_2F1_BC/ - \(b-c\) is an integer.+-- +-- The last four flags can be set to indicate that the respective parameter+-- differences are known to represent exact integers, even if the input+-- intervals are inexact. This allows the correct limits to be evaluated+-- when applying transformation formulas. For example, to evaluate+-- \({}_2F_1(\sqrt{2}, 1/2, \sqrt{2}+3/2, 9/10)\), the /ABC/ flag should be+-- set. If not set, the result will be an indeterminate interval due to+-- internally dividing by an interval containing zero. If the parameters+-- are exact floating-point numbers (including exact integers or+-- half-integers), then the limits are computed automatically, and setting+-- these flags is unnecessary.+-- +-- Currently, only the /AB/ and /ABC/ flags are used this way; the /AC/ and+-- /BC/ flags might be used in the future.+foreign import ccall "acb_hypgeom.h acb_hypgeom_2f1"+ acb_hypgeom_2f1 :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- Orthogonal polynomials and functions ----------------------------------------++-- | /acb_hypgeom_chebyshev_t/ /res/ /n/ /z/ /prec/ +--+foreign import ccall "acb_hypgeom.h acb_hypgeom_chebyshev_t"+ acb_hypgeom_chebyshev_t :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_chebyshev_u/ /res/ /n/ /z/ /prec/ +--+-- Computes the Chebyshev polynomial (or Chebyshev function) of first or+-- second kind+-- +-- \[`\]+-- \[T_n(z) = {}_2F_1\left(-n,n,\frac{1}{2},\frac{1-z}{2}\right)\]+-- +-- \[`\]+-- \[U_n(z) = (n+1) {}_2F_1\left(-n,n+2,\frac{3}{2},\frac{1-z}{2}\right).\]+-- +-- The hypergeometric series definitions are only used for computation near+-- the point 1. In general, trigonometric representations are used. For+-- word-size integer /n/, @acb_chebyshev_t_ui@ and @acb_chebyshev_u_ui@ are+-- called.+foreign import ccall "acb_hypgeom.h acb_hypgeom_chebyshev_u"+ acb_hypgeom_chebyshev_u :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_jacobi_p/ /res/ /n/ /a/ /b/ /z/ /prec/ +--+-- Computes the Jacobi polynomial (or Jacobi function)+-- +-- \[`\]+-- \[P_n^{(a,b)}(z)=\frac{(a+1)_n}{\Gamma(n+1)} {}_2F_1\left(-n,n+a+b+1,a+1,\frac{1-z}{2}\right).\]+-- +-- For nonnegative integer /n/, this is a polynomial in /a/, /b/ and /z/,+-- even when the parameters are such that the hypergeometric series is+-- undefined. In such cases, the polynomial is evaluated using direct+-- methods.+foreign import ccall "acb_hypgeom.h acb_hypgeom_jacobi_p"+ acb_hypgeom_jacobi_p :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_gegenbauer_c/ /res/ /n/ /m/ /z/ /prec/ +--+-- Computes the Gegenbauer polynomial (or Gegenbauer function)+-- +-- \[`\]+-- \[C_n^{m}(z)=\frac{(2m)_n}{\Gamma(n+1)} {}_2F_1\left(-n,2m+n,m+\frac{1}{2},\frac{1-z}{2}\right).\]+-- +-- For nonnegative integer /n/, this is a polynomial in /m/ and /z/, even+-- when the parameters are such that the hypergeometric series is+-- undefined. In such cases, the polynomial is evaluated using direct+-- methods.+foreign import ccall "acb_hypgeom.h acb_hypgeom_gegenbauer_c"+ acb_hypgeom_gegenbauer_c :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_laguerre_l/ /res/ /n/ /m/ /z/ /prec/ +--+-- Computes the Laguerre polynomial (or Laguerre function)+-- +-- \[`\]+-- \[L_n^{m}(z)=\frac{(m+1)_n}{\Gamma(n+1)} {}_1F_1\left(-n,m+1,z\right).\]+-- +-- For nonnegative integer /n/, this is a polynomial in /m/ and /z/, even+-- when the parameters are such that the hypergeometric series is+-- undefined. In such cases, the polynomial is evaluated using direct+-- methods.+-- +-- There are at least two incompatible ways to define the Laguerre function+-- when /n/ is a negative integer. One possibility when \(m = 0\) is to+-- define \(L_{-n}^0(z) = e^z L_{n-1}^0(-z)\). Another possibility is to+-- cover this case with the recurrence relation+-- \(L_{n-1}^m(z) + L_n^{m-1}(z) = L_n^m(z)\). Currently, we leave this+-- case undefined (returning indeterminate).+foreign import ccall "acb_hypgeom.h acb_hypgeom_laguerre_l"+ acb_hypgeom_laguerre_l :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_hermite_h/ /res/ /n/ /z/ /prec/ +--+-- Computes the Hermite polynomial (or Hermite function)+-- +-- \[`\]+-- \[H_n(z) = 2^n \sqrt{\pi} \left(+-- \frac{1}{\Gamma((1-n)/2)} {}_1F_1\left(-\frac{n}{2},\frac{1}{2},z^2\right)+-- - +-- \frac{2z}{\Gamma(-n/2)} {}_1F_1\left(\frac{1-n}{2},\frac{3}{2},z^2\right)\right).\]+foreign import ccall "acb_hypgeom.h acb_hypgeom_hermite_h"+ acb_hypgeom_hermite_h :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_legendre_p/ /res/ /n/ /m/ /z/ /type/ /prec/ +--+-- Sets /res/ to the associated Legendre function of the first kind+-- evaluated for degree /n/, order /m/, and argument /z/. When /m/ is zero,+-- this reduces to the Legendre polynomial \(P_n(z)\).+-- +-- Many different branch cut conventions appear in the literature. If+-- /type/ is 0, the version+-- +-- \[`\]+-- \[P_n^m(z) = \frac{(1+z)^{m/2}}{(1-z)^{m/2}}+-- \mathbf{F}\left(-n, n+1, 1-m, \frac{1-z}{2}\right)\]+-- +-- is computed, and if /type/ is 1, the alternative version+-- +-- \[`\]+-- \[{\mathcal P}_n^m(z) = \frac{(z+1)^{m/2}}{(z-1)^{m/2}}+-- \mathbf{F}\left(-n, n+1, 1-m, \frac{1-z}{2}\right).\]+-- +-- is computed. Type 0 and type 1 respectively correspond to type 2 and+-- type 3 in /Mathematica/ and /mpmath/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_legendre_p"+ acb_hypgeom_legendre_p :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_legendre_q/ /res/ /n/ /m/ /z/ /type/ /prec/ +--+-- Sets /res/ to the associated Legendre function of the second kind+-- evaluated for degree /n/, order /m/, and argument /z/. When /m/ is zero,+-- this reduces to the Legendre function \(Q_n(z)\).+-- +-- Many different branch cut conventions appear in the literature. If+-- /type/ is 0, the version+-- +-- \[`\]+-- \[Q_n^m(z) = \frac{\pi}{2 \sin(\pi m)}+-- \left( \cos(\pi m) P_n^m(z) -+-- \frac{\Gamma(1+m+n)}{\Gamma(1-m+n)} P_n^{-m}(z)\right)\]+-- +-- is computed, and if /type/ is 1, the alternative version+-- +-- \[`\]+-- \[\mathcal{Q}_n^m(z) = \frac{\pi}{2 \sin(\pi m)} e^{\pi i m}+-- \left( \mathcal{P}_n^m(z) -+-- \frac{\Gamma(1+m+n)}{\Gamma(1-m+n)} \mathcal{P}_n^{-m}(z)\right)\]+-- +-- is computed. Type 0 and type 1 respectively correspond to type 2 and+-- type 3 in /Mathematica/ and /mpmath/.+-- +-- When /m/ is an integer, either expression is interpreted as a limit. We+-- make use of the connection formulas < [WQ3a]>, < [WQ3b]> and < [WQ3c]>+-- to allow computing the function even in the limiting case. (The formula+-- < [WQ3d]> would be useful, but is incorrect in the lower half plane.)+foreign import ccall "acb_hypgeom.h acb_hypgeom_legendre_q"+ acb_hypgeom_legendre_q :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_legendre_p_uiui_rec/ /res/ /n/ /m/ /z/ /prec/ +--+-- For nonnegative integer /n/ and /m/, uses recurrence relations to+-- evaluate \((1-z^2)^{-m/2} P_n^m(z)\) which is a polynomial in /z/.+foreign import ccall "acb_hypgeom.h acb_hypgeom_legendre_p_uiui_rec"+ acb_hypgeom_legendre_p_uiui_rec :: Ptr CAcb -> CULong -> CULong -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_spherical_y/ /res/ /n/ /m/ /theta/ /phi/ /prec/ +--+-- Computes the spherical harmonic of degree /n/, order /m/, latitude angle+-- /theta/, and longitude angle /phi/, normalized such that+-- +-- \[`\]+-- \[Y_n^m(\theta, \phi) = \sqrt{\frac{2n+1}{4\pi} \frac{(n-m)!}{(n+m)!}} e^{im\phi} P_n^m(\cos(\theta)).\]+-- +-- The definition is extended to negative /m/ and /n/ by symmetry. This+-- function is a polynomial in \(\cos(\theta)\) and \(\sin(\theta)\). We+-- evaluate it using @acb_hypgeom_legendre_p_uiui_rec@.+foreign import ccall "acb_hypgeom.h acb_hypgeom_spherical_y"+ acb_hypgeom_spherical_y :: Ptr CAcb -> CLong -> CLong -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Dilogarithm -----------------------------------------------------------------++-- The dilogarithm function is given by+-- \(\operatorname{Li}_2(z) = -\int_0^z \frac{\log(1-t)}{t} dt = z {}_3F_2(1,1,1,2,2,z)\).+--++++-- | /acb_hypgeom_dilog_zero_taylor/ /res/ /z/ /prec/ +--+-- Computes the dilogarithm for /z/ close to 0 using the hypergeometric+-- series (effective only when \(|z| \ll 1\)).+foreign import ccall "acb_hypgeom.h acb_hypgeom_dilog_zero_taylor"+ acb_hypgeom_dilog_zero_taylor :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_dilog_zero/ /res/ /z/ /prec/ +--+-- Computes the dilogarithm for /z/ close to 0, using the bit-burst+-- algorithm instead of the hypergeometric series directly at very high+-- precision.+foreign import ccall "acb_hypgeom.h acb_hypgeom_dilog_zero"+ acb_hypgeom_dilog_zero :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_dilog_transform/ /res/ /z/ /algorithm/ /prec/ +--+-- Computes the dilogarithm by applying one of the transformations \(1/z\),+-- \(1-z\), \(z/(z-1)\), \(1/(1-z)\), indexed by /algorithm/ from 1 to 4,+-- and calling @acb_hypgeom_dilog_zero@ with the reduced variable.+-- Alternatively, for /algorithm/ between 5 and 7, starts from the+-- respective point \(\pm i\), \((1\pm i)/2\), \((1\pm i)/2\) (with the+-- sign chosen according to the midpoint of /z/) and computes the+-- dilogarithm by the bit-burst method.+foreign import ccall "acb_hypgeom.h acb_hypgeom_dilog_transform"+ acb_hypgeom_dilog_transform :: Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> IO ()++-- | /acb_hypgeom_dilog_continuation/ /res/ /a/ /z/ /prec/ +--+-- Computes \(\operatorname{Li}_2(z) - \operatorname{Li}_2(a)\) using+-- Taylor expansion at /a/. Binary splitting is used. Both /a/ and /z/+-- should be well isolated from the points 0 and 1, except that /a/ may be+-- exactly 0. If the straight line path from /a/ to /b/ crosses the branch+-- cut, this method provides continuous analytic continuation instead of+-- computing the principal branch.+foreign import ccall "acb_hypgeom.h acb_hypgeom_dilog_continuation"+ acb_hypgeom_dilog_continuation :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_dilog_bitburst/ /res/ /z0/ /z/ /prec/ +--+-- Sets /z0/ to a point with short bit expansion close to /z/ and sets+-- /res/ to \(\operatorname{Li}_2(z) - \operatorname{Li}_2(z_0)\), computed+-- using the bit-burst algorithm.+foreign import ccall "acb_hypgeom.h acb_hypgeom_dilog_bitburst"+ acb_hypgeom_dilog_bitburst :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_hypgeom_dilog/ /res/ /z/ /prec/ +--+-- Computes the dilogarithm using a default algorithm choice.+foreign import ccall "acb_hypgeom.h acb_hypgeom_dilog"+ acb_hypgeom_dilog :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()+
+ src/Data/Number/Flint/Acb/Instances.hs view
@@ -0,0 +1,17 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Acb.Instances where++import System.IO.Unsafe+import Foreign.C.String+import Foreign.Marshal.Alloc ( free )++import Data.Number.Flint.Arb+import Data.Number.Flint.Acb++instance Show Acb where+ show x = unsafePerformIO $ do+ (_, cs) <- withAcb x $ \x -> acb_get_strn x 16 arb_str_no_radius+ s <- peekCString cs+ free cs+ return s+
+ src/Data/Number/Flint/Acb/Mat.hs view
@@ -0,0 +1,14 @@+{- |+An @AcbMat@ represents a dense matrix over the complex numbers,+implemented as an array of entries of type @Acb@. The dimension+(number of rows and columns) of a matrix is fixed at initialization, and+the user must ensure that inputs and outputs to an operation have+compatible dimensions. The number of rows or columns in a matrix can be+zero.+-}++module Data.Number.Flint.Acb.Mat (+ module Data.Number.Flint.Acb.Mat.FFI+ ) where++import Data.Number.Flint.Acb.Mat.FFI
+ src/Data/Number/Flint/Acb/Mat/FFI.hsc view
@@ -0,0 +1,1162 @@+{-|+module : Data.Number.Flint.Acb.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Acb.Mat.FFI (+ -- * Matrices over the complex numbers+ AcbMat (..)+ , CAcbMat (..)+ -- * Constructors+ , newAcbMat+ , newAcbMatFromFmpzMat+ , newAcbMatFromFmpzMatRound+ , newAcbMatFromFmpqMat+ , newAcbMatFromArbMat+ , newAcbMatFromArbMatRound+ , withAcbMat+ , withNewAcbMat+ -- * Memory management+ , acb_mat_init+ , acb_mat_clear+ , acb_mat_allocated_bytes+ , acb_mat_window_init+ --, acb_mat_window_clear+ -- * Conversions+ , acb_mat_entry+ , acb_mat_set+ , acb_mat_set_fmpz_mat+ , acb_mat_set_round_fmpz_mat+ , acb_mat_set_fmpq_mat+ , acb_mat_set_arb_mat+ , acb_mat_set_round_arb_mat+ -- * Random generation+ , acb_mat_randtest+ , acb_mat_randtest_eig+ -- * Input and output+ , acb_mat_get_strd+ , acb_mat_printd+ , acb_mat_fprintd+ , acb_mat_get_strn+ , acb_mat_printn+ , acb_mat_fprintn+ -- * Comparisons+ , acb_mat_equal+ , acb_mat_overlaps+ , acb_mat_contains+ , acb_mat_contains_fmpz_mat+ , acb_mat_contains_fmpq_mat+ , acb_mat_eq+ , acb_mat_ne+ , acb_mat_is_real+ , acb_mat_is_empty+ , acb_mat_is_square+ , acb_mat_is_exact+ , acb_mat_is_zero+ , acb_mat_is_finite+ , acb_mat_is_triu+ , acb_mat_is_tril+ , acb_mat_is_diag+ -- * Special matrices+ , acb_mat_zero+ , acb_mat_one+ , acb_mat_ones+ , acb_mat_indeterminate+ , acb_mat_dft+ -- * Transpose+ , acb_mat_transpose+ , acb_mat_conjugate_transpose+ , acb_mat_conjugate+ -- * Norms+ , acb_mat_bound_inf_norm+ , acb_mat_frobenius_norm+ , acb_mat_bound_frobenius_norm+ -- * Arithmetic+ , acb_mat_neg+ , acb_mat_add+ , acb_mat_sub+ , acb_mat_mul_classical+ , acb_mat_mul_threaded+ , acb_mat_mul_reorder+ , acb_mat_mul+ , acb_mat_mul_entrywise+ , acb_mat_sqr_classical+ , acb_mat_sqr+ , acb_mat_pow_ui+ , acb_mat_approx_mul+ -- * Scalar arithmetic+ , acb_mat_scalar_mul_2exp_si+ , acb_mat_scalar_addmul_si+ , acb_mat_scalar_addmul_fmpz+ , acb_mat_scalar_addmul_arb+ , acb_mat_scalar_addmul_acb+ , acb_mat_scalar_mul_si+ , acb_mat_scalar_mul_fmpz+ , acb_mat_scalar_mul_arb+ , acb_mat_scalar_mul_acb+ , acb_mat_scalar_div_si+ , acb_mat_scalar_div_fmpz+ , acb_mat_scalar_div_arb+ , acb_mat_scalar_div_acb+ -- * Gaussian elimination and solving+ , acb_mat_lu_classical+ , acb_mat_lu_recursive+ , acb_mat_lu+ , acb_mat_solve_tril_classical+ , acb_mat_solve_tril_recursive+ , acb_mat_solve_tril+ , acb_mat_solve_triu_classical+ , acb_mat_solve_triu_recursive+ , acb_mat_solve_triu+ , acb_mat_solve_lu_precomp+ , acb_mat_solve+ , acb_mat_solve_lu+ , acb_mat_solve_precond+ , acb_mat_inv+ , acb_mat_det_lu+ , acb_mat_det_precond+ , acb_mat_det+ , acb_mat_approx_solve_triu+ , acb_mat_approx_solve_tril+ , acb_mat_approx_lu+ , acb_mat_approx_solve_lu_precomp+ , acb_mat_approx_solve+ , acb_mat_approx_inv+ -- * Characteristic polynomial and companion matrix+ , _acb_mat_charpoly+ , acb_mat_charpoly+ , _acb_mat_companion+ , acb_mat_companion+ -- * Special functions+ , acb_mat_exp_taylor_sum+ , acb_mat_exp+ , acb_mat_trace+ , _acb_mat_diag_prod+ , acb_mat_diag_prod+ -- * Component and error operations+ , acb_mat_get_mid+ , acb_mat_add_error_mag+ -- * Eigenvalues and eigenvectors+ , acb_mat_approx_eig_qr+ , acb_mat_eig_global_enclosure+ , acb_mat_eig_enclosure_rump+ , acb_mat_eig_simple_rump+ , acb_mat_eig_simple_vdhoeven_mourrain+ , acb_mat_eig_simple+ , acb_mat_eig_multiple_rump+ , acb_mat_eig_multiple+) where++-- Matrices over the complex numbers -------------------------------------------++import System.IO.Unsafe++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr+import Foreign.Storable+import Foreign.Marshal+import Foreign.Marshal.Array++import Data.Number.Flint.Flint++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mat++import Data.Number.Flint.Fmpq.Mat++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Arb.Mat++import Data.Number.Flint.Acb.Types+import Data.Number.Flint.Acb.Poly++#include <flint/acb_mat.h>++-- Types -----------------------------------------------------------------------++data AcbMat = AcbMat {-# UNPACK #-} !(ForeignPtr CAcbMat) +data CAcbMat = CAcbMat (Ptr CAcb) CLong CLong (Ptr (Ptr CAcb)) ++instance Storable CAcbMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size acb_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment acb_mat_t}+ peek ptr = CAcbMat+ <$> #{peek acb_mat_struct, entries} ptr+ <*> #{peek acb_mat_struct, r } ptr+ <*> #{peek acb_mat_struct, c } ptr+ <*> #{peek acb_mat_struct, rows } ptr+ poke = error "CAcbMat.poke: Not defined."+ +newAcbMat rows cols = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> acb_mat_init x rows cols+ addForeignPtrFinalizer p_acb_mat_clear x+ return $ AcbMat x++newAcbMatFromFmpzMat a = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpzMat a $ \a -> do+ CFmpzMat _ rows cols _ <- peek a+ acb_mat_init x rows cols+ acb_mat_set_fmpz_mat x a+ addForeignPtrFinalizer p_acb_mat_clear x+ return $ AcbMat x++newAcbMatFromFmpzMatRound a prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpzMat a $ \a -> do+ CFmpzMat _ rows cols _ <- peek a+ acb_mat_init x rows cols+ acb_mat_set_round_fmpz_mat x a prec+ addForeignPtrFinalizer p_acb_mat_clear x+ +newAcbMatFromFmpqMat a prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpqMat a $ \a -> do+ CFmpqMat _ rows cols _ <- peek a+ acb_mat_init x rows cols+ acb_mat_set_fmpq_mat x a prec+ addForeignPtrFinalizer p_acb_mat_clear x+ return $ AcbMat x++newAcbMatFromArbMat a = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withArbMat a $ \a -> do+ CArbMat _ rows cols _ <- peek a+ acb_mat_init x rows cols+ acb_mat_set_arb_mat x a+ addForeignPtrFinalizer p_acb_mat_clear x+ return $ AcbMat x++newAcbMatFromArbMatRound a prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withArbMat a $ \a -> do+ CArbMat _ rows cols _ <- peek a+ acb_mat_init x rows cols+ acb_mat_set_round_arb_mat x a prec+ addForeignPtrFinalizer p_acb_mat_clear x++{-# INLINE withAcbMat #-}+withAcbMat (AcbMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (AcbMat x,)++{-# INLINE withNewAcbMat #-}+withNewAcbMat rows cols f = do+ x <- newAcbMat rows cols+ withAcbMat x f++-- Memory management -----------------------------------------------------------++-- | /acb_mat_init/ /mat/ /r/ /c/ +-- +-- Initializes the matrix, setting it to the zero matrix with /r/ rows and+-- /c/ columns.+foreign import ccall "acb_mat.h acb_mat_init"+ acb_mat_init :: Ptr CAcbMat -> CLong -> CLong -> IO ()++-- | /acb_mat_clear/ /mat/ +-- +-- Clears the matrix, deallocating all entries.+foreign import ccall "acb_mat.h acb_mat_clear"+ acb_mat_clear :: Ptr CAcbMat -> IO ()++foreign import ccall "acb_mat.h &acb_mat_clear"+ p_acb_mat_clear :: FunPtr (Ptr CAcbMat -> IO ())++-- | /acb_mat_allocated_bytes/ /x/ +-- +-- Returns the total number of bytes heap-allocated internally by this+-- object. The count excludes the size of the structure itself. Add+-- @sizeof(acb_mat_struct)@ to get the size of the object as a whole.+foreign import ccall "acb_mat.h acb_mat_allocated_bytes"+ acb_mat_allocated_bytes :: Ptr CAcbMat -> IO CLong++-- | /acb_mat_window_init/ /window/ /mat/ /r1/ /c1/ /r2/ /c2/ +-- +-- Initializes /window/ to a window matrix into the submatrix of /mat/+-- starting at the corner at row /r1/ and column /c1/ (inclusive) and+-- ending at row /r2/ and column /c2/ (exclusive).+foreign import ccall "acb_mat.h acb_mat_window_init"+ acb_mat_window_init :: Ptr CAcbMat -> Ptr CAcbMat -> CLong -> CLong -> CLong -> CLong -> IO ()++-- -- | /acb_mat_window_clear/ /window/ +-- -- +-- -- Frees the window matrix.+-- foreign import ccall "acb_mat.h acb_mat_window_clear"+-- acb_mat_window_clear :: Ptr CAcbMat -> IO ()++-- Conversions -----------------------------------------------------------------++foreign import ccall "acb_mat.h acb_mat_entry_"+ acb_mat_entry :: Ptr CAcbMat -> CLong -> CLong -> IO (Ptr CAcb)+ +foreign import ccall "acb_mat.h acb_mat_set"+ acb_mat_set :: Ptr CAcbMat -> Ptr CAcbMat -> IO ()++foreign import ccall "acb_mat.h acb_mat_set_fmpz_mat"+ acb_mat_set_fmpz_mat :: Ptr CAcbMat -> Ptr CFmpzMat -> IO ()++foreign import ccall "acb_mat.h acb_mat_set_round_fmpz_mat"+ acb_mat_set_round_fmpz_mat :: Ptr CAcbMat -> Ptr CFmpzMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_set_fmpq_mat"+ acb_mat_set_fmpq_mat :: Ptr CAcbMat -> Ptr CFmpqMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_set_arb_mat"+ acb_mat_set_arb_mat :: Ptr CAcbMat -> Ptr CArbMat -> IO ()++-- | /acb_mat_set_round_arb_mat/ /dest/ /src/ /prec/ +-- +-- Sets /dest/ to /src/. The operands must have identical dimensions.+foreign import ccall "acb_mat.h acb_mat_set_round_arb_mat"+ acb_mat_set_round_arb_mat :: Ptr CAcbMat -> Ptr CArbMat -> CLong -> IO ()++-- Random generation -----------------------------------------------------------++-- | /acb_mat_randtest/ /mat/ /state/ /prec/ /mag_bits/ +-- +-- Sets /mat/ to a random matrix with up to /prec/ bits of precision and+-- with exponents of width up to /mag_bits/.+foreign import ccall "acb_mat.h acb_mat_randtest"+ acb_mat_randtest :: Ptr CAcbMat -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /acb_mat_randtest_eig/ /mat/ /state/ /E/ /prec/ +-- +-- Sets /mat/ to a random matrix with the prescribed eigenvalues supplied+-- as the vector /E/. The output matrix is required to be square. We+-- generate a random unitary matrix via a matrix exponential, and then+-- evaluate an inverse Schur decomposition.+foreign import ccall "acb_mat.h acb_mat_randtest_eig"+ acb_mat_randtest_eig :: Ptr CAcbMat -> Ptr CFRandState -> Ptr CAcb -> CLong -> IO ()++-- Input and output ------------------------------------------------------------++foreign import ccall "acb_mat acb_mat_get_strd"+ acb_mat_get_strd :: Ptr CAcbMat -> CLong -> IO CString++foreign import ccall "acb_mat acb_mat_get_strn"+ acb_mat_get_strn :: Ptr CAcbMat -> CLong -> ArbStrOption -> IO CString++-- | /acb_mat_printd/ /mat/ /digits/ +-- +-- Prints each entry in the matrix with the specified number of decimal+-- digits.+acb_mat_printd :: Ptr CAcbMat -> CLong -> IO ()+acb_mat_printd mat digits = do+ printCStr (\mat -> acb_mat_get_strd mat digits) mat+ return ()++-- | /acb_mat_fprintd/ /file/ /mat/ /digits/ +-- +-- Prints each entry in the matrix with the specified number of decimal+-- digits to the stream /file/.+foreign import ccall "acb_mat.h acb_mat_fprintd"+ acb_mat_fprintd :: Ptr CFile -> Ptr CAcbMat -> CLong -> IO ()++-- | /acb_mat_printn/ /mat/ /digits/ /options/+-- +-- Prints each entry in the matrix with the specified number of decimal+-- digits.+acb_mat_printn :: Ptr CAcbMat -> CLong -> ArbStrOption -> IO ()+acb_mat_printn mat digits options = do+ printCStr (\mat -> acb_mat_get_strn mat digits options) mat+ return ()++-- | /acb_mat_fprintd/ /file/ /mat/ /digits/ +-- +-- Prints each entry in the matrix with the specified number of decimal+-- digits to the stream /file/.+foreign import ccall "acb_mat.h acb_mat_fprintn"+ acb_mat_fprintn :: Ptr CFile -> Ptr CAcbMat -> CLong -> ArbStrOption -> IO ()++-- Comparisons -----------------------------------------------------------------++-- Predicate methods return 1 if the property certainly holds and 0+-- otherwise.+--+-- | /acb_mat_equal/ /mat1/ /mat2/ +-- +-- Returns whether the matrices have the same dimensions and identical+-- intervals as entries.+foreign import ccall "acb_mat.h acb_mat_equal"+ acb_mat_equal :: Ptr CAcbMat -> Ptr CAcbMat -> IO CInt++-- | /acb_mat_overlaps/ /mat1/ /mat2/ +-- +-- Returns whether the matrices have the same dimensions and each entry in+-- /mat1/ overlaps with the corresponding entry in /mat2/.+foreign import ccall "acb_mat.h acb_mat_overlaps"+ acb_mat_overlaps :: Ptr CAcbMat -> Ptr CAcbMat -> IO CInt++foreign import ccall "acb_mat.h acb_mat_contains"+ acb_mat_contains :: Ptr CAcbMat -> Ptr CAcbMat -> IO CInt++foreign import ccall "acb_mat.h acb_mat_contains_fmpz_mat"+ acb_mat_contains_fmpz_mat :: Ptr CAcbMat -> Ptr CFmpzMat -> IO CInt++-- | /acb_mat_contains_fmpq_mat/ /mat1/ /mat2/ +-- +-- Returns whether the matrices have the same dimensions and each entry in+-- /mat2/ is contained in the corresponding entry in /mat1/.+foreign import ccall "acb_mat.h acb_mat_contains_fmpq_mat"+ acb_mat_contains_fmpq_mat :: Ptr CAcbMat -> Ptr CFmpqMat -> IO CInt++-- | /acb_mat_eq/ /mat1/ /mat2/ +-- +-- Returns whether /mat1/ and /mat2/ certainly represent the same matrix.+foreign import ccall "acb_mat.h acb_mat_eq"+ acb_mat_eq :: Ptr CAcbMat -> Ptr CAcbMat -> IO CInt++-- | /acb_mat_ne/ /mat1/ /mat2/ +-- +-- Returns whether /mat1/ and /mat2/ certainly do not represent the same+-- matrix.+foreign import ccall "acb_mat.h acb_mat_ne"+ acb_mat_ne :: Ptr CAcbMat -> Ptr CAcbMat -> IO CInt++-- | /acb_mat_is_real/ /mat/ +-- +-- Returns whether all entries in /mat/ have zero imaginary part.+foreign import ccall "acb_mat.h acb_mat_is_real"+ acb_mat_is_real :: Ptr CAcbMat -> IO CInt++-- | /acb_mat_is_empty/ /mat/ +-- +-- Returns whether the number of rows or the number of columns in /mat/ is+-- zero.+foreign import ccall "acb_mat.h acb_mat_is_empty"+ acb_mat_is_empty :: Ptr CAcbMat -> IO CInt++-- | /acb_mat_is_square/ /mat/ +-- +-- Returns whether the number of rows is equal to the number of columns in+-- /mat/.+foreign import ccall "acb_mat.h acb_mat_is_square"+ acb_mat_is_square :: Ptr CAcbMat -> IO CInt++-- | /acb_mat_is_exact/ /mat/ +-- +-- Returns whether all entries in /mat/ have zero radius.+foreign import ccall "acb_mat.h acb_mat_is_exact"+ acb_mat_is_exact :: Ptr CAcbMat -> IO CInt++-- | /acb_mat_is_zero/ /mat/ +-- +-- Returns whether all entries in /mat/ are exactly zero.+foreign import ccall "acb_mat.h acb_mat_is_zero"+ acb_mat_is_zero :: Ptr CAcbMat -> IO CInt++-- | /acb_mat_is_finite/ /mat/ +-- +-- Returns whether all entries in /mat/ are finite.+foreign import ccall "acb_mat.h acb_mat_is_finite"+ acb_mat_is_finite :: Ptr CAcbMat -> IO CInt++-- | /acb_mat_is_triu/ /mat/ +-- +-- Returns whether /mat/ is upper triangular; that is, all entries below+-- the main diagonal are exactly zero.+foreign import ccall "acb_mat.h acb_mat_is_triu"+ acb_mat_is_triu :: Ptr CAcbMat -> IO CInt++-- | /acb_mat_is_tril/ /mat/ +-- +-- Returns whether /mat/ is lower triangular; that is, all entries above+-- the main diagonal are exactly zero.+foreign import ccall "acb_mat.h acb_mat_is_tril"+ acb_mat_is_tril :: Ptr CAcbMat -> IO CInt++-- | /acb_mat_is_diag/ /mat/ +-- +-- Returns whether /mat/ is a diagonal matrix; that is, all entries off the+-- main diagonal are exactly zero.+foreign import ccall "acb_mat.h acb_mat_is_diag"+ acb_mat_is_diag :: Ptr CAcbMat -> IO CInt++-- Special matrices ------------------------------------------------------------++-- | /acb_mat_zero/ /mat/ +-- +-- Sets all entries in mat to zero.+foreign import ccall "acb_mat.h acb_mat_zero"+ acb_mat_zero :: Ptr CAcbMat -> IO ()++-- | /acb_mat_one/ /mat/ +-- +-- Sets the entries on the main diagonal to ones, and all other entries to+-- zero.+foreign import ccall "acb_mat.h acb_mat_one"+ acb_mat_one :: Ptr CAcbMat -> IO ()++-- | /acb_mat_ones/ /mat/ +-- +-- Sets all entries in the matrix to ones.+foreign import ccall "acb_mat.h acb_mat_ones"+ acb_mat_ones :: Ptr CAcbMat -> IO ()++-- | /acb_mat_indeterminate/ /mat/ +-- +-- Sets all entries in the matrix to indeterminate (NaN).+foreign import ccall "acb_mat.h acb_mat_indeterminate"+ acb_mat_indeterminate :: Ptr CAcbMat -> IO ()++-- | /acb_mat_dft/ /mat/ /type/ /prec/ +-- +-- Sets /mat/ to the DFT (discrete Fourier transform) matrix of order /n/+-- where /n/ is the smallest dimension of /mat/ (if /mat/ is not square,+-- the matrix is extended periodically along the larger dimension). Here,+-- we use the normalized DFT matrix+-- +-- \[`\]+-- \[A_{j,k} = \frac{\omega^{jk}}{\sqrt{n}}, \quad \omega = e^{-2\pi i/n}.\]+-- +-- The /type/ parameter is currently ignored and should be set to 0. In the+-- future, it might be used to select a different convention.+foreign import ccall "acb_mat.h acb_mat_dft"+ acb_mat_dft :: Ptr CAcbMat -> CInt -> CLong -> IO ()++-- Transpose -------------------------------------------------------------------++-- | /acb_mat_transpose/ /dest/ /src/ +-- +-- Sets /dest/ to the exact transpose /src/. The operands must have+-- compatible dimensions. Aliasing is allowed.+foreign import ccall "acb_mat.h acb_mat_transpose"+ acb_mat_transpose :: Ptr CAcbMat -> Ptr CAcbMat -> IO ()++-- | /acb_mat_conjugate_transpose/ /dest/ /src/ +-- +-- Sets /dest/ to the conjugate transpose of /src/. The operands must have+-- compatible dimensions. Aliasing is allowed.+foreign import ccall "acb_mat.h acb_mat_conjugate_transpose"+ acb_mat_conjugate_transpose :: Ptr CAcbMat -> Ptr CAcbMat -> IO ()++-- | /acb_mat_conjugate/ /dest/ /src/ +-- +-- Sets /dest/ to the elementwise complex conjugate of /src/.+foreign import ccall "acb_mat.h acb_mat_conjugate"+ acb_mat_conjugate :: Ptr CAcbMat -> Ptr CAcbMat -> IO ()++-- Norms -----------------------------------------------------------------------++-- | /acb_mat_bound_inf_norm/ /b/ /A/ +-- +-- Sets /b/ to an upper bound for the infinity norm (i.e. the largest+-- absolute value row sum) of /A/.+foreign import ccall "acb_mat.h acb_mat_bound_inf_norm"+ acb_mat_bound_inf_norm :: Ptr CMag -> Ptr CAcbMat -> IO ()++-- | /acb_mat_frobenius_norm/ /res/ /A/ /prec/ +-- +-- Sets /res/ to the Frobenius norm (i.e. the square root of the sum of+-- squares of entries) of /A/.+foreign import ccall "acb_mat.h acb_mat_frobenius_norm"+ acb_mat_frobenius_norm :: Ptr CAcb -> Ptr CAcbMat -> CLong -> IO ()++-- | /acb_mat_bound_frobenius_norm/ /res/ /A/ +-- +-- Sets /res/ to an upper bound for the Frobenius norm of /A/.+foreign import ccall "acb_mat.h acb_mat_bound_frobenius_norm"+ acb_mat_bound_frobenius_norm :: Ptr CMag -> Ptr CAcbMat -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- | /acb_mat_neg/ /dest/ /src/ +-- +-- Sets /dest/ to the exact negation of /src/. The operands must have the+-- same dimensions.+foreign import ccall "acb_mat.h acb_mat_neg"+ acb_mat_neg :: Ptr CAcbMat -> Ptr CAcbMat -> IO ()++-- | /acb_mat_add/ /res/ /mat1/ /mat2/ /prec/ +-- +-- Sets res to the sum of /mat1/ and /mat2/. The operands must have the+-- same dimensions.+foreign import ccall "acb_mat.h acb_mat_add"+ acb_mat_add :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++-- | /acb_mat_sub/ /res/ /mat1/ /mat2/ /prec/ +-- +-- Sets /res/ to the difference of /mat1/ and /mat2/. The operands must+-- have the same dimensions.+foreign import ccall "acb_mat.h acb_mat_sub"+ acb_mat_sub :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_mul_classical"+ acb_mat_mul_classical :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_mul_threaded"+ acb_mat_mul_threaded :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_mul_reorder"+ acb_mat_mul_reorder :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++-- | /acb_mat_mul/ /res/ /mat1/ /mat2/ /prec/ +-- +-- Sets /res/ to the matrix product of /mat1/ and /mat2/. The operands must+-- have compatible dimensions for matrix multiplication.+-- +-- The /classical/ version performs matrix multiplication in the trivial+-- way.+-- +-- The /threaded/ version performs classical multiplication but splits the+-- computation over the number of threads returned by+-- /flint_get_num_threads()/.+-- +-- The /reorder/ version reorders the data and performs one to four real+-- matrix multiplications via @arb_mat_mul@.+-- +-- The default version chooses an algorithm automatically.+foreign import ccall "acb_mat.h acb_mat_mul"+ acb_mat_mul :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++-- | /acb_mat_mul_entrywise/ /res/ /mat1/ /mat2/ /prec/ +-- +-- Sets /res/ to the entrywise product of /mat1/ and /mat2/. The operands+-- must have the same dimensions.+foreign import ccall "acb_mat.h acb_mat_mul_entrywise"+ acb_mat_mul_entrywise :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_sqr_classical"+ acb_mat_sqr_classical :: Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++-- | /acb_mat_sqr/ /res/ /mat/ /prec/ +-- +-- Sets /res/ to the matrix square of /mat/. The operands must both be+-- square with the same dimensions.+foreign import ccall "acb_mat.h acb_mat_sqr"+ acb_mat_sqr :: Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++-- | /acb_mat_pow_ui/ /res/ /mat/ /exp/ /prec/ +-- +-- Sets /res/ to /mat/ raised to the power /exp/. Requires that /mat/ is a+-- square matrix.+foreign import ccall "acb_mat.h acb_mat_pow_ui"+ acb_mat_pow_ui :: Ptr CAcbMat -> Ptr CAcbMat -> CULong -> CLong -> IO ()++-- | /acb_mat_approx_mul/ /res/ /mat1/ /mat2/ /prec/ +-- +-- Approximate matrix multiplication. The input radii are ignored and the+-- output matrix is set to an approximate floating-point result. For+-- performance reasons, the radii in the output matrix will /not/+-- necessarily be written (zeroed), but will remain zero if they are+-- already zeroed in /res/ before calling this function.+foreign import ccall "acb_mat.h acb_mat_approx_mul"+ acb_mat_approx_mul :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++-- Scalar arithmetic -----------------------------------------------------------++-- | /acb_mat_scalar_mul_2exp_si/ /B/ /A/ /c/ +-- +-- Sets /B/ to /A/ multiplied by \(2^c\).+foreign import ccall "acb_mat.h acb_mat_scalar_mul_2exp_si"+ acb_mat_scalar_mul_2exp_si :: Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_scalar_addmul_si"+ acb_mat_scalar_addmul_si :: Ptr CAcbMat -> Ptr CAcbMat -> CLong -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_scalar_addmul_fmpz"+ acb_mat_scalar_addmul_fmpz :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_scalar_addmul_arb"+ acb_mat_scalar_addmul_arb :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CArb -> CLong -> IO ()++-- | /acb_mat_scalar_addmul_acb/ /B/ /A/ /c/ /prec/ +-- +-- Sets /B/ to \(B + A \times c\).+foreign import ccall "acb_mat.h acb_mat_scalar_addmul_acb"+ acb_mat_scalar_addmul_acb :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_scalar_mul_si"+ acb_mat_scalar_mul_si :: Ptr CAcbMat -> Ptr CAcbMat -> CLong -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_scalar_mul_fmpz"+ acb_mat_scalar_mul_fmpz :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_scalar_mul_arb"+ acb_mat_scalar_mul_arb :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CArb -> CLong -> IO ()++-- | /acb_mat_scalar_mul_acb/ /B/ /A/ /c/ /prec/ +-- +-- Sets /B/ to \(A \times c\).+foreign import ccall "acb_mat.h acb_mat_scalar_mul_acb"+ acb_mat_scalar_mul_acb :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_scalar_div_si"+ acb_mat_scalar_div_si :: Ptr CAcbMat -> Ptr CAcbMat -> CLong -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_scalar_div_fmpz"+ acb_mat_scalar_div_fmpz :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_scalar_div_arb"+ acb_mat_scalar_div_arb :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CArb -> CLong -> IO ()++-- | /acb_mat_scalar_div_acb/ /B/ /A/ /c/ /prec/ +-- +-- Sets /B/ to \(A / c\).+foreign import ccall "acb_mat.h acb_mat_scalar_div_acb"+ acb_mat_scalar_div_acb :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcb -> CLong -> IO ()++-- Gaussian elimination and solving --------------------------------------------++foreign import ccall "acb_mat.h acb_mat_lu_classical"+ acb_mat_lu_classical :: Ptr CLong -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO CInt++foreign import ccall "acb_mat.h acb_mat_lu_recursive"+ acb_mat_lu_recursive :: Ptr CLong -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO CInt++-- | /acb_mat_lu/ /perm/ /LU/ /A/ /prec/ +-- +-- Given an \(n \times n\) matrix \(A\), computes an LU decomposition+-- \(PLU = A\) using Gaussian elimination with partial pivoting. The input+-- and output matrices can be the same, performing the decomposition+-- in-place.+-- +-- Entry \(i\) in the permutation vector perm is set to the row index in+-- the input matrix corresponding to row \(i\) in the output matrix.+-- +-- The algorithm succeeds and returns nonzero if it can find \(n\)+-- invertible (i.e. not containing zero) pivot entries. This guarantees+-- that the matrix is invertible.+-- +-- The algorithm fails and returns zero, leaving the entries in \(P\) and+-- \(LU\) undefined, if it cannot find \(n\) invertible pivot elements. In+-- this case, either the matrix is singular, the input matrix was computed+-- to insufficient precision, or the LU decomposition was attempted at+-- insufficient precision.+-- +-- The /classical/ version uses Gaussian elimination directly while the+-- /recursive/ version performs the computation in a block recursive way to+-- benefit from fast matrix multiplication. The default version chooses an+-- algorithm automatically.+foreign import ccall "acb_mat.h acb_mat_lu"+ acb_mat_lu :: Ptr CLong -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO CInt++foreign import ccall "acb_mat.h acb_mat_solve_tril_classical"+ acb_mat_solve_tril_classical :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CInt -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_solve_tril_recursive"+ acb_mat_solve_tril_recursive :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CInt -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_solve_tril"+ acb_mat_solve_tril :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CInt -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_solve_triu_classical"+ acb_mat_solve_triu_classical :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CInt -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_solve_triu_recursive"+ acb_mat_solve_triu_recursive :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CInt -> CLong -> IO ()++-- | /acb_mat_solve_triu/ /X/ /U/ /B/ /unit/ /prec/ +-- +-- Solves the lower triangular system \(LX = B\) or the upper triangular+-- system \(UX = B\), respectively. If /unit/ is set, the main diagonal of+-- /L/ or /U/ is taken to consist of all ones, and in that case the actual+-- entries on the diagonal are not read at all and can contain other data.+-- +-- The /classical/ versions perform the computations iteratively while the+-- /recursive/ versions perform the computations in a block recursive way+-- to benefit from fast matrix multiplication. The default versions choose+-- an algorithm automatically.+foreign import ccall "acb_mat.h acb_mat_solve_triu"+ acb_mat_solve_triu :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CInt -> CLong -> IO ()++-- | /acb_mat_solve_lu_precomp/ /X/ /perm/ /LU/ /B/ /prec/ +-- +-- Solves \(AX = B\) given the precomputed nonsingular LU decomposition+-- \(A = PLU\). The matrices \(X\) and \(B\) are allowed to be aliased with+-- each other, but \(X\) is not allowed to be aliased with \(LU\).+foreign import ccall "acb_mat.h acb_mat_solve_lu_precomp"+ acb_mat_solve_lu_precomp :: Ptr CAcbMat -> Ptr CLong -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_solve"+ acb_mat_solve :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO CInt++foreign import ccall "acb_mat.h acb_mat_solve_lu"+ acb_mat_solve_lu :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO CInt++-- | /acb_mat_solve_precond/ /X/ /A/ /B/ /prec/ +-- +-- Solves \(AX = B\) where \(A\) is a nonsingular \(n \times n\) matrix and+-- \(X\) and \(B\) are \(n \times m\) matrices.+-- +-- If \(m > 0\) and \(A\) cannot be inverted numerically (indicating either+-- that \(A\) is singular or that the precision is insufficient), the+-- values in the output matrix are left undefined and zero is returned. A+-- nonzero return value guarantees that \(A\) is invertible and that the+-- exact solution matrix is contained in the output.+-- +-- Three algorithms are provided:+-- +-- - The /lu/ version performs LU decomposition directly in ball+-- arithmetic. This is fast, but the bounds typically blow up+-- exponentially with /n/, even if the system is well-conditioned. This+-- algorithm is usually the best choice at very high precision.+-- - The /precond/ version computes an approximate inverse to+-- precondition the system. This is usually several times slower than+-- direct LU decomposition, but the bounds do not blow up with /n/ if+-- the system is well-conditioned. This algorithm is usually the best+-- choice for large systems at low to moderate precision.+-- - The default version selects between /lu/ and /precomp/+-- automatically.+-- +-- The automatic choice should be reasonable most of the time, but users+-- may benefit from trying either /lu/ or /precond/ in specific+-- applications. For example, the /lu/ solver often performs better for+-- ill-conditioned systems where use of very high precision is unavoidable.+foreign import ccall "acb_mat.h acb_mat_solve_precond"+ acb_mat_solve_precond :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO CInt++-- | /acb_mat_inv/ /X/ /A/ /prec/ +-- +-- Sets \(X = A^{-1}\) where \(A\) is a square matrix, computed by solving+-- the system \(AX = I\).+-- +-- If \(A\) cannot be inverted numerically (indicating either that \(A\) is+-- singular or that the precision is insufficient), the values in the+-- output matrix are left undefined and zero is returned. A nonzero return+-- value guarantees that the matrix is invertible and that the exact+-- inverse is contained in the output.+foreign import ccall "acb_mat.h acb_mat_inv"+ acb_mat_inv :: Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO CInt++foreign import ccall "acb_mat.h acb_mat_det_lu"+ acb_mat_det_lu :: Ptr CAcb -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_det_precond"+ acb_mat_det_precond :: Ptr CAcb -> Ptr CAcbMat -> CLong -> IO ()++-- | /acb_mat_det/ /det/ /A/ /prec/ +-- +-- Sets /det/ to the determinant of the matrix /A/.+-- +-- The /lu/ version uses Gaussian elimination with partial pivoting. If at+-- some point an invertible pivot element cannot be found, the elimination+-- is stopped and the magnitude of the determinant of the remaining+-- submatrix is bounded using Hadamard\'s inequality.+-- +-- The /precond/ version computes an approximate LU factorization of /A/+-- and multiplies by the inverse /L/ and /U/ martices as preconditioners to+-- obtain a matrix close to the identity matrix < [Rum2010]>. An enclosure+-- for this determinant is computed using Gershgorin circles. This is about+-- four times slower than direct Gaussian elimination, but much more+-- numerically stable.+-- +-- The default version automatically selects between the /lu/ and /precond/+-- versions and additionally handles small or triangular matrices by direct+-- formulas.+foreign import ccall "acb_mat.h acb_mat_det"+ acb_mat_det :: Ptr CAcb -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_approx_solve_triu"+ acb_mat_approx_solve_triu :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CInt -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_approx_solve_tril"+ acb_mat_approx_solve_tril :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CInt -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_approx_lu"+ acb_mat_approx_lu :: Ptr CLong -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO CInt++foreign import ccall "acb_mat.h acb_mat_approx_solve_lu_precomp"+ acb_mat_approx_solve_lu_precomp :: Ptr CAcbMat -> Ptr CLong -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_approx_solve"+ acb_mat_approx_solve :: Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO CInt++-- | /acb_mat_approx_inv/ /X/ /A/ /prec/ +-- +-- These methods perform approximate solving /without any error control/.+-- The radii in the input matrices are ignored, the computations are done+-- numerically with floating-point arithmetic (using ordinary Gaussian+-- elimination and triangular solving, accelerated through the use of block+-- recursive strategies for large matrices), and the output matrices are+-- set to the approximate floating-point results with zeroed error bounds.+foreign import ccall "acb_mat.h acb_mat_approx_inv"+ acb_mat_approx_inv :: Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO CInt++-- Characteristic polynomial and companion matrix ------------------------------++foreign import ccall "acb_mat.h _acb_mat_charpoly"+ _acb_mat_charpoly :: Ptr CAcb -> Ptr CAcbMat -> CLong -> IO ()++-- | /acb_mat_charpoly/ /poly/ /mat/ /prec/ +-- +-- Sets /poly/ to the characteristic polynomial of /mat/ which must be a+-- square matrix. If the matrix has /n/ rows, the underscore method+-- requires space for \(n + 1\) output coefficients. Employs a+-- division-free algorithm using \(O(n^4)\) operations.+foreign import ccall "acb_mat.h acb_mat_charpoly"+ acb_mat_charpoly :: Ptr CAcbPoly -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h _acb_mat_companion"+ _acb_mat_companion :: Ptr CAcbMat -> Ptr CAcb -> CLong -> IO ()++-- | /acb_mat_companion/ /mat/ /poly/ /prec/ +-- +-- Sets the /n/ by /n/ matrix /mat/ to the companion matrix of the+-- polynomial /poly/ which must have degree /n/. The underscore method+-- reads \(n + 1\) input coefficients.+foreign import ccall "acb_mat.h acb_mat_companion"+ acb_mat_companion :: Ptr CAcbMat -> Ptr CAcbPoly -> CLong -> IO ()++-- Special functions -----------------------------------------------------------++-- | /acb_mat_exp_taylor_sum/ /S/ /A/ /N/ /prec/ +-- +-- Sets /S/ to the truncated exponential Taylor series+-- \(S = \sum_{k=0}^{N-1} A^k / k!\). See @arb_mat_exp_taylor_sum@ for+-- implementation notes.+foreign import ccall "acb_mat.h acb_mat_exp_taylor_sum"+ acb_mat_exp_taylor_sum :: Ptr CAcbMat -> Ptr CAcbMat -> CLong -> CLong -> IO ()++-- | /acb_mat_exp/ /B/ /A/ /prec/ +-- +-- Sets /B/ to the exponential of the matrix /A/, defined by the Taylor+-- series+-- +-- \[`\]+-- \[\exp(A) = \sum_{k=0}^{\infty} \frac{A^k}{k!}.\]+-- +-- The function is evaluated as \(\exp(A/2^r)^{2^r}\), where \(r\) is+-- chosen to give rapid convergence of the Taylor series. Error bounds are+-- computed as for @arb_mat_exp@.+foreign import ccall "acb_mat.h acb_mat_exp"+ acb_mat_exp :: Ptr CAcbMat -> Ptr CAcbMat -> CLong -> IO ()++-- | /acb_mat_trace/ /trace/ /mat/ /prec/ +-- +-- Sets /trace/ to the trace of the matrix, i.e. the sum of entries on the+-- main diagonal of /mat/. The matrix is required to be square.+foreign import ccall "acb_mat.h acb_mat_trace"+ acb_mat_trace :: Ptr CAcb -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h _acb_mat_diag_prod"+ _acb_mat_diag_prod :: Ptr CAcb -> Ptr CAcbMat -> CLong -> CLong -> CLong -> IO ()++-- | /acb_mat_diag_prod/ /res/ /mat/ /prec/ +-- +-- Sets /res/ to the product of the entries on the main diagonal of /mat/.+-- The underscore method computes the product of the entries between index+-- /a/ inclusive and /b/ exclusive (the indices must be in range).+foreign import ccall "acb_mat.h acb_mat_diag_prod"+ acb_mat_diag_prod :: Ptr CAcb -> Ptr CAcbMat -> CLong -> IO ()++-- Component and error operations ----------------------------------------------++-- | /acb_mat_get_mid/ /B/ /A/ +-- +-- Sets the entries of /B/ to the exact midpoints of the entries of /A/.+foreign import ccall "acb_mat.h acb_mat_get_mid"+ acb_mat_get_mid :: Ptr CAcbMat -> Ptr CAcbMat -> IO ()++-- | /acb_mat_add_error_mag/ /mat/ /err/ +-- +-- Adds /err/ in-place to the radii of the entries of /mat/.+foreign import ccall "acb_mat.h acb_mat_add_error_mag"+ acb_mat_add_error_mag :: Ptr CAcbMat -> Ptr CMag -> IO ()++-- Eigenvalues and eigenvectors ------------------------------------------------++-- The functions in this section are experimental. There are classes of+-- matrices where the algorithms fail to converge even as /prec/ is+-- increased, or for which the error bounds are much worse than necessary.+-- In some cases, it can help to manually precondition the matrix /A/ by+-- applying a similarity transformation \(T^{-1} A T\).+--++++-- | /acb_mat_approx_eig_qr/ /E/ /L/ /R/ /A/ /tol/ /maxiter/ /prec/ +-- +-- Computes floating-point approximations of all the /n/ eigenvalues (and+-- optionally eigenvectors) of the given /n/ by /n/ matrix /A/. The+-- approximations of the eigenvalues are written to the vector /E/, in no+-- particular order. If /L/ is not /NULL/, approximations of the+-- corresponding left eigenvectors are written to the rows of /L/. If /R/+-- is not /NULL/, approximations of the corresponding right eigenvectors+-- are written to the columns of /R/.+-- +-- The parameters /tol/ and /maxiter/ can be used to control the target+-- numerical error and the maximum number of iterations allowed before+-- giving up. Passing /NULL/ and 0 respectively results in default values+-- being used.+-- +-- Uses the implicitly shifted QR algorithm with reduction to Hessenberg+-- form. No guarantees are made about the accuracy of the output. A nonzero+-- return value indicates that the QR iteration converged numerically, but+-- this is only a heuristic termination test and does not imply any+-- statement whatsoever about error bounds. The output may also be accurate+-- even if this function returns zero.+foreign import ccall "acb_mat.h acb_mat_approx_eig_qr"+ acb_mat_approx_eig_qr :: Ptr CAcb -> Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> Ptr CMag -> CLong -> CLong -> IO CInt++-- | /acb_mat_eig_global_enclosure/ /eps/ /A/ /E/ /R/ /prec/ +-- +-- Given an /n/ by /n/ matrix /A/, a length-/n/ vector /E/ containing+-- approximations of the eigenvalues of /A/, and an /n/ by /n/ matrix /R/+-- containing approximations of the corresponding right eigenvectors,+-- computes a rigorous bound \(\varepsilon\) such that every eigenvalue+-- \(\lambda\) of /A/ satisfies+-- \(|\lambda - \hat \lambda_k| \le \varepsilon\) for some+-- \(\hat \lambda_k\) in /E/. In other words, the union of the balls+-- \(B_k = \{z : |z - \hat \lambda_k| \le \varepsilon\}\) is guaranteed to+-- be an enclosure of all eigenvalues of /A/.+-- +-- Note that there is no guarantee that each ball \(B_k\) can be identified+-- with a single eigenvalue: it is possible that some balls contain several+-- eigenvalues while other balls contain no eigenvalues. In other words,+-- this method is not powerful enough to compute isolating balls for the+-- individual eigenvalues (or even for clusters of eigenvalues other than+-- the whole spectrum). Nevertheless, in practice the balls \(B_k\) will+-- represent eigenvalues one-to-one with high probability if the given+-- approximations are good.+-- +-- The output can be used to certify that all eigenvalues of /A/ lie in+-- some region of the complex plane (such as a specific half-plane, strip,+-- disk, or annulus) without the need to certify the individual+-- eigenvalues. The output is easily converted into lower or upper bounds+-- for the absolute values or real or imaginary parts of the spectrum, and+-- with high probability these bounds will be tight. Using+-- @acb_add_error_mag@ and @acb_union@, the output can also be converted to+-- a single @acb_t@ enclosing the whole spectrum of /A/ in a rectangle, but+-- note that to test whether a condition holds for all eigenvalues of /A/,+-- it is typically better to iterate over the individual balls \(B_k\).+-- +-- This function implements the fast algorithm in Theorem 1 in < [Miy2010]>+-- which extends the Bauer-Fike theorem. Approximations /E/ and /R/ can,+-- for instance, be computed using @acb_mat_approx_eig_qr@. No assumptions+-- are made about the structure of /A/ or the quality of the given+-- approximations.+foreign import ccall "acb_mat.h acb_mat_eig_global_enclosure"+ acb_mat_eig_global_enclosure :: Ptr CMag -> Ptr CAcbMat -> Ptr CAcb -> Ptr CAcbMat -> CLong -> IO ()++-- | /acb_mat_eig_enclosure_rump/ /lambda/ /J/ /R/ /A/ /lambda_approx/ /R_approx/ /prec/ +-- +-- Given an /n/ by /n/ matrix /A/ and an approximate eigenvalue-eigenvector+-- pair /lambda_approx/ and /R_approx/ (where /R_approx/ is an /n/ by 1+-- matrix), computes an enclosure /lambda/ guaranteed to contain at least+-- one of the eigenvalues of /A/, along with an enclosure /R/ for a+-- corresponding right eigenvector.+-- +-- More generally, this function can handle clustered (or repeated)+-- eigenvalues. If /R_approx/ is an /n/ by /k/ matrix containing+-- approximate eigenvectors for a presumed cluster of /k/ eigenvalues near+-- /lambda_approx/, this function computes an enclosure /lambda/ guaranteed+-- to contain at least /k/ eigenvalues of /A/ along with a matrix /R/+-- guaranteed to contain a basis for the /k/-dimensional invariant subspace+-- associated with these eigenvalues. Note that for multiple eigenvalues,+-- determining the individual eigenvectors is an ill-posed problem;+-- describing an enclosure of the invariant subspace is the best we can+-- hope for.+-- +-- For \(k = 1\), it is guaranteed that \(AR - R \lambda\) contains the+-- zero matrix. For \(k > 2\), this cannot generally be guaranteed (in+-- particular, /A/ might not diagonalizable). In this case, we can still+-- compute an approximately diagonal /k/ by /k/ interval matrix+-- \(J \approx \lambda I\) such that \(AR - RJ\) is guaranteed to contain+-- the zero matrix. This matrix has the property that the Jordan canonical+-- form of (any exact matrix contained in) /A/ has a /k/ by /k/ submatrix+-- equal to the Jordan canonical form of (some exact matrix contained in)+-- /J/. The output /J/ is optional (the user can pass /NULL/ to omit it).+-- +-- The algorithm follows section 13.4 in < [Rum2010]>, corresponding to the+-- @verifyeig()@ routine in INTLAB. The initial approximations can, for+-- instance, be computed using @acb_mat_approx_eig_qr@. No assumptions are+-- made about the structure of /A/ or the quality of the given+-- approximations.+foreign import ccall "acb_mat.h acb_mat_eig_enclosure_rump"+ acb_mat_eig_enclosure_rump :: Ptr CAcb -> Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcb -> Ptr CAcbMat -> CLong -> IO ()++foreign import ccall "acb_mat.h acb_mat_eig_simple_rump"+ acb_mat_eig_simple_rump :: Ptr CAcb -> Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcb -> Ptr CAcbMat -> CLong -> IO CInt++foreign import ccall "acb_mat.h acb_mat_eig_simple_vdhoeven_mourrain"+ acb_mat_eig_simple_vdhoeven_mourrain :: Ptr CAcb -> Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcb -> Ptr CAcbMat -> CLong -> IO CInt++-- | /acb_mat_eig_simple/ /E/ /L/ /R/ /A/ /E_approx/ /R_approx/ /prec/ +-- +-- Computes all the eigenvalues (and optionally corresponding eigenvectors)+-- of the given /n/ by /n/ matrix /A/.+-- +-- Attempts to prove that /A/ has /n/ simple (isolated) eigenvalues,+-- returning 1 if successful and 0 otherwise. On success, isolating complex+-- intervals for the eigenvalues are written to the vector /E/, in no+-- particular order. If /L/ is not /NULL/, enclosures of the corresponding+-- left eigenvectors are written to the rows of /L/. If /R/ is not /NULL/,+-- enclosures of the corresponding right eigenvectors are written to the+-- columns of /R/.+-- +-- The left eigenvectors are normalized so that \(L = R^{-1}\). This+-- produces a diagonalization \(LAR = D\) where /D/ is the diagonal matrix+-- with the entries in /E/ on the diagonal.+-- +-- The user supplies approximations /E_approx/ and /R_approx/ of the+-- eigenvalues and the right eigenvectors. The initial approximations can,+-- for instance, be computed using @acb_mat_approx_eig_qr@. No assumptions+-- are made about the structure of /A/ or the quality of the given+-- approximations.+-- +-- Two algorithms are implemented:+-- +-- - The /rump/ version calls @acb_mat_eig_enclosure_rump@ repeatedly to+-- certify eigenvalue-eigenvector pairs one by one. The iteration is+-- stopped to return non-success if a new eigenvalue overlaps with+-- previously computed one. Finally, /L/ is computed by a matrix+-- inversion. This has complexity \(O(n^4)\).+-- - The /vdhoeven_mourrain/ version uses the algorithm in < [HM2017]> to+-- certify all eigenvalues and eigenvectors in one step. This has+-- complexity \(O(n^3)\).+-- +-- The default version currently uses /vdhoeven_mourrain/.+-- +-- By design, these functions terminate instead of attempting to compute+-- eigenvalue clusters if some eigenvalues cannot be isolated. To compute+-- all eigenvalues of a matrix allowing for overlap,+-- @acb_mat_eig_multiple_rump@ may be used as a fallback, or+-- @acb_mat_eig_multiple@ may be used in the first place.+foreign import ccall "acb_mat.h acb_mat_eig_simple"+ acb_mat_eig_simple :: Ptr CAcb -> Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcbMat -> Ptr CAcb -> Ptr CAcbMat -> CLong -> IO CInt++foreign import ccall "acb_mat.h acb_mat_eig_multiple_rump"+ acb_mat_eig_multiple_rump :: Ptr CAcb -> Ptr CAcbMat -> Ptr CAcb -> Ptr CAcbMat -> CLong -> IO CInt++-- | /acb_mat_eig_multiple/ /E/ /A/ /E_approx/ /R_approx/ /prec/ +-- +-- Computes all the eigenvalues of the given /n/ by /n/ matrix /A/. On+-- success, the output vector /E/ contains /n/ complex intervals, each+-- representing one eigenvalue of /A/ with the correct multiplicities in+-- case of overlap. The output intervals are either disjoint or identical,+-- and identical intervals are guaranteed to be grouped consecutively. Each+-- complete run of /k/ identical intervals thus represents a cluster of+-- exactly /k/ eigenvalues which could not be separated from each other at+-- the current precision, but which could be isolated from the other+-- \(n - k\) eigenvalues of the matrix.+-- +-- The user supplies approximations /E_approx/ and /R_approx/ of the+-- eigenvalues and the right eigenvectors. The initial approximations can,+-- for instance, be computed using @acb_mat_approx_eig_qr@. No assumptions+-- are made about the structure of /A/ or the quality of the given+-- approximations.+-- +-- The /rump/ algorithm groups approximate eigenvalues that are close and+-- calls @acb_mat_eig_enclosure_rump@ repeatedly to validate each cluster.+-- The complexity is \(O(m n^3)\) for /m/ clusters.+-- +-- The default version, as currently implemented, first attempts to call+-- @acb_mat_eig_simple_vdhoeven_mourrain@ hoping that the eigenvalues are+-- actually simple. It then uses the /rump/ algorithm as a fallback.+foreign import ccall "acb_mat.h acb_mat_eig_multiple"+ acb_mat_eig_multiple :: Ptr CAcb -> Ptr CAcbMat -> Ptr CAcb -> Ptr CAcbMat -> CLong -> IO CInt+
+ src/Data/Number/Flint/Acb/Mat/Instances.hs view
@@ -0,0 +1,16 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Acb.Mat.Instances where++import System.IO.Unsafe+import Foreign.C.String+import Foreign.Marshal.Alloc ( free )++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb.Mat++instance Show AcbMat where+ show x = unsafePerformIO $ do+ (_, cs) <- withAcbMat x $ \x -> do acb_mat_get_strn x 16 arb_str_no_radius+ s <- peekCString cs+ free cs+ return s
+ src/Data/Number/Flint/Acb/Modular.hs view
@@ -0,0 +1,26 @@+{- |+This module provides methods for numerical evaluation of modular forms+and Jacobi theta functions. See module [Data.Number.Flint.Acb.Elliptic]("Data.Number.Flint.Acb.Elliptic") for the closely related elliptic functions and integrals.++In the context of this module, /tau/ or \(\tau\) always denotes an+element of the complex +upper half-plane \(\mathbb{H} = \{z\in\mathbb{C}:\operatorname{Im}(z) > 0\}\). +We also often use the variable \(q\),+variously defined as \(q = e^{2 \pi i \tau}\) (usually in relation to+modular forms) or \(q = e^{\pi i \tau}\) (usually in relation to theta+functions) and satisfying \(|q| < 1\). We will clarify the local meaning+of \(q\) every time such a quantity appears as a function of \(\tau\).++As usual, the numerical functions in this module compute strict error+bounds: if /tau/ is represented by an "Acb" whose content overlaps+with the real line (or lies in the lower half-plane), and /tau/ is+passed to a function defined only on \(\mathbb{H}\), then the output+will have an infinite radius. The analogous behavior holds for functions+requiring \(|q| < 1\).+-}++module Data.Number.Flint.Acb.Modular (+ module Data.Number.Flint.Acb.Modular.FFI+ ) where++import Data.Number.Flint.Acb.Modular.FFI
+ src/Data/Number/Flint/Acb/Modular/FFI.hsc view
@@ -0,0 +1,907 @@+{-|+module : Data.Number.Flint.Acb.Modular.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Acb.Modular.FFI (+ -- * Modular forms of complex variables+ -- * The modular group+ PSL2Z (..)+ , CPSL2Z (..)+ , newPSL2Z+ , newPSL2Z_+ , withPSL2Z+ , withNewPSL2Z+ , withNewPSL2Z_+ , psl2z_init+ , psl2z_clear+ , psl2z_swap+ , psl2z_set+ , psl2z_one+ , psl2z_is_one+ , psl2z_get_str+ , psl2z_print+ , psl2z_fprint+ , psl2z_equal+ , psl2z_mul+ , psl2z_inv+ , psl2z_is_correct+ , psl2z_randtest+ -- * Word problem+ --+ -- $WordProblem+ , PSL2ZWord (..)+ , CPSL2ZWord (..)+ , newPSL2ZWord+ , withPSL2ZWord+ , withNewPSL2ZWord+ , psl2z_word_init+ , psl2z_word_clear+ , psl2z_get_word+ , psl2z_set_word+ , _perm_set_word+ , psl2z_word_fprint+ , psl2z_word_print+ , psl2z_word_get_str+ , psl2z_word_fprint_pretty+ , psl2z_word_print_pretty+ , psl2z_word_get_str_pretty+ , psl2z_get_perm+ -- * Modular transformations+ , acb_modular_transform+ , acb_modular_fundamental_domain_approx_d+ , acb_modular_fundamental_domain_approx_arf+ , acb_modular_fundamental_domain_approx+ , acb_modular_is_in_fundamental_domain+ -- * Addition sequences+ , acb_modular_fill_addseq+ -- * Jacobi theta functions+ , acb_modular_theta_transform+ , acb_modular_addseq_theta+ , acb_modular_theta_sum+ , acb_modular_theta_const_sum_basecase+ , acb_modular_theta_const_sum_rs+ , acb_modular_theta_const_sum+ , acb_modular_theta_notransform+ , acb_modular_theta+ , acb_modular_theta_jet_notransform+ , acb_modular_theta_jet+ , _acb_modular_theta_series+ , acb_modular_theta_series+ -- * Dedekind eta function+ , acb_modular_addseq_eta+ , acb_modular_eta_sum+ , acb_modular_epsilon_arg+ , acb_modular_eta+ -- * Modular forms+ , acb_modular_j+ , acb_modular_lambda+ , acb_modular_delta+ , acb_modular_eisenstein+ -- * Elliptic integrals and functions+ , acb_modular_elliptic_k+ , acb_modular_elliptic_k_cpx+ , acb_modular_elliptic_e+ , acb_modular_elliptic_p+ , acb_modular_elliptic_p_zpx+ -- * Class polynomials+ , acb_modular_hilbert_class_poly+) where++-- Modular forms of complex variables ------------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, castPtr, nullPtr )+import Foreign.Storable+import Foreign.Marshal ( free, peekArray )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpq++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb.Types+import Data.Number.Flint.Acb.Poly++#include <flint/acb_modular.h>++-- psl2z_t ---------------------------------------------------------------------++data PSL2Z = PSL2Z {-# UNPACK #-} !(ForeignPtr CPSL2Z) +data CPSL2Z = CPSL2Z (Ptr CFmpz) (Ptr CFmpz) (Ptr CFmpz) (Ptr CFmpz) ++instance Storable CPSL2Z where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size psl2z_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment psl2z_t}+ peek ptr = CPSL2Z+ <$> (return $ castPtr ptr)+ <*> (return $ castPtr ptr `advancePtr` 1)+ <*> (return $ castPtr ptr `advancePtr` 2)+ <*> (return $ castPtr ptr `advancePtr` 3)+ poke = error "CPSL2Z.poke: undefined."+ +newPSL2Z = do+ x <- mallocForeignPtr+ withForeignPtr x psl2z_init+ addForeignPtrFinalizer p_psl2z_clear x+ return $ PSL2Z x++newPSL2Z_ a b c d = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ psl2z_init x+ withFmpz a $ \a' -> do+ withFmpz b $ \b' -> do+ withFmpz c $ \c' -> do+ withFmpz d $ \d' -> do+ CPSL2Z a b c d <- peek x+ fmpz_set a a'+ fmpz_set b b'+ fmpz_set c c'+ fmpz_set d d'+ psl2z_normal_form x+ flag <- psl2z_is_correct x+ when (flag /= 1) $ do error "newPSL2Z_ a b c d with ad - bc not one."+ addForeignPtrFinalizer p_psl2z_clear x+ return $ PSL2Z x++{-# INLINE withPSL2Z #-}+withPSL2Z (PSL2Z x) f = do+ withForeignPtr x $ \px -> f px >>= return . (PSL2Z x,)++{-# INLINE withNewPSL2Z #-}+withNewPSL2Z f = do+ x <- newPSL2Z+ withPSL2Z x f++{-# INLINE withNewPSL2Z_ #-}+withNewPSL2Z_ a b c d f = do+ x <- newPSL2Z_ a b c d+ withPSL2Z x f++-- The modular group -----------------------------------------------------------++-- | /psl2z_init/ /g/ +-- +-- Initializes /g/ and set it to the identity element.+foreign import ccall "acb_modular.h psl2z_init_"+ psl2z_init :: Ptr CPSL2Z -> IO ()+ +-- | /psl2z_clear/ /g/ +-- +-- Clears /g/.+foreign import ccall "acb_modular.h psl2z_clear_"+ psl2z_clear :: Ptr CPSL2Z -> IO ()++foreign import ccall "acb_modular.h &psl2z_clear_"+ p_psl2z_clear :: FunPtr (Ptr CPSL2Z -> IO ())++foreign import ccall "acb_modular.h psl2z_normal_form"+ psl2z_normal_form :: Ptr CPSL2Z -> IO ()++-- | /psl2z_swap/ /f/ /g/ +-- +-- Swaps /f/ and /g/ efficiently.+foreign import ccall "acb_modular.h psl2z_swap_"+ psl2z_swap :: Ptr CPSL2Z -> Ptr CPSL2Z -> IO ()++-- | /psl2z_set/ /f/ /g/ +-- +-- Sets /f/ to a copy of /g/.+foreign import ccall "acb_modular.h psl2z_set_"+ psl2z_set :: Ptr CPSL2Z -> Ptr CPSL2Z -> IO ()++-- | /psl2z_one/ /g/ +-- +-- Sets /g/ to the identity element.+foreign import ccall "acb_modular.h psl2z_one_"+ psl2z_one :: Ptr CPSL2Z -> IO ()++-- | /psl2z_is_one/ /g/ +-- +-- Returns nonzero iff /g/ is the identity element.+foreign import ccall "acb_modular.h psl2z_is_one_"+ psl2z_is_one :: Ptr CPSL2Z -> IO CInt++foreign import ccall "acb_modular.h"+ psl2z_get_str :: Ptr CPSL2Z -> IO CString+ +-- | /psl2z_print/ /g/ +-- +-- Prints /g/ to standard output.+psl2z_print :: Ptr CPSL2Z -> IO ()+psl2z_print x = do+ cs <- psl2z_get_str x+ s <- peekCString cs+ free cs+ putStr s+ +-- | /psl2z_fprint/ /file/ /g/ +-- +-- Prints /g/ to the stream /file/.+foreign import ccall "acb_modular.h psl2z_fprint"+ psl2z_fprint :: Ptr CFile -> Ptr CPSL2Z -> IO ()++-- | /psl2z_equal/ /f/ /g/ +-- +-- Returns nonzero iff /f/ and /g/ are equal.+foreign import ccall "acb_modular.h psl2z_equal_"+ psl2z_equal :: Ptr CPSL2Z -> Ptr CPSL2Z -> IO CInt++-- | /psl2z_mul/ /h/ /f/ /g/ +-- +-- Sets /h/ to the product of /f/ and /g/, namely the matrix product with+-- the signs canonicalized.+foreign import ccall "acb_modular.h psl2z_mul"+ psl2z_mul :: Ptr CPSL2Z -> Ptr CPSL2Z -> Ptr CPSL2Z -> IO ()++-- | /psl2z_inv/ /h/ /g/ +-- +-- Sets /h/ to the inverse of /g/.+foreign import ccall "acb_modular.h psl2z_inv"+ psl2z_inv :: Ptr CPSL2Z -> Ptr CPSL2Z -> IO ()++-- | /psl2z_is_correct/ /g/ +-- +-- Returns nonzero iff /g/ contains correct data, i.e. satisfying+-- \(ad-bc = 1\), \(c \ge 0\), and \(d > 0\) if \(c = 0\).+foreign import ccall "acb_modular.h psl2z_is_correct"+ psl2z_is_correct :: Ptr CPSL2Z -> IO CInt++-- | /psl2z_randtest/ /g/ /state/ /bits/ +-- +-- Sets /g/ to a random element of \(\text{PSL}(2, \mathbb{Z})\) with+-- entries of bit length at most /bits/ (or 1, if /bits/ is not positive).+-- We first generate /a/ and /d/, compute their Bezout coefficients, divide+-- by the GCD, and then correct the signs.+foreign import ccall "acb_modular.h psl2z_randtest"+ psl2z_randtest :: Ptr CPSL2Z -> Ptr CFRandState -> CLong -> IO ()++-- Word problem ----------------------------------------------------------------++-- $WordProblem+--+-- Any element \(\gamma\) of \(\rm{PSL}_2(\mathbb{Z})\) can be+-- expressed in a word in the generatars of the modular group \(S\)+-- and \(T\). This decomposition is not unique. E.g.+-- the element \[\gamma = \begin{pmatrix} 36 & 7 \\ 5 & 1 \end{pmatrix}\]+-- corresponds to the word \([(T,7),(S,3),(T,-5),(S,3)]\) meaning+-- that \(\gamma\) can be written as+-- \[\gamma = T^7 S^3 T^{-5} S^3.\]++#include "psl2z.h"++data PSL2ZWord = PSL2ZWord {-#UNPACK#-} !(ForeignPtr CPSL2ZWord)+data CPSL2ZWord = CPSL2ZWord (Ptr CFmpz) CLong++instance Storable CPSL2ZWord where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size psl2z_word_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment psl2z_word_t}+ peek ptr = CPSL2ZWord+ <$> #{peek psl2z_word_struct, letters} ptr+ <*> #{peek psl2z_word_struct, alloc } ptr+ poke = error "CPSL2ZWord.poke: undefined."+ +newPSL2ZWord = do+ x <- mallocForeignPtr+ withForeignPtr x psl2z_word_init+ addForeignPtrFinalizer p_psl2z_word_clear x+ return $ PSL2ZWord x++{-# INLINE withPSL2ZWord #-}+withPSL2ZWord (PSL2ZWord x) f = do+ withForeignPtr x $ \px -> f px >>= return . (PSL2ZWord x,)++{-# INLINE withNewPSL2ZWord #-}+withNewPSL2ZWord f = do+ x <- newPSL2ZWord+ withPSL2ZWord x f++--- | /psl2z_init/ /word/+--+-- Initializes /word/ for the word problem with the empty word.+foreign import ccall "psl2z.h psl2z_word_init"+ psl2z_word_init :: Ptr CPSL2ZWord -> IO ()++--- | /psl2z_clear/ /word/+--+-- Clears /word/.+foreign import ccall "psl2z.h psl2z_word_clear"+ psl2z_word_clear :: Ptr CPSL2ZWord -> IO ()++foreign import ccall "psl2z.h &psl2z_word_clear"+ p_psl2z_word_clear :: FunPtr (Ptr CPSL2ZWord -> IO ())++-- | /psl2z_get_word/ /word/ /x/+--+-- Decomposes \x\ into a word in /S/ and /T/.+foreign import ccall "psl2z.h psl2z_get_word"+ psl2z_get_word :: Ptr CPSL2ZWord -> Ptr CPSL2Z -> IO ()++-- | /psl2z__word/ /word/ /x/+--+-- Compose \x\ from a word in /S/ and /T/.+foreign import ccall "psl2z.h psl2z_set_word"+ psl2z_set_word :: Ptr CPSL2Z -> Ptr CPSL2ZWord -> IO ()++-- | /perm_set_word/ /x/ /s/ /t/ /n/ /word/+--+-- Calculate homomorphism for word from permutations `s` and `t`.+foreign import ccall "psl2z.h _perm_set_word"+ _perm_set_word :: Ptr CLong -> Ptr CLong -> Ptr CLong -> CLong+ -> Ptr CPSL2ZWord -> IO ()++-- Word input output -----------------------------------------------------------++-- | /psl2z_word_fprint/ /word/+--+-- Outputs /word/ to a file as vector. +foreign import ccall "psl2z.h psl2z_word_fprint"+ psl2z_word_fprint :: Ptr CFile -> Ptr CPSL2ZWord -> IO ()++-- | /psl2z_word_print/ /word/+--+-- Outputs /word/ to `stdout` as vector. +psl2z_word_print :: Ptr CPSL2ZWord -> IO ()+psl2z_word_print word = do+ printCStr psl2z_word_get_str word+ return ()++-- | /psl2z_word_get_str/ /word/+--+-- Returns as string representation of /word/ as vector. +foreign import ccall "psl2z.h psl2z_word_get_str"+ psl2z_word_get_str :: Ptr CPSL2ZWord -> IO CString++-- | /psl2z_word_fprint_pretty/ /word/+--+-- Outputs /word/ to a file in tuples of generators with the+-- corresponding power.+foreign import ccall "psl2z.h psl2z_word_fprint_pretty"+ psl2z_word_fprint_pretty :: Ptr CFile -> Ptr CPSL2ZWord -> IO ()++-- | /psl2z_word_print_pretty/ /word/+--+-- Outputs /word/ to stdout in tuples of generators with the+-- corresponding power.+psl2z_word_print_pretty :: Ptr CPSL2ZWord -> IO ()+psl2z_word_print_pretty word = do+ printCStr psl2z_word_get_str_pretty word+ return ()++-- | /psl2z_word_get_str_pretty/ /word/+--+-- Returns a string representation of /word/ in tuples of generators with the+-- corresponding power.+foreign import ccall "psl2z.h psl2z_word_get_str_pretty"+ psl2z_word_get_str_pretty :: Ptr CPSL2ZWord -> IO CString++-- | /psl2z_get_perm/ /p/ /s/ /t/ /n/ /x/+--+-- Returns the permutation \(p\) corresponding to \(x\) by the +-- homomorphism \(\phi:{\textrm PSL}_2\left({\mathbb Z}\right)\rightarrow S_n\)+-- defined by the permutations \(s\) and \(t\):+--+-- \[+-- \begin{align}+-- \begin{pmatrix} 0 &-1 \\ 1 & 0 \end{pmatrix} &\mapsto s \\+-- \begin{pmatrix} 1 & 1 \\ 0 & 1 \end{pmatrix} &\mapsto t. \\+-- \end{align}+-- \]+foreign import ccall "psl2z.h psl2z_get_perm"+ psl2z_get_perm :: Ptr CLong -> Ptr CLong -> Ptr CLong -> CLong+ -> Ptr CPSL2Z -> IO ()+ +-- Modular transformations -----------------------------------------------------++-- | /acb_modular_transform/ /w/ /g/ /z/ /prec/ +-- +-- Applies the modular transformation /g/ to the complex number /z/,+-- evaluating+-- +-- \[`\]+-- \[w = g z = \frac{az+b}{cz+d}.\]+foreign import ccall "acb_modular.h acb_modular_transform"+ acb_modular_transform :: Ptr CAcb -> Ptr CPSL2Z -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_modular.h acb_modular_fundamental_domain_approx_d"+ acb_modular_fundamental_domain_approx_d :: Ptr CPSL2Z -> CDouble -> CDouble -> CDouble -> IO ()++-- | /acb_modular_fundamental_domain_approx_arf/ /g/ /x/ /y/ /one_minus_eps/ /prec/ +-- +-- Attempts to determine a modular transformation /g/ that maps the complex+-- number \(x+yi\) to the fundamental domain or just slightly outside the+-- fundamental domain, where the target tolerance (not a strict bound) is+-- specified by /one_minus_eps/.+-- +-- The inputs are assumed to be finite numbers, with /y/ positive.+-- +-- Uses floating-point iteration, repeatedly applying either the+-- transformation \(z \gets z + b\) or \(z \gets -1/z\). The iteration is+-- terminated if \(|x| \le 1/2\) and \(x^2 + y^2 \ge 1 - \varepsilon\)+-- where \(1 - \varepsilon\) is passed as /one_minus_eps/. It is also+-- terminated if too many steps have been taken without convergence, or if+-- the numbers end up too large or too small for the working precision.+-- +-- The algorithm can fail to produce a satisfactory transformation. The+-- output /g/ is always set to /some/ correct modular transformation, but+-- it is up to the user to verify a posteriori that /g/ maps \(x+yi\) close+-- enough to the fundamental domain.+foreign import ccall "acb_modular.h acb_modular_fundamental_domain_approx_arf"+ acb_modular_fundamental_domain_approx_arf :: Ptr CPSL2Z -> Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> IO ()++-- | /acb_modular_fundamental_domain_approx/ /w/ /g/ /z/ /one_minus_eps/ /prec/ +-- +-- Attempts to determine a modular transformation /g/ that maps the complex+-- number \(z\) to the fundamental domain or just slightly outside the+-- fundamental domain, where the target tolerance (not a strict bound) is+-- specified by /one_minus_eps/. It also computes the transformed value+-- \(w = gz\).+-- +-- This function first tries to use+-- @acb_modular_fundamental_domain_approx_d@ and checks if the result is+-- acceptable. If this fails, it calls+-- @acb_modular_fundamental_domain_approx_arf@ with higher precision.+-- Finally, \(w = gz\) is evaluated by a single application of /g/.+-- +-- The algorithm can fail to produce a satisfactory transformation. The+-- output /g/ is always set to /some/ correct modular transformation, but+-- it is up to the user to verify a posteriori that \(w\) is close enough+-- to the fundamental domain.+foreign import ccall "acb_modular.h acb_modular_fundamental_domain_approx"+ acb_modular_fundamental_domain_approx :: Ptr CAcb -> Ptr CPSL2Z -> Ptr CAcb -> Ptr CArf -> CLong -> IO ()++-- | /acb_modular_is_in_fundamental_domain/ /z/ /tol/ /prec/ +-- +-- Returns nonzero if it is certainly true that \(|z| \ge 1 - \varepsilon\)+-- and \(|\operatorname{Re}(z)| \le 1/2 + \varepsilon\) where+-- \(\varepsilon\) is specified by /tol/. Returns zero if this is false or+-- cannot be determined.+foreign import ccall "acb_modular.h acb_modular_is_in_fundamental_domain"+ acb_modular_is_in_fundamental_domain :: Ptr CAcb -> Ptr CArf -> CLong -> IO CInt++-- Addition sequences ----------------------------------------------------------++-- | /acb_modular_fill_addseq/ /tab/ /len/ +-- +-- Builds a near-optimal addition sequence for a sequence of integers which+-- is assumed to be reasonably dense.+-- +-- As input, the caller should set each entry in /tab/ to \(-1\) if that+-- index is to be part of the addition sequence, and to 0 otherwise. On+-- output, entry /i/ in /tab/ will either be zero (if the number is not+-- part of the sequence), or a value /j/ such that both /j/ and \(i - j\)+-- are also marked. The first two entries in /tab/ are ignored (the number+-- 1 is always assumed to be part of the sequence).+foreign import ccall "acb_modular.h acb_modular_fill_addseq"+ acb_modular_fill_addseq :: Ptr CLong -> CLong -> IO ()++-- Jacobi theta functions ------------------------------------------------------++-- Unfortunately, there are many inconsistent notational variations for+-- Jacobi theta functions in the literature. Unless otherwise noted, we use+-- the functions+--+-- \[`\]+-- \[\theta_1(z,\tau) = -i \sum_{n=-\infty}^{\infty} (-1)^n \exp(\pi i [(n + 1/2)^2 \tau + (2n + 1) z])+-- = 2 q_{1/4} \sum_{n=0}^{\infty} (-1)^n q^{n(n+1)} \sin((2n+1) \pi z)\]+--+-- \[`\]+-- \[\theta_2(z,\tau) = \sum_{n=-\infty}^{\infty} \exp(\pi i [(n + 1/2)^2 \tau + (2n + 1) z])+-- = 2 q_{1/4} \sum_{n=0}^{\infty} q^{n(n+1)} \cos((2n+1) \pi z)\]+--+-- \[`\]+-- \[\theta_3(z,\tau) = \sum_{n=-\infty}^{\infty} \exp(\pi i [n^2 \tau + 2n z])+-- = 1 + 2 \sum_{n=1}^{\infty} q^{n^2} \cos(2n \pi z)\]+--+-- \[`\]+-- \[\theta_4(z,\tau) = \sum_{n=-\infty}^{\infty} (-1)^n \exp(\pi i [n^2 \tau + 2n z])+-- = 1 + 2 \sum_{n=1}^{\infty} (-1)^n q^{n^2} \cos(2n \pi z)\]+--+-- where \(q = \exp(\pi i \tau)\) and \(q_{1/4} = \exp(\pi i \tau / 4)\).+-- Note that many authors write \(q_{1/4}\) as \(q^{1/4}\), but the+-- principal fourth root \((q)^{1/4} = \exp(\frac{1}{4} \log q)\) differs+-- from \(q_{1/4}\) in general and some formulas are only correct if one+-- reads \"q^{1\/4} = exp(pi i tau \/ 4)\". To avoid confusion, we only+-- write \(q^k\) when \(k\) is an integer.+--+-- | /acb_modular_theta_transform/ /R/ /S/ /C/ /g/ +-- +-- We wish to write a theta function with quasiperiod \(\tau\) in terms of+-- a theta function with quasiperiod \(\tau' = g \tau\), given some+-- \(g = (a, b; c, d) \in \text{PSL}(2, \mathbb{Z})\). For+-- \(i = 0, 1, 2, 3\), this function computes integers \(R_i\) and \(S_i\)+-- (/R/ and /S/ should be arrays of length 4) and \(C \in \{0, 1\}\) such+-- that+-- +-- \[`\]+-- \[\theta_{1+i}(z,\tau) = \exp(\pi i R_i / 4) \cdot A \cdot B \cdot \theta_{1+S_i}(z',\tau')\]+-- +-- where \(z' = z, A = B = 1\) if \(C = 0\), and+-- +-- \[`\]+-- \[z' = \frac{-z}{c \tau + d}, \quad+-- A = \sqrt{\frac{i}{c \tau + d}}, \quad+-- B = \exp\left(-\pi i c \frac{z^2}{c \tau + d}\right)\]+-- +-- if \(C = 1\). Note that \(A\) is well-defined with the principal branch+-- of the square root since \(A^2 = i/(c \tau + d)\) lies in the right+-- half-plane.+-- +-- Firstly, if \(c = 0\), we have+-- \(\theta_i(z, \tau) = \exp(-\pi i b / 4) \theta_i(z, \tau+b)\) for+-- \(i = 1, 2\), whereas \(\theta_3\) and \(\theta_4\) remain unchanged+-- when \(b\) is even and swap places with each other when \(b\) is odd. In+-- this case we set \(C = 0\).+-- +-- For an arbitrary \(g\) with \(c > 0\), we set \(C = 1\). The general+-- transformations are given by Rademacher < [Rad1973]>. We need the+-- function \(\theta_{m,n}(z,\tau)\) defined for \(m, n \in \mathbb{Z}\) by+-- (beware of the typos in < [Rad1973]>)+-- +-- \[`\]+-- \[\theta_{0,0}(z,\tau) = \theta_3(z,\tau), \quad+-- \theta_{0,1}(z,\tau) = \theta_4(z,\tau)\]+-- +-- \[`\]+-- \[\theta_{1,0}(z,\tau) = \theta_2(z,\tau), \quad+-- \theta_{1,1}(z,\tau) = i \theta_1(z,\tau)\]+-- +-- \[`\]+-- \[\theta_{m+2,n}(z,\tau) = (-1)^n \theta_{m,n}(z,\tau)\]+-- +-- \[`\]+-- \[\theta_{m,n+2}(z,\tau) = \theta_{m,n}(z,\tau).\]+-- +-- Then we may write+-- +-- \[+-- \begin{eqnarray*}+-- \theta_1(z,\tau) &=& \varepsilon_1 A B \theta_1(z', \tau')\\+-- \theta_2(z,\tau) &=& \varepsilon_2 A B \theta_{1-c,1+a}(z', \tau')\\+-- \theta_3(z,\tau) &=& \varepsilon_3 A B \theta_{1+d-c,1-b+a}(z', \tau')\\+-- \theta_4(z,\tau) &=& \varepsilon_4 A B \theta_{1+d,1-b}(z', \tau')+-- \end{eqnarray*}+-- \]+-- +-- where \(\varepsilon_i\) is an 8th root of unity. Specifically, if we+-- denote the 24th root of unity in the transformation formula of the+-- Dedekind eta function by+-- \(\varepsilon(a,b,c,d) = \exp(\pi i R(a,b,c,d) / 12)\) (see+-- @acb_modular_epsilon_arg@), then:+-- +-- \[+-- \begin{eqnarray*}+-- \varepsilon_1(a,b,c,d) &=& \exp(\pi i [R(-d,b,c,-a) + 1]/4)\\+-- \varepsilon_2(a,b,c,d) &=& \exp(\pi i [-R(a,b,c,d) + (5+(2-c)a)]/4)\\+-- \varepsilon_3(a,b,c,d) &=& \exp(\pi i [-R(a,b,c,d) + (4+(c-d-2)(b-a))]/4)\\+-- \varepsilon_4(a,b,c,d) &=& \exp(\pi i [-R(a,b,c,d) + (3-(2+d)b)]/4)\\+-- \end{eqnarray*}+-- \]+--+-- These formulas are easily derived from the formulas in < [Rad1973]>+-- (Rademacher has the transformed\/untransformed variables exchanged, and+-- his \"(\varepsilon\)\" differs from ours by a constant offset in the phase).+foreign import ccall "acb_modular.h acb_modular_theta_transform"+ acb_modular_theta_transform :: Ptr CInt -> Ptr CInt -> Ptr CInt -> Ptr CPSL2Z -> IO ()++-- | /acb_modular_addseq_theta/ /exponents/ /aindex/ /bindex/ /num/ +-- +-- Constructs an addition sequence for the first /num/ squares and+-- triangular numbers interleaved (excluding zero), i.e. 1, 2, 4, 6, 9, 12,+-- 16, 20, 25, 30 etc.+foreign import ccall "acb_modular.h acb_modular_addseq_theta"+ acb_modular_addseq_theta :: Ptr CLong -> Ptr CLong -> Ptr CLong -> CLong -> IO ()++-- | /acb_modular_theta_sum/ /theta1/ /theta2/ /theta3/ /theta4/ /w/ /w_is_unit/ /q/ /len/ /prec/ +-- +-- Simultaneously computes the first /len/ coefficients of each of the+-- formal power series+-- +-- \[`\]+-- \[\theta_1(z+x,\tau) / q_{1/4} \in \mathbb{C}[[x]]\]+-- \[\theta_2(z+x,\tau) / q_{1/4} \in \mathbb{C}[[x]]\]+-- \[\theta_3(z+x,\tau) \in \mathbb{C}[[x]]\]+-- \[\theta_4(z+x,\tau) \in \mathbb{C}[[x]]\]+-- +-- given \(w = \exp(\pi i z)\) and \(q = \exp(\pi i \tau)\), by summing a+-- finite truncation of the respective theta function series. In+-- particular, with /len/ equal to 1, computes the respective value of the+-- theta function at the point /z/. We require /len/ to be positive. If+-- /w_is_unit/ is nonzero, /w/ is assumed to lie on the unit circle, i.e.+-- /z/ is assumed to be real.+-- +-- Note that the factor \(q_{1/4}\) is removed from \(\theta_1\) and+-- \(\theta_2\). To get the true theta function values, the user has to+-- multiply this factor back. This convention avoids unnecessary+-- computations, since the user can compute+-- \(q_{1/4} = \exp(\pi i \tau / 4)\) followed by \(q = (q_{1/4})^4\), and+-- in many cases when computing products or quotients of theta functions,+-- the factor \(q_{1/4}\) can be eliminated entirely.+-- +-- This function is intended for \(|q| \ll 1\). It can be called with any+-- \(q\), but will return useless intervals if convergence is not rapid.+-- For general evaluation of theta functions, the user should only call+-- this function after applying a suitable modular transformation.+-- +-- We consider the sums together, alternatingly updating+-- \((\theta_1, \theta_2)\) or \((\theta_3, \theta_4)\). For+-- \(k = 0, 1, 2, \ldots\), the powers of \(q\) are+-- \(\lfloor (k+2)^2 / 4 \rfloor = 1, 2, 4, 6, 9\) etc. and the powers of+-- \(w\) are \(\pm (k+2) = \pm 2, \pm 3, \pm 4, \ldots\) etc. The scheme is+-- illustrated by the following table:+-- +-- \[`\]+-- \[\begin{aligned}+-- \begin{array}{llll}+-- & \theta_1, \theta_2 & q^0 & (w^1 \pm w^{-1}) \\+-- k = 0 & \theta_3, \theta_4 & q^1 & (w^2 \pm w^{-2}) \\+-- k = 1 & \theta_1, \theta_2 & q^2 & (w^3 \pm w^{-3}) \\+-- k = 2 & \theta_3, \theta_4 & q^4 & (w^4 \pm w^{-4}) \\+-- k = 3 & \theta_1, \theta_2 & q^6 & (w^5 \pm w^{-5}) \\+-- k = 4 & \theta_3, \theta_4 & q^9 & (w^6 \pm w^{-6}) \\+-- k = 5 & \theta_1, \theta_2 & q^{12} & (w^7 \pm w^{-7}) \\+-- \end{array}+-- \end{aligned}\]+-- +-- For some integer \(N \ge 1\), the summation is stopped just before term+-- \(k = N\). Let \(Q = |q|\), \(W = \max(|w|,|w^{-1}|)\),+-- \(E = \lfloor (N+2)^2 / 4 \rfloor\) and+-- \(F = \lfloor (N+1)/2 \rfloor + 1\). The error of the zeroth derivative+-- can be bounded as+-- +-- \[`\]+-- \[2 Q^E W^{N+2} \left[ 1 + Q^F W + Q^{2F} W^2 + \ldots \right]+-- = \frac{2 Q^E W^{N+2}}{1 - Q^F W}\]+-- +-- provided that the denominator is positive (otherwise we set the error+-- bound to infinity). When /len/ is greater than 1, consider the+-- derivative of order /r/. The term of index /k/ and order /r/ picks up a+-- factor of magnitude \((k+2)^r\) from differentiation of \(w^{k+2}\) (it+-- also picks up a factor \(\pi^r\), but we omit this until we rescale the+-- coefficients at the end of the computation). Thus we have the error+-- bound+-- +-- \[`\]+-- \[2 Q^E W^{N+2} (N+2)^r \left[ 1 + Q^F W \frac{(N+3)^r}{(N+2)^r} + Q^{2F} W^2 \frac{(N+4)^r}{(N+2)^r} + \ldots \right]\]+-- +-- which by the inequality \((1 + m/(N+2))^r \le \exp(mr/(N+2))\) can be+-- bounded as+-- +-- \[`\]+-- \[\frac{2 Q^E W^{N+2} (N+2)^r}{1 - Q^F W \exp(r/(N+2))},\]+-- +-- again valid when the denominator is positive.+-- +-- To actually evaluate the series, we write the even cosine terms as+-- \(w^{2n} + w^{-2n}\), the odd cosine terms as+-- \(w (w^{2n} + w^{-2n-2})\), and the sine terms as+-- \(w (w^{2n} - w^{-2n-2})\). This way we only need even powers of \(w\)+-- and \(w^{-1}\). The implementation is not yet optimized for real \(z\),+-- in which case further work can be saved.+-- +-- This function does not permit aliasing between input and output+-- arguments.+foreign import ccall "acb_modular.h acb_modular_theta_sum"+ acb_modular_theta_sum :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_modular.h acb_modular_theta_const_sum_basecase"+ acb_modular_theta_const_sum_basecase :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_modular_theta_const_sum_rs/ /theta2/ /theta3/ /theta4/ /q/ /N/ /prec/ +-- +-- Computes the truncated theta constant sums+-- \(\theta_2 = \sum_{k(k+1) < N} q^{k(k+1)}\),+-- \(\theta_3 = \sum_{k^2 < N} q^{k^2}\),+-- \(\theta_4 = \sum_{k^2 < N} (-1)^k q^{k^2}\). The /basecase/ version+-- uses a short addition sequence. The /rs/ version uses rectangular+-- splitting. The algorithms are described in < [EHJ2016]>.+foreign import ccall "acb_modular.h acb_modular_theta_const_sum_rs"+ acb_modular_theta_const_sum_rs :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_modular_theta_const_sum/ /theta2/ /theta3/ /theta4/ /q/ /prec/ +-- +-- Computes the respective theta constants by direct summation (without+-- applying modular transformations). This function selects an appropriate+-- /N/, calls either @acb_modular_theta_const_sum_basecase@ or+-- @acb_modular_theta_const_sum_rs@ or depending on /N/, and adds a bound+-- for the truncation error.+foreign import ccall "acb_modular.h acb_modular_theta_const_sum"+ acb_modular_theta_const_sum :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_modular_theta_notransform/ /theta1/ /theta2/ /theta3/ /theta4/ /z/ /tau/ /prec/ +-- +-- Evaluates the Jacobi theta functions \(\theta_i(z,\tau)\),+-- \(i = 1, 2, 3, 4\) simultaneously. This function does not move \(\tau\)+-- to the fundamental domain. This is generally worse than+-- @acb_modular_theta@, but can be slightly better for moderate input.+foreign import ccall "acb_modular.h acb_modular_theta_notransform"+ acb_modular_theta_notransform :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_modular_theta/ /theta1/ /theta2/ /theta3/ /theta4/ /z/ /tau/ /prec/ +-- +-- Evaluates the Jacobi theta functions \(\theta_i(z,\tau)\),+-- \(i = 1, 2, 3, 4\) simultaneously. This function moves \(\tau\) to the+-- fundamental domain and then also reduces \(z\) modulo \(\tau\) before+-- calling @acb_modular_theta_sum@.+foreign import ccall "acb_modular.h acb_modular_theta"+ acb_modular_theta :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_modular.h acb_modular_theta_jet_notransform"+ acb_modular_theta_jet_notransform :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_modular_theta_jet/ /theta1/ /theta2/ /theta3/ /theta4/ /z/ /tau/ /len/ /prec/ +-- +-- Evaluates the Jacobi theta functions along with their derivatives with+-- respect to /z/, writing the first /len/ coefficients in the power series+-- \(\theta_i(z+x,\tau) \in \mathbb{C}[[x]]\) to each respective output+-- variable. The /notransform/ version does not move \(\tau\) to the+-- fundamental domain or reduce \(z\) during the computation.+foreign import ccall "acb_modular.h acb_modular_theta_jet"+ acb_modular_theta_jet :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_modular.h _acb_modular_theta_series"+ _acb_modular_theta_series :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_modular_theta_series/ /theta1/ /theta2/ /theta3/ /theta4/ /z/ /tau/ /len/ /prec/ +-- +-- Evaluates the respective Jacobi theta functions of the power series /z/,+-- truncated to length /len/. Either of the output variables can be /NULL/.+foreign import ccall "acb_modular.h acb_modular_theta_series"+ acb_modular_theta_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> CLong -> IO ()++-- Dedekind eta function -------------------------------------------------------++-- | /acb_modular_addseq_eta/ /exponents/ /aindex/ /bindex/ /num/ +-- +-- Constructs an addition sequence for the first /num/ generalized+-- pentagonal numbers (excluding zero), i.e. 1, 2, 5, 7, 12, 15, 22, 26,+-- 35, 40 etc.+foreign import ccall "acb_modular.h acb_modular_addseq_eta"+ acb_modular_addseq_eta :: Ptr CLong -> Ptr CLong -> Ptr CLong -> CLong -> IO ()++-- | /acb_modular_eta_sum/ /eta/ /q/ /prec/ +-- +-- Evaluates the Dedekind eta function without the leading 24th root, i.e.+-- +-- \[` \exp(-\pi i \tau/12) \eta(\tau) = \sum_{n=-\infty}^{\infty} (-1)^n q^{(3n^2-n)/2}\]+-- +-- given \(q = \exp(2 \pi i \tau)\), by summing the defining series.+-- +-- This function is intended for \(|q| \ll 1\). It can be called with any+-- \(q\), but will return useless intervals if convergence is not rapid.+-- For general evaluation of the eta function, the user should only call+-- this function after applying a suitable modular transformation.+-- +-- The series is evaluated using either a short addition sequence or+-- rectangular splitting, depending on the number of terms. The algorithms+-- are described in < [EHJ2016]>.+foreign import ccall "acb_modular.h acb_modular_eta_sum"+ acb_modular_eta_sum :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_modular_epsilon_arg/ /g/ +-- +-- Given \(g = (a, b; c, d)\), computes an integer \(R\) such that+-- \(\varepsilon(a,b,c,d) = \exp(\pi i R / 12)\) is the 24th root of unity+-- in the transformation formula for the Dedekind eta function,+-- +-- \[`\]+-- \[\eta\left(\frac{a\tau+b}{c\tau+d}\right) = \varepsilon (a,b,c,d)+-- \sqrt{c\tau+d} \eta(\tau).\]+foreign import ccall "acb_modular.h acb_modular_epsilon_arg"+ acb_modular_epsilon_arg :: Ptr CPSL2Z -> IO CInt++-- | /acb_modular_eta/ /r/ /tau/ /prec/ +-- +-- Computes the Dedekind eta function \(\eta(\tau)\) given \(\tau\) in the+-- upper half-plane. This function applies the functional equation to move+-- \(\tau\) to the fundamental domain before calling @acb_modular_eta_sum@.+foreign import ccall "acb_modular.h acb_modular_eta"+ acb_modular_eta :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- Modular forms ---------------------------------------------------------------++-- | /acb_modular_j/ /r/ /tau/ /prec/ +-- +-- Computes Klein\'s j-invariant \(j(\tau)\) given \(\tau\) in the upper+-- half-plane. The function is normalized so that \(j(i) = 1728\). We first+-- move \(\tau\) to the fundamental domain, which does not change the value+-- of the function. Then we use the formula+-- \(j(\tau) = 32 (\theta_2^8+\theta_3^8+\theta_4^8)^3 / (\theta_2 \theta_3 \theta_4)^8\)+-- where \(\theta_i = \theta_i(0,\tau)\).+foreign import ccall "acb_modular.h acb_modular_j"+ acb_modular_j :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_modular_lambda/ /r/ /tau/ /prec/ +-- +-- Computes the lambda function+-- \(\lambda(\tau) = \theta_2^4(0,\tau) / \theta_3^4(0,\tau)\), which is+-- invariant under modular transformations \((a, b; c, d)\) where \(a, d\)+-- are odd and \(b, c\) are even.+foreign import ccall "acb_modular.h acb_modular_lambda"+ acb_modular_lambda :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_modular_delta/ /r/ /tau/ /prec/ +-- +-- Computes the modular discriminant \(\Delta(\tau) = \eta(\tau)^{24}\),+-- which transforms as+-- +-- \[`\]+-- \[\Delta\left(\frac{a\tau+b}{c\tau+d}\right) = (c\tau+d)^{12} \Delta(\tau).\]+-- +-- The modular discriminant is sometimes defined with an extra factor+-- \((2\pi)^{12}\), which we omit in this implementation.+foreign import ccall "acb_modular.h acb_modular_delta"+ acb_modular_delta :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++-- | /acb_modular_eisenstein/ /r/ /tau/ /len/ /prec/ +-- +-- Computes simultaneously the first /len/ entries in the sequence of+-- Eisenstein series \(G_4(\tau), G_6(\tau), G_8(\tau), \ldots\), defined+-- by+-- +-- \[`\]+-- \[G_{2k}(\tau) = \sum_{m^2 + n^2 \ne 0} \frac{1}{(m+n\tau )^{2k}}\]+-- +-- and satisfying+-- +-- \[`\]+-- \[G_{2k} \left(\frac{a\tau+b}{c\tau+d}\right) = (c\tau+d)^{2k} G_{2k}(\tau).\]+-- +-- We first evaluate \(G_4(\tau)\) and \(G_6(\tau)\) on the fundamental+-- domain using theta functions, and then compute the Eisenstein series of+-- higher index using a recurrence relation.+foreign import ccall "acb_modular.h acb_modular_eisenstein"+ acb_modular_eisenstein :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- Elliptic integrals and functions --------------------------------------------++-- See the @acb_elliptic.h \<acb-elliptic>@ module for elliptic integrals+-- and functions. The following wrappers are available for backwards+-- compatibility.+--+foreign import ccall "acb_modular.h acb_modular_elliptic_k"+ acb_modular_elliptic_k :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_modular.h acb_modular_elliptic_k_cpx"+ acb_modular_elliptic_k_cpx :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_modular.h acb_modular_elliptic_e"+ acb_modular_elliptic_e :: Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_modular.h acb_modular_elliptic_p"+ acb_modular_elliptic_p :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_modular.h acb_modular_elliptic_p_zpx"+ acb_modular_elliptic_p_zpx :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- Class polynomials -----------------------------------------------------------++-- | /acb_modular_hilbert_class_poly/ /res/ /D/ +-- +-- Sets /res/ to the Hilbert class polynomial of discriminant /D/, defined+-- as+-- +-- \[`\]+-- \[H_D(x) = \prod_{(a,b,c)} \left(x - j\left(\frac{-b+\sqrt{D}}{2a}\right)\right)\]+-- +-- where \((a,b,c)\) ranges over the primitive reduced positive definite+-- binary quadratic forms of discriminant \(b^2 - 4ac = D\).+-- +-- The Hilbert class polynomial is only defined if \(D < 0\) and /D/ is+-- congruent to 0 or 1 mod 4. If some other value of /D/ is passed as+-- input, /res/ is set to the zero polynomial.+foreign import ccall "acb_modular.h acb_modular_hilbert_class_poly"+ acb_modular_hilbert_class_poly :: Ptr CFmpzPoly -> CLong -> IO ()+
+ src/Data/Number/Flint/Acb/Modular/Instances.hs view
@@ -0,0 +1,57 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+{-|+module : Data.Number.Flint.Acb.Modular.Instances+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Acb.Modular.Instances where++import System.IO.Unsafe++import Foreign.C.String+import Foreign.Marshal.Alloc (free)++import Data.Group++import Data.Number.Flint.Acb.Modular++instance Show PSL2Z where+ show x = unsafePerformIO $ do+ (_, cs) <- withPSL2Z x psl2z_get_str+ s <- peekCString cs+ free cs+ return s++instance Eq PSL2Z where+ (==) x y = snd $ snd $ unsafePerformIO $ do+ withPSL2Z x $ \x -> do+ withPSL2Z y $ \y -> do+ flag <- psl2z_equal x y+ return $ flag == 1+ +instance Monoid PSL2Z where+ mempty = unsafePerformIO $ do+ result <- newPSL2Z+ return result+ +instance Semigroup PSL2Z where+ (<>) x y = fst $ unsafePerformIO $ do+ withNewPSL2Z $ \result -> do + withPSL2Z x $ \x -> do+ withPSL2Z y $ \y -> do+ psl2z_mul result x y+ +instance Group PSL2Z where+ invert x = fst $ unsafePerformIO $ do+ withNewPSL2Z $ \result -> do+ withPSL2Z x $ \x -> do+ psl2z_inv result x++instance Show PSL2ZWord where+ show x = unsafePerformIO $ do+ (_, cs) <- withPSL2ZWord x psl2z_word_get_str_pretty+ s <- peekCString cs+ free cs+ return s
+ src/Data/Number/Flint/Acb/Poly.hs view
@@ -0,0 +1,16 @@+{-|+An @AcbPoly@ represents a polynomial over the complex numbers,+implemented as an array of coefficients of type @Acb@.++Most functions are provided in two versions: an underscore method which+operates directly on pre-allocated arrays of coefficients and generally+has some restrictions (such as requiring the lengths to be nonzero and+not supporting aliasing of the input and output arrays), and a+non-underscore method which performs automatic memory management and+handles degenerate cases.+-}+module Data.Number.Flint.Acb.Poly (+ module Data.Number.Flint.Acb.Poly.FFI+ ) where++import Data.Number.Flint.Acb.Poly.FFI
+ src/Data/Number/Flint/Acb/Poly/FFI.hsc view
@@ -0,0 +1,1839 @@+{-|+module : Data.Number.Flint.Acb.Poly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Acb.Poly.FFI (+ -- * Polynomials over the complex numbers+ -- * Types+ AcbPoly (..)+ , CAcbPoly (..)+ , newAcbPoly+ , newAcbPolyFromFmpzPoly+ , newAcbPolyFromFmpqPoly+ , withAcbPoly+ , withNewAcbPoly+ , withNewAcbPolyFromFmpzPoly+ , withNewAcbPolyFromFmpqPoly+ -- * Memory management+ , acb_poly_init+ , acb_poly_clear+ , acb_poly_fit_length+ , _acb_poly_set_length+ , _acb_poly_normalise+ , acb_poly_swap+ , acb_poly_allocated_bytes+ -- * Basic properties and manipulation+ , acb_poly_length+ , acb_poly_degree+ , acb_poly_is_zero+ , acb_poly_is_one+ , acb_poly_is_x+ , acb_poly_zero+ , acb_poly_one+ , acb_poly_set+ , acb_poly_set_round+ , acb_poly_set_trunc+ , acb_poly_set_trunc_round+ , acb_poly_set_coeff_si+ , acb_poly_set_coeff_acb+ , acb_poly_get_coeff_acb+ , _acb_poly_shift_right+ , acb_poly_shift_right+ , _acb_poly_shift_left+ , acb_poly_shift_left+ , acb_poly_truncate+ , acb_poly_valuation+ -- * Input and output+ , acb_poly_get_strd+ , acb_poly_printd+ , acb_poly_fprintd+ -- * Random generation+ , acb_poly_randtest+ -- * Comparisons+ , acb_poly_equal+ , acb_poly_contains+ , acb_poly_contains_fmpz_poly+ , acb_poly_contains_fmpq_poly+ , _acb_poly_overlaps+ , acb_poly_overlaps+ , acb_poly_get_unique_fmpz_poly+ , acb_poly_is_real+ -- * Conversions+ , acb_poly_set_fmpz_poly+ , acb_poly_set2_fmpz_poly+ , acb_poly_set_arb_poly+ , acb_poly_set2_arb_poly+ , acb_poly_set_fmpq_poly+ , acb_poly_set2_fmpq_poly+ , acb_poly_set_acb+ , acb_poly_set_si+ -- * Bounds+ , _acb_poly_majorant+ , acb_poly_majorant+ -- * Arithmetic+ , _acb_poly_add+ , acb_poly_add+ , acb_poly_add_si+ , _acb_poly_sub+ , acb_poly_sub+ , acb_poly_add_series+ , acb_poly_sub_series+ , acb_poly_neg+ , acb_poly_scalar_mul_2exp_si+ , acb_poly_scalar_mul+ , acb_poly_scalar_div+ , _acb_poly_mullow_classical+ , _acb_poly_mullow_transpose+ , _acb_poly_mullow_transpose_gauss+ , _acb_poly_mullow+ , acb_poly_mullow_classical+ , acb_poly_mullow_transpose+ , acb_poly_mullow_transpose_gauss+ , acb_poly_mullow+ , _acb_poly_mul+ , acb_poly_mul+ , _acb_poly_inv_series+ , acb_poly_inv_series+ , _acb_poly_div_series+ , acb_poly_div_series+ , _acb_poly_div+ , _acb_poly_rem+ , _acb_poly_divrem+ , acb_poly_divrem+ , _acb_poly_div_root+ -- * Composition+ , _acb_poly_taylor_shift+ , _acb_poly_compose+ , _acb_poly_compose_series+ , _acb_poly_revert_series_lagrange+ , acb_poly_revert_series_lagrange+ , _acb_poly_revert_series_newton+ , acb_poly_revert_series_newton+ , _acb_poly_revert_series_lagrange_fast+ , acb_poly_revert_series_lagrange_fast+ , _acb_poly_revert_series+ , acb_poly_revert_series+ -- * Evaluation+ , _acb_poly_evaluate_horner+ , acb_poly_evaluate_horner+ , _acb_poly_evaluate_rectangular+ , acb_poly_evaluate_rectangular+ , _acb_poly_evaluate+ , acb_poly_evaluate+ , _acb_poly_evaluate2_horner+ , acb_poly_evaluate2_horner+ , _acb_poly_evaluate2_rectangular+ , acb_poly_evaluate2_rectangular+ , _acb_poly_evaluate2+ , acb_poly_evaluate2+ -- * Product trees+ , _acb_poly_product_roots+ , acb_poly_product_roots+ , _acb_poly_tree_alloc+ , _acb_poly_tree_free+ , _acb_poly_tree_build+ -- * Multipoint evaluation+ , _acb_poly_evaluate_vec_iter+ , acb_poly_evaluate_vec_iter+ , _acb_poly_evaluate_vec_fast_precomp+ , _acb_poly_evaluate_vec_fast+ , acb_poly_evaluate_vec_fast+ -- * Interpolation+ , _acb_poly_interpolate_newton+ , acb_poly_interpolate_newton+ , _acb_poly_interpolate_barycentric+ , acb_poly_interpolate_barycentric+ , _acb_poly_interpolation_weights+ , _acb_poly_interpolate_fast_precomp+ , _acb_poly_interpolate_fast+ , acb_poly_interpolate_fast+ -- * Differentiation+ , _acb_poly_derivative+ , acb_poly_derivative+ , _acb_poly_nth_derivative+ , acb_poly_nth_derivative+ , _acb_poly_integral+ , acb_poly_integral+ -- * Transforms+ , _acb_poly_borel_transform+ , acb_poly_borel_transform+ , _acb_poly_inv_borel_transform+ , acb_poly_inv_borel_transform+ , _acb_poly_binomial_transform_basecase+ , acb_poly_binomial_transform_basecase+ , _acb_poly_binomial_transform_convolution+ , acb_poly_binomial_transform_convolution+ , _acb_poly_binomial_transform+ , acb_poly_binomial_transform+ , _acb_poly_graeffe_transform+ , acb_poly_graeffe_transform+ -- * Elementary functions+ , _acb_poly_pow_ui_trunc_binexp+ , acb_poly_pow_ui_trunc_binexp+ , _acb_poly_pow_ui+ , acb_poly_pow_ui+ , _acb_poly_pow_series+ , acb_poly_pow_series+ , _acb_poly_pow_acb_series+ , acb_poly_pow_acb_series+ , _acb_poly_sqrt_series+ , acb_poly_sqrt_series+ , _acb_poly_rsqrt_series+ , acb_poly_rsqrt_series+ , _acb_poly_log_series+ , acb_poly_log_series+ , _acb_poly_log1p_series+ , acb_poly_log1p_series+ , _acb_poly_atan_series+ , acb_poly_atan_series+ , _acb_poly_exp_series_basecase+ , acb_poly_exp_series_basecase+ , _acb_poly_exp_series+ , acb_poly_exp_series+ , _acb_poly_exp_pi_i_series+ , acb_poly_exp_pi_i_series+ , _acb_poly_sin_cos_series+ , _acb_poly_sin_series+ , acb_poly_sin_series+ , _acb_poly_cos_series+ , acb_poly_cos_series+ , _acb_poly_tan_series+ , acb_poly_tan_series+ , _acb_poly_sin_cos_pi_series+ , acb_poly_sin_cos_pi_series+ , _acb_poly_sin_pi_series+ , acb_poly_sin_pi_series+ , _acb_poly_cos_pi_series+ , acb_poly_cos_pi_series+ , _acb_poly_cot_pi_series+ , acb_poly_cot_pi_series+ , _acb_poly_sinh_cosh_series_basecase+ , acb_poly_sinh_cosh_series_basecase+ , _acb_poly_sinh_cosh_series_exponential+ , acb_poly_sinh_cosh_series_exponential+ , _acb_poly_sinh_cosh_series+ , acb_poly_sinh_cosh_series+ , _acb_poly_sinh_series+ , acb_poly_sinh_series+ , _acb_poly_cosh_series+ , acb_poly_cosh_series+ , _acb_poly_sinc_series+ , acb_poly_sinc_series+ -- * Lambert W function+ , _acb_poly_lambertw_series+ , acb_poly_lambertw_series+ -- * Gamma function+ , _acb_poly_gamma_series+ , acb_poly_gamma_series+ , _acb_poly_rgamma_series+ , acb_poly_rgamma_series+ , _acb_poly_lgamma_series+ , acb_poly_lgamma_series+ , _acb_poly_digamma_series+ , acb_poly_digamma_series+ , _acb_poly_rising_ui_series+ , acb_poly_rising_ui_series+ -- * Power sums+ , _acb_poly_powsum_series_naive+ , _acb_poly_powsum_series_naive_threaded+ , _acb_poly_powsum_one_series_sieved+ -- * Zeta function+ , _acb_poly_zeta_em_choose_param+ , _acb_poly_zeta_em_bound1+ , _acb_poly_zeta_em_bound+ , _acb_poly_zeta_em_tail_naive+ , _acb_poly_zeta_em_tail_bsplit+ , _acb_poly_zeta_em_sum+ , _acb_poly_zeta_cpx_series+ , _acb_poly_zeta_series+ , acb_poly_zeta_series+ -- * Other special functions+ , _acb_poly_polylog_cpx_small+ , _acb_poly_polylog_cpx_zeta+ , _acb_poly_polylog_cpx+ , _acb_poly_polylog_series+ , acb_poly_polylog_series+ , _acb_poly_erf_series+ , acb_poly_erf_series+ , _acb_poly_agm1_series+ , acb_poly_agm1_series+ , _acb_poly_elliptic_k_series+ , acb_poly_elliptic_k_series+ , _acb_poly_elliptic_p_series+ , acb_poly_elliptic_p_series+ -- * Root-finding+ , _acb_poly_root_bound_fujiwara+ , acb_poly_root_bound_fujiwara+ , _acb_poly_root_inclusion+ , _acb_poly_validate_roots+ , _acb_poly_refine_roots_durand_kerner+ , _acb_poly_find_roots+ , acb_poly_find_roots+ , _acb_poly_validate_real_roots+ , acb_poly_validate_real_roots+) where++-- Polynomials over the complex numbers ----------------------------------------++-- An @AcPoly@ represents a polynomial over the complex numbers,+-- implemented as an array of coefficients of type @acb_struct@.+--+-- Most functions are provided in two versions: an underscore method which+-- operates directly on pre-allocated arrays of coefficients and generally+-- has some restrictions (such as requiring the lengths to be nonzero and+-- not supporting aliasing of the input and output arrays), and a+-- non-underscore method which performs automatic memory management and+-- handles degenerate cases.+--++#include <flint/arb.h>+#include <flint/acb_poly.h>++import System.IO.Unsafe ( unsafePerformIO )++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr )+import Foreign.Marshal ( free )++import Foreign.Storable++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpq.Poly++import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.Types++import Data.Number.Flint.Acb+import Data.Number.Flint.Acb.Types++-- Types -----------------------------------------------------------------------++data AcbPoly = AcbPoly {-# UNPACK #-} !(ForeignPtr CAcbPoly)+type CAcbPoly = CFlint AcbPoly++-- | Createst a new `CAcbPoly` structure encapsulated in `AcbPoly`.+{-# INLINE newAcbPoly #-}+newAcbPoly = do+ p <- mallocForeignPtr+ withForeignPtr p acb_poly_init+ addForeignPtrFinalizer p_acb_poly_clear p+ return $ AcbPoly p++newAcbPolyFromFmpzPoly poly prec = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p -> do+ acb_poly_init p+ withFmpzPoly poly $ \poly -> acb_poly_set_fmpz_poly p poly prec+ addForeignPtrFinalizer p_acb_poly_clear p+ return $ AcbPoly p++newAcbPolyFromFmpqPoly poly prec = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p -> do+ acb_poly_init p+ withFmpqPoly poly $ \poly -> acb_poly_set_fmpq_poly p poly prec+ addForeignPtrFinalizer p_acb_poly_clear p+ return $ AcbPoly p+ +-- | Use `AcbPoly` in f.+{-# INLINE withAcbPoly #-}+withAcbPoly (AcbPoly p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (AcbPoly p,)++-- | Use new `AcbPoly` ptr in f.+{-# INLINE withNewAcbPoly #-}+withNewAcbPoly f = do+ p <- newAcbPoly+ withAcbPoly p f++withNewAcbPolyFromFmpzPoly poly prec f = do+ p <- newAcbPolyFromFmpzPoly poly prec+ withAcbPoly p f++withNewAcbPolyFromFmpqPoly poly prec f = do+ p <- newAcbPolyFromFmpqPoly poly prec+ withAcbPoly p f++instance Storable CAcbPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size acb_poly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment acb_poly_t}+ peek = error "CAcbPoly.peek: Not defined"+ poke = error "CAcbPoly.poke: Not defined"++-- Memory management -----------------------------------------------------------++-- | /acb_poly_init/ /poly/ +-- +-- Initializes the polynomial for use, setting it to the zero polynomial.+foreign import ccall "acb_poly.h acb_poly_init"+ acb_poly_init :: Ptr CAcbPoly -> IO ()++-- | /acb_poly_clear/ /poly/ +-- +-- Clears the polynomial, deallocating all coefficients and the coefficient+-- array.+foreign import ccall "acb_poly.h acb_poly_clear"+ acb_poly_clear :: Ptr CAcbPoly -> IO ()++foreign import ccall "acb_poly.h &acb_poly_clear"+ p_acb_poly_clear :: FunPtr (Ptr CAcbPoly -> IO ())++-- | /acb_poly_fit_length/ /poly/ /len/ +-- +-- Makes sure that the coefficient array of the polynomial contains at+-- least /len/ initialized coefficients.+foreign import ccall "acb_poly.h acb_poly_fit_length"+ acb_poly_fit_length :: Ptr CAcbPoly -> CLong -> IO ()++-- | /_acb_poly_set_length/ /poly/ /len/ +-- +-- Directly changes the length of the polynomial, without allocating or+-- deallocating coefficients. The value should not exceed the allocation+-- length.+foreign import ccall "acb_poly.h _acb_poly_set_length"+ _acb_poly_set_length :: Ptr CAcbPoly -> CLong -> IO ()++-- | /_acb_poly_normalise/ /poly/ +-- +-- Strips any trailing coefficients which are identical to zero.+foreign import ccall "acb_poly.h _acb_poly_normalise"+ _acb_poly_normalise :: Ptr CAcbPoly -> IO ()++-- | /acb_poly_swap/ /poly1/ /poly2/ +-- +-- Swaps /poly1/ and /poly2/ efficiently.+foreign import ccall "acb_poly.h acb_poly_swap"+ acb_poly_swap :: Ptr CAcbPoly -> Ptr CAcbPoly -> IO ()++-- | /acb_poly_allocated_bytes/ /x/ +-- +-- Returns the total number of bytes heap-allocated internally by this+-- object. The count excludes the size of the structure itself. Add+-- @sizeof(acb_poly_struct)@ to get the size of the object as a whole.+foreign import ccall "acb_poly.h acb_poly_allocated_bytes"+ acb_poly_allocated_bytes :: Ptr CAcbPoly -> IO CLong++-- Basic properties and manipulation -------------------------------------------++-- | /acb_poly_length/ /poly/ +-- +-- Returns the length of /poly/, i.e. zero if /poly/ is identically zero,+-- and otherwise one more than the index of the highest term that is not+-- identically zero.+foreign import ccall "acb_poly.h acb_poly_length"+ acb_poly_length :: Ptr CAcbPoly -> IO CLong++-- | /acb_poly_degree/ /poly/ +-- +-- Returns the degree of /poly/, defined as one less than its length. Note+-- that if one or several leading coefficients are balls containing zero,+-- this value can be larger than the true degree of the exact polynomial+-- represented by /poly/, so the return value of this function is+-- effectively an upper bound.+foreign import ccall "acb_poly.h acb_poly_degree"+ acb_poly_degree :: Ptr CAcbPoly -> IO CLong++foreign import ccall "acb_poly.h acb_poly_is_zero"+ acb_poly_is_zero :: Ptr CAcbPoly -> IO CInt++foreign import ccall "acb_poly.h acb_poly_is_one"+ acb_poly_is_one :: Ptr CAcbPoly -> IO CInt++-- | /acb_poly_is_x/ /poly/ +-- +-- Returns 1 if /poly/ is exactly the polynomial 0, 1 or /x/ respectively.+-- Returns 0 otherwise.+foreign import ccall "acb_poly.h acb_poly_is_x"+ acb_poly_is_x :: Ptr CAcbPoly -> IO CInt++-- | /acb_poly_zero/ /poly/ +-- +-- Sets /poly/ to the zero polynomial.+foreign import ccall "acb_poly.h acb_poly_zero"+ acb_poly_zero :: Ptr CAcbPoly -> IO ()++-- | /acb_poly_one/ /poly/ +-- +-- Sets /poly/ to the constant polynomial 1.+foreign import ccall "acb_poly.h acb_poly_one"+ acb_poly_one :: Ptr CAcbPoly -> IO ()++-- | /acb_poly_set/ /dest/ /src/ +-- +-- Sets /dest/ to a copy of /src/.+foreign import ccall "acb_poly.h acb_poly_set"+ acb_poly_set :: Ptr CAcbPoly -> Ptr CAcbPoly -> IO ()++-- | /acb_poly_set_round/ /dest/ /src/ /prec/ +-- +-- Sets /dest/ to a copy of /src/, rounded to /prec/ bits.+foreign import ccall "acb_poly.h acb_poly_set_round"+ acb_poly_set_round :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_set_trunc"+ acb_poly_set_trunc :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++-- | /acb_poly_set_trunc_round/ /dest/ /src/ /n/ /prec/ +-- +-- Sets /dest/ to a copy of /src/, truncated to length /n/ and rounded to+-- /prec/ bits.+foreign import ccall "acb_poly.h acb_poly_set_trunc_round"+ acb_poly_set_trunc_round :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_set_coeff_si"+ acb_poly_set_coeff_si :: Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_poly_set_coeff_acb/ /poly/ /n/ /c/ +-- +-- Sets the coefficient with index /n/ in /poly/ to the value /c/. We+-- require that /n/ is nonnegative.+foreign import ccall "acb_poly.h acb_poly_set_coeff_acb"+ acb_poly_set_coeff_acb :: Ptr CAcbPoly -> CLong -> Ptr CAcb -> IO ()++-- | /acb_poly_get_coeff_acb/ /v/ /poly/ /n/ +-- +-- Sets /v/ to the value of the coefficient with index /n/ in /poly/. We+-- require that /n/ is nonnegative.+foreign import ccall "acb_poly.h acb_poly_get_coeff_acb"+ acb_poly_get_coeff_acb :: Ptr CAcb -> Ptr CAcbPoly -> CLong -> IO ()+++++foreign import ccall "acb_poly.h _acb_poly_shift_right"+ _acb_poly_shift_right :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_shift_right/ /res/ /poly/ /n/ +-- +-- Sets /res/ to /poly/ divided by \(x^n\), throwing away the lower+-- coefficients. We require that /n/ is nonnegative.+foreign import ccall "acb_poly.h acb_poly_shift_right"+ acb_poly_shift_right :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_shift_left"+ _acb_poly_shift_left :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_shift_left/ /res/ /poly/ /n/ +-- +-- Sets /res/ to /poly/ multiplied by \(x^n\). We require that /n/ is+-- nonnegative.+foreign import ccall "acb_poly.h acb_poly_shift_left"+ acb_poly_shift_left :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++-- | /acb_poly_truncate/ /poly/ /n/ +-- +-- Truncates /poly/ to have length at most /n/, i.e. degree strictly+-- smaller than /n/. We require that /n/ is nonnegative.+foreign import ccall "acb_poly.h acb_poly_truncate"+ acb_poly_truncate :: Ptr CAcbPoly -> CLong -> IO ()++-- | /acb_poly_valuation/ /poly/ +-- +-- Returns the degree of the lowest term that is not exactly zero in+-- /poly/. Returns -1 if /poly/ is the zero polynomial.+foreign import ccall "acb_poly.h acb_poly_valuation"+ acb_poly_valuation :: Ptr CAcbPoly -> IO CLong++-- Input and output ------------------------------------------------------------++foreign import ccall "acb_poly.h acb_poly_get_strd"+ acb_poly_get_strd :: Ptr CAcbPoly -> CLong -> IO CString++-- | /acb_poly_printd/ /poly/ /digits/ +-- +-- Prints the polynomial as an array of coefficients, printing each+-- coefficient using /acb_printd/.+acb_poly_printd :: Ptr CAcbPoly -> CLong -> IO ()+acb_poly_printd poly digits = do+ cs <- acb_poly_get_strd poly digits+ s <- peekCString cs+ free cs+ putStr s++-- | /acb_poly_fprintd/ /file/ /poly/ /digits/ +-- +-- Prints the polynomial as an array of coefficients to the stream /file/,+-- printing each coefficient using /acb_fprintd/.+foreign import ccall "acb_poly.h acb_poly_fprintd"+ acb_poly_fprintd :: Ptr CFile -> Ptr CAcbPoly -> CLong -> IO ()++-- Random generation -----------------------------------------------------------++-- | /acb_poly_randtest/ /poly/ /state/ /len/ /prec/ /mag_bits/ +-- +-- Creates a random polynomial with length at most /len/.+foreign import ccall "acb_poly.h acb_poly_randtest"+ acb_poly_randtest :: Ptr CAcbPoly -> Ptr CFRandState -> CLong -> CLong -> CLong -> IO ()++-- Comparisons -----------------------------------------------------------------++-- | /acb_poly_equal/ /A/ /B/ +-- +-- Returns nonzero iff /A/ and /B/ are identical as interval polynomials.+foreign import ccall "acb_poly.h acb_poly_equal"+ acb_poly_equal :: Ptr CAcbPoly -> Ptr CAcbPoly -> IO CInt++foreign import ccall "acb_poly.h acb_poly_contains"+ acb_poly_contains :: Ptr CAcbPoly -> Ptr CAcbPoly -> IO CInt++foreign import ccall "acb_poly.h acb_poly_contains_fmpz_poly"+ acb_poly_contains_fmpz_poly :: Ptr CAcbPoly -> Ptr CFmpzPoly -> IO CInt++-- | /acb_poly_contains_fmpq_poly/ /poly1/ /poly2/ +-- +-- Returns nonzero iff /poly2/ is contained in /poly1/.+foreign import ccall "acb_poly.h acb_poly_contains_fmpq_poly"+ acb_poly_contains_fmpq_poly :: Ptr CAcbPoly -> Ptr CFmpqPoly -> IO CInt++foreign import ccall "acb_poly.h _acb_poly_overlaps"+ _acb_poly_overlaps :: Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO CInt++-- | /acb_poly_overlaps/ /poly1/ /poly2/ +-- +-- Returns nonzero iff /poly1/ overlaps with /poly2/. The underscore+-- function requires that /len1/ ist at least as large as /len2/.+foreign import ccall "acb_poly.h acb_poly_overlaps"+ acb_poly_overlaps :: Ptr CAcbPoly -> Ptr CAcbPoly -> IO CInt++-- | /acb_poly_get_unique_fmpz_poly/ /z/ /x/ +-- +-- If /x/ contains a unique integer polynomial, sets /z/ to that value and+-- returns nonzero. Otherwise (if /x/ represents no integers or more than+-- one integer), returns zero, possibly partially modifying /z/.+foreign import ccall "acb_poly.h acb_poly_get_unique_fmpz_poly"+ acb_poly_get_unique_fmpz_poly :: Ptr CFmpzPoly -> Ptr CAcbPoly -> IO CInt++-- | /acb_poly_is_real/ /poly/ +-- +-- Returns nonzero iff all coefficients in /poly/ have zero imaginary part.+foreign import ccall "acb_poly.h acb_poly_is_real"+ acb_poly_is_real :: Ptr CAcbPoly -> IO CInt++-- Conversions -----------------------------------------------------------------++foreign import ccall "acb_poly.h acb_poly_set_fmpz_poly"+ acb_poly_set_fmpz_poly :: Ptr CAcbPoly -> Ptr CFmpzPoly -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_set2_fmpz_poly"+ acb_poly_set2_fmpz_poly :: Ptr CAcbPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_set_arb_poly"+ acb_poly_set_arb_poly :: Ptr CAcbPoly -> Ptr CArbPoly -> IO ()++foreign import ccall "acb_poly.h acb_poly_set2_arb_poly"+ acb_poly_set2_arb_poly :: Ptr CAcbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> IO ()++foreign import ccall "acb_poly.h acb_poly_set_fmpq_poly"+ acb_poly_set_fmpq_poly :: Ptr CAcbPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /acb_poly_set2_fmpq_poly/ /poly/ /re/ /im/ /prec/ +-- +-- Sets /poly/ to the given real part /re/ plus the imaginary part /im/,+-- both rounded to /prec/ bits.+foreign import ccall "acb_poly.h acb_poly_set2_fmpq_poly"+ acb_poly_set2_fmpq_poly :: Ptr CAcbPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_set_acb"+ acb_poly_set_acb :: Ptr CAcbPoly -> Ptr CAcb -> IO ()++-- | /acb_poly_set_si/ /poly/ /src/ +-- +-- Sets /poly/ to /src/.+foreign import ccall "acb_poly.h acb_poly_set_si"+ acb_poly_set_si :: Ptr CAcbPoly -> CLong -> IO ()++-- Bounds ----------------------------------------------------------------------++foreign import ccall "acb_poly.h _acb_poly_majorant"+ _acb_poly_majorant :: Ptr CArb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_majorant/ /res/ /poly/ /prec/ +-- +-- Sets /res/ to an exact real polynomial whose coefficients are upper+-- bounds for the absolute values of the coefficients in /poly/, rounded to+-- /prec/ bits.+foreign import ccall "acb_poly.h acb_poly_majorant"+ acb_poly_majorant :: Ptr CArbPoly -> Ptr CAcbPoly -> CLong -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- | /_acb_poly_add/ /C/ /A/ /lenA/ /B/ /lenB/ /prec/ +-- +-- Sets /{C, max(lenA, lenB)}/ to the sum of /{A, lenA}/ and /{B, lenB}/.+-- Allows aliasing of the input and output operands.+foreign import ccall "acb_poly.h _acb_poly_add"+ _acb_poly_add :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_add"+ acb_poly_add :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++-- | /acb_poly_add_si/ /C/ /A/ /B/ /prec/ +-- +-- Sets /C/ to the sum of /A/ and /B/.+foreign import ccall "acb_poly.h acb_poly_add_si"+ acb_poly_add_si :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /_acb_poly_sub/ /C/ /A/ /lenA/ /B/ /lenB/ /prec/ +-- +-- Sets /{C, max(lenA, lenB)}/ to the difference of /{A, lenA}/ and /{B,+-- lenB}/. Allows aliasing of the input and output operands.+foreign import ccall "acb_poly.h _acb_poly_sub"+ _acb_poly_sub :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_sub/ /C/ /A/ /B/ /prec/ +-- +-- Sets /C/ to the difference of /A/ and /B/.+foreign import ccall "acb_poly.h acb_poly_sub"+ acb_poly_sub :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++-- | /acb_poly_add_series/ /C/ /A/ /B/ /len/ /prec/ +-- +-- Sets /C/ to the sum of /A/ and /B/, truncated to length /len/.+foreign import ccall "acb_poly.h acb_poly_add_series"+ acb_poly_add_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_poly_sub_series/ /C/ /A/ /B/ /len/ /prec/ +-- +-- Sets /C/ to the difference of /A/ and /B/, truncated to length /len/.+foreign import ccall "acb_poly.h acb_poly_sub_series"+ acb_poly_sub_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_poly_neg/ /C/ /A/ +-- +-- Sets /C/ to the negation of /A/.+foreign import ccall "acb_poly.h acb_poly_neg"+ acb_poly_neg :: Ptr CAcbPoly -> Ptr CAcbPoly -> IO ()++-- | /acb_poly_scalar_mul_2exp_si/ /C/ /A/ /c/ +-- +-- Sets /C/ to /A/ multiplied by \(2^c\).+foreign import ccall "acb_poly.h acb_poly_scalar_mul_2exp_si"+ acb_poly_scalar_mul_2exp_si :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++-- | /acb_poly_scalar_mul/ /C/ /A/ /c/ /prec/ +-- +-- Sets /C/ to /A/ multiplied by /c/.+foreign import ccall "acb_poly.h acb_poly_scalar_mul"+ acb_poly_scalar_mul :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> IO ()++-- | /acb_poly_scalar_div/ /C/ /A/ /c/ /prec/ +-- +-- Sets /C/ to /A/ divided by /c/.+foreign import ccall "acb_poly.h acb_poly_scalar_div"+ acb_poly_scalar_div :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_mullow_classical"+ _acb_poly_mullow_classical :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_mullow_transpose"+ _acb_poly_mullow_transpose :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_mullow_transpose_gauss"+ _acb_poly_mullow_transpose_gauss :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /_acb_poly_mullow/ /C/ /A/ /lenA/ /B/ /lenB/ /n/ /prec/ +-- +-- Sets /{C, n}/ to the product of /{A, lenA}/ and /{B, lenB}/, truncated+-- to length /n/. The output is not allowed to be aliased with either of+-- the inputs. We require \(\mathrm{lenA} \ge \mathrm{lenB} > 0\),+-- \(n > 0\), \(\mathrm{lenA} + \mathrm{lenB} - 1 \ge n\).+-- +-- The /classical/ version uses a plain loop.+-- +-- The /transpose/ version evaluates the product using four real polynomial+-- multiplications (via @_arb_poly_mullow@).+-- +-- The /transpose_gauss/ version evaluates the product using three real+-- polynomial multiplications. This is almost always faster than+-- /transpose/, but has worse numerical stability when the coefficients+-- vary in magnitude.+-- +-- The default function @_acb_poly_mullow@ automatically switches been+-- /classical/ and /transpose/ multiplication.+-- +-- If the input pointers are identical (and the lengths are the same), they+-- are assumed to represent the same polynomial, and its square is+-- computed.+foreign import ccall "acb_poly.h _acb_poly_mullow"+ _acb_poly_mullow :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_mullow_classical"+ acb_poly_mullow_classical :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_mullow_transpose"+ acb_poly_mullow_transpose :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_mullow_transpose_gauss"+ acb_poly_mullow_transpose_gauss :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /acb_poly_mullow/ /C/ /A/ /B/ /n/ /prec/ +-- +-- Sets /C/ to the product of /A/ and /B/, truncated to length /n/. If the+-- same variable is passed for /A/ and /B/, sets /C/ to the square of /A/+-- truncated to length /n/.+foreign import ccall "acb_poly.h acb_poly_mullow"+ acb_poly_mullow :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /_acb_poly_mul/ /C/ /A/ /lenA/ /B/ /lenB/ /prec/ +-- +-- Sets /{C, lenA + lenB - 1}/ to the product of /{A, lenA}/ and /{B,+-- lenB}/. The output is not allowed to be aliased with either of the+-- inputs. We require \(\mathrm{lenA} \ge \mathrm{lenB} > 0\). This+-- function is implemented as a simple wrapper for @_acb_poly_mullow@.+-- +-- If the input pointers are identical (and the lengths are the same), they+-- are assumed to represent the same polynomial, and its square is+-- computed.+foreign import ccall "acb_poly.h _acb_poly_mul"+ _acb_poly_mul :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_mul/ /C/ /A1/ /B2/ /prec/ +-- +-- Sets /C/ to the product of /A/ and /B/. If the same variable is passed+-- for /A/ and /B/, sets /C/ to the square of /A/.+foreign import ccall "acb_poly.h acb_poly_mul"+ acb_poly_mul :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++-- | /_acb_poly_inv_series/ /Qinv/ /Q/ /Qlen/ /len/ /prec/ +-- +-- Sets /{Qinv, len}/ to the power series inverse of /{Q, Qlen}/. Uses+-- Newton iteration.+foreign import ccall "acb_poly.h _acb_poly_inv_series"+ _acb_poly_inv_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_inv_series/ /Qinv/ /Q/ /n/ /prec/ +-- +-- Sets /Qinv/ to the power series inverse of /Q/.+foreign import ccall "acb_poly.h acb_poly_inv_series"+ acb_poly_inv_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /_acb_poly_div_series/ /Q/ /A/ /Alen/ /B/ /Blen/ /n/ /prec/ +-- +-- Sets /{Q, n}/ to the power series quotient of /{A, Alen}/ by /{B,+-- Blen}/. Uses Newton iteration followed by multiplication.+foreign import ccall "acb_poly.h _acb_poly_div_series"+ _acb_poly_div_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_div_series/ /Q/ /A/ /B/ /n/ /prec/ +-- +-- Sets /Q/ to the power series quotient /A/ divided by /B/, truncated to+-- length /n/.+foreign import ccall "acb_poly.h acb_poly_div_series"+ acb_poly_div_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_div"+ _acb_poly_div :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_rem"+ _acb_poly_rem :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_divrem"+ _acb_poly_divrem :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_divrem/ /Q/ /R/ /A/ /B/ /prec/ +-- +-- Performs polynomial division with remainder, computing a quotient \(Q\)+-- and a remainder \(R\) such that \(A = BQ + R\). The implementation+-- reverses the inputs and performs power series division.+-- +-- If the leading coefficient of \(B\) contains zero (or if \(B\) is+-- identically zero), returns 0 indicating failure without modifying the+-- outputs. Otherwise returns nonzero.+foreign import ccall "acb_poly.h acb_poly_divrem"+ acb_poly_divrem :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO CInt++-- | /_acb_poly_div_root/ /Q/ /R/ /A/ /len/ /c/ /prec/ +-- +-- Divides \(A\) by the polynomial \(x - c\), computing the quotient \(Q\)+-- as well as the remainder \(R = f(c)\).+foreign import ccall "acb_poly.h _acb_poly_div_root"+ _acb_poly_div_root :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++-- Composition -----------------------------------------------------------------++-- | /_acb_poly_taylor_shift/ /g/ /c/ /n/ /prec/ +-- +-- Sets /g/ to the Taylor shift \(f(x+c)\). The underscore methods act+-- in-place on /g/ = /f/ which has length /n/.+foreign import ccall "acb_poly.h _acb_poly_taylor_shift"+ _acb_poly_taylor_shift :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /_acb_poly_compose/ /res/ /poly1/ /len1/ /poly2/ /len2/ /prec/ +-- +-- Sets /res/ to the composition \(h(x) = f(g(x))\) where \(f\) is given by+-- /poly1/ and \(g\) is given by /poly2/. The underscore method does not+-- support aliasing of the output with either input polynomial.+foreign import ccall "acb_poly.h _acb_poly_compose"+ _acb_poly_compose :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /_acb_poly_compose_series/ /res/ /poly1/ /len1/ /poly2/ /len2/ /n/ /prec/ +-- +-- Sets /res/ to the power series composition \(h(x) = f(g(x))\) truncated+-- to order \(O(x^n)\) where \(f\) is given by /poly1/ and \(g\) is given+-- by /poly2/. Wraps @_gr_poly_compose_series@ which chooses automatically+-- between various algorithms.+-- +-- We require that the constant term in \(g(x)\) is exactly zero. The+-- underscore method does not support aliasing of the output with either+-- input polynomial.+foreign import ccall "acb_poly.h _acb_poly_compose_series"+ _acb_poly_compose_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_revert_series_lagrange"+ _acb_poly_revert_series_lagrange :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_revert_series_lagrange"+ acb_poly_revert_series_lagrange :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_revert_series_newton"+ _acb_poly_revert_series_newton :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_revert_series_newton"+ acb_poly_revert_series_newton :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_revert_series_lagrange_fast"+ _acb_poly_revert_series_lagrange_fast :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_revert_series_lagrange_fast"+ acb_poly_revert_series_lagrange_fast :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_revert_series"+ _acb_poly_revert_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_revert_series/ /h/ /f/ /n/ /prec/ +-- +-- Sets \(h\) to the power series reversion of \(f\), i.e. the expansion of+-- the compositional inverse function \(f^{-1}(x)\), truncated to order+-- \(O(x^n)\), using respectively Lagrange inversion, Newton iteration,+-- fast Lagrange inversion, and a default algorithm choice.+-- +-- We require that the constant term in \(f\) is exactly zero and that the+-- linear term is nonzero. The underscore methods assume that /flen/ is at+-- least 2, and do not support aliasing.+foreign import ccall "acb_poly.h acb_poly_revert_series"+ acb_poly_revert_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- Evaluation ------------------------------------------------------------------++foreign import ccall "acb_poly.h _acb_poly_evaluate_horner"+ _acb_poly_evaluate_horner :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_evaluate_horner"+ acb_poly_evaluate_horner :: Ptr CAcb -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_evaluate_rectangular"+ _acb_poly_evaluate_rectangular :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_evaluate_rectangular"+ acb_poly_evaluate_rectangular :: Ptr CAcb -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_evaluate"+ _acb_poly_evaluate :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++-- | /acb_poly_evaluate/ /y/ /f/ /x/ /prec/ +-- +-- Sets \(y = f(x)\), evaluated respectively using Horner\'s rule,+-- rectangular splitting, and an automatic algorithm choice.+foreign import ccall "acb_poly.h acb_poly_evaluate"+ acb_poly_evaluate :: Ptr CAcb -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_evaluate2_horner"+ _acb_poly_evaluate2_horner :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_evaluate2_horner"+ acb_poly_evaluate2_horner :: Ptr CAcb -> Ptr CAcb -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_evaluate2_rectangular"+ _acb_poly_evaluate2_rectangular :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_evaluate2_rectangular"+ acb_poly_evaluate2_rectangular :: Ptr CAcb -> Ptr CAcb -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_evaluate2"+ _acb_poly_evaluate2 :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> IO ()++-- | /acb_poly_evaluate2/ /y/ /z/ /f/ /x/ /prec/ +-- +-- Sets \(y = f(x), z = f'(x)\), evaluated respectively using Horner\'s+-- rule, rectangular splitting, and an automatic algorithm choice.+-- +-- When Horner\'s rule is used, the only advantage of evaluating the+-- function and its derivative simultaneously is that one does not have to+-- generate the derivative polynomial explicitly. With the rectangular+-- splitting algorithm, the powers can be reused, making simultaneous+-- evaluation slightly faster.+foreign import ccall "acb_poly.h acb_poly_evaluate2"+ acb_poly_evaluate2 :: Ptr CAcb -> Ptr CAcb -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> IO ()++-- Product trees ---------------------------------------------------------------++foreign import ccall "acb_poly.h _acb_poly_product_roots"+ _acb_poly_product_roots :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_product_roots/ /poly/ /xs/ /n/ /prec/ +-- +-- Generates the polynomial \((x-x_0)(x-x_1)\cdots(x-x_{n-1})\).+foreign import ccall "acb_poly.h acb_poly_product_roots"+ acb_poly_product_roots :: Ptr CAcbPoly -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /_acb_poly_tree_alloc/ /len/ +-- +-- Returns an initialized data structured capable of representing a+-- remainder tree (product tree) of /len/ roots.+foreign import ccall "acb_poly.h _acb_poly_tree_alloc"+ _acb_poly_tree_alloc :: CLong -> IO (Ptr (Ptr CAcb))++-- | /_acb_poly_tree_free/ /tree/ /len/ +-- +-- Deallocates a tree structure as allocated using /_acb_poly_tree_alloc/.+foreign import ccall "acb_poly.h _acb_poly_tree_free"+ _acb_poly_tree_free :: Ptr (Ptr CAcb) -> CLong -> IO ()++-- | /_acb_poly_tree_build/ /tree/ /roots/ /len/ /prec/ +-- +-- Constructs a product tree from a given array of /len/ roots. The tree+-- structure must be pre-allocated to the specified length using+-- @_acb_poly_tree_alloc@.+foreign import ccall "acb_poly.h _acb_poly_tree_build"+ _acb_poly_tree_build :: Ptr (Ptr CAcb) -> Ptr CAcb -> CLong -> CLong -> IO ()++-- Multipoint evaluation -------------------------------------------------------++foreign import ccall "acb_poly.h _acb_poly_evaluate_vec_iter"+ _acb_poly_evaluate_vec_iter :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_evaluate_vec_iter/ /ys/ /poly/ /xs/ /n/ /prec/ +-- +-- Evaluates the polynomial simultaneously at /n/ given points, calling+-- @_acb_poly_evaluate@ repeatedly.+foreign import ccall "acb_poly.h acb_poly_evaluate_vec_iter"+ acb_poly_evaluate_vec_iter :: Ptr CAcb -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_evaluate_vec_fast_precomp"+ _acb_poly_evaluate_vec_fast_precomp :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr (Ptr CAcb) -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_evaluate_vec_fast"+ _acb_poly_evaluate_vec_fast :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_evaluate_vec_fast/ /ys/ /poly/ /xs/ /n/ /prec/ +-- +-- Evaluates the polynomial simultaneously at /n/ given points, using fast+-- multipoint evaluation.+foreign import ccall "acb_poly.h acb_poly_evaluate_vec_fast"+ acb_poly_evaluate_vec_fast :: Ptr CAcb -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> CLong -> IO ()++-- Interpolation ---------------------------------------------------------------++foreign import ccall "acb_poly.h _acb_poly_interpolate_newton"+ _acb_poly_interpolate_newton :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_interpolate_newton/ /poly/ /xs/ /ys/ /n/ /prec/ +-- +-- Recovers the unique polynomial of length at most /n/ that interpolates+-- the given /x/ and /y/ values. This implementation first interpolates in+-- the Newton basis and then converts back to the monomial basis.+foreign import ccall "acb_poly.h acb_poly_interpolate_newton"+ acb_poly_interpolate_newton :: Ptr CAcbPoly -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_interpolate_barycentric"+ _acb_poly_interpolate_barycentric :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_interpolate_barycentric/ /poly/ /xs/ /ys/ /n/ /prec/ +-- +-- Recovers the unique polynomial of length at most /n/ that interpolates+-- the given /x/ and /y/ values. This implementation uses the barycentric+-- form of Lagrange interpolation.+foreign import ccall "acb_poly.h acb_poly_interpolate_barycentric"+ acb_poly_interpolate_barycentric :: Ptr CAcbPoly -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_interpolation_weights"+ _acb_poly_interpolation_weights :: Ptr CAcb -> Ptr (Ptr CAcb) -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_interpolate_fast_precomp"+ _acb_poly_interpolate_fast_precomp :: Ptr CAcb -> Ptr CAcb -> Ptr (Ptr CAcb) -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_interpolate_fast"+ _acb_poly_interpolate_fast :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_interpolate_fast/ /poly/ /xs/ /ys/ /n/ /prec/ +-- +-- Recovers the unique polynomial of length at most /n/ that interpolates+-- the given /x/ and /y/ values, using fast Lagrange interpolation. The+-- precomp function takes a precomputed product tree over the /x/ values+-- and a vector of interpolation weights as additional inputs.+foreign import ccall "acb_poly.h acb_poly_interpolate_fast"+ acb_poly_interpolate_fast :: Ptr CAcbPoly -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- Differentiation -------------------------------------------------------------++-- | /_acb_poly_derivative/ /res/ /poly/ /len/ /prec/ +-- +-- Sets /{res, len - 1}/ to the derivative of /{poly, len}/. Allows+-- aliasing of the input and output.+foreign import ccall "acb_poly.h _acb_poly_derivative"+ _acb_poly_derivative :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_derivative/ /res/ /poly/ /prec/ +-- +-- Sets /res/ to the derivative of /poly/.+foreign import ccall "acb_poly.h acb_poly_derivative"+ acb_poly_derivative :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++-- | /_acb_poly_nth_derivative/ /res/ /poly/ /n/ /len/ /prec/ +-- +-- Sets /{res, len - n}/ to the nth derivative of /{poly, len}/. Does+-- nothing if /len \<= n/. Allows aliasing of the input and output.+foreign import ccall "acb_poly.h _acb_poly_nth_derivative"+ _acb_poly_nth_derivative :: Ptr CAcb -> Ptr CAcb -> CULong -> CLong -> CLong -> IO ()++-- | /acb_poly_nth_derivative/ /res/ /poly/ /n/ /prec/ +-- +-- Sets /res/ to the nth derivative of /poly/.+foreign import ccall "acb_poly.h acb_poly_nth_derivative"+ acb_poly_nth_derivative :: Ptr CAcbPoly -> Ptr CAcbPoly -> CULong -> CLong -> IO ()++-- | /_acb_poly_integral/ /res/ /poly/ /len/ /prec/ +-- +-- Sets /{res, len}/ to the integral of /{poly, len - 1}/. Allows aliasing+-- of the input and output.+foreign import ccall "acb_poly.h _acb_poly_integral"+ _acb_poly_integral :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_integral/ /res/ /poly/ /prec/ +-- +-- Sets /res/ to the integral of /poly/.+foreign import ccall "acb_poly.h acb_poly_integral"+ acb_poly_integral :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++-- Transforms ------------------------------------------------------------------++foreign import ccall "acb_poly.h _acb_poly_borel_transform"+ _acb_poly_borel_transform :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_borel_transform/ /res/ /poly/ /prec/ +-- +-- Computes the Borel transform of the input polynomial, mapping+-- \(\sum_k a_k x^k\) to \(\sum_k (a_k / k!) x^k\). The underscore method+-- allows aliasing.+foreign import ccall "acb_poly.h acb_poly_borel_transform"+ acb_poly_borel_transform :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_inv_borel_transform"+ _acb_poly_inv_borel_transform :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_inv_borel_transform/ /res/ /poly/ /prec/ +-- +-- Computes the inverse Borel transform of the input polynomial, mapping+-- \(\sum_k a_k x^k\) to \(\sum_k a_k k! x^k\). The underscore method+-- allows aliasing.+foreign import ccall "acb_poly.h acb_poly_inv_borel_transform"+ acb_poly_inv_borel_transform :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_binomial_transform_basecase"+ _acb_poly_binomial_transform_basecase :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_binomial_transform_basecase"+ acb_poly_binomial_transform_basecase :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_binomial_transform_convolution"+ _acb_poly_binomial_transform_convolution :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_binomial_transform_convolution"+ acb_poly_binomial_transform_convolution :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_binomial_transform"+ _acb_poly_binomial_transform :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_binomial_transform/ /b/ /a/ /len/ /prec/ +-- +-- Computes the binomial transform of the input polynomial, truncating the+-- output to length /len/. See @arb_poly_binomial_transform@ for details.+-- +-- The underscore methods do not support aliasing, and assume that the+-- lengths are nonzero.+foreign import ccall "acb_poly.h acb_poly_binomial_transform"+ acb_poly_binomial_transform :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_graeffe_transform"+ _acb_poly_graeffe_transform :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_graeffe_transform/ /b/ /a/ /prec/ +-- +-- Computes the Graeffe transform of input polynomial, which is of length+-- /len/. See @arb_poly_graeffe_transform@ for details.+-- +-- The underscore method assumes that /a/ and /b/ are initialized, /a/ is+-- of length /len/, and /b/ is of length at least /len/. Both methods allow+-- aliasing.+foreign import ccall "acb_poly.h acb_poly_graeffe_transform"+ acb_poly_graeffe_transform :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> IO ()++-- Elementary functions --------------------------------------------------------++-- | /_acb_poly_pow_ui_trunc_binexp/ /res/ /f/ /flen/ /exp/ /len/ /prec/ +-- +-- Sets /{res, len}/ to /{f, flen}/ raised to the power /exp/, truncated to+-- length /len/. Requires that /len/ is no longer than the length of the+-- power as computed without truncation (i.e. no zero-padding is+-- performed). Does not support aliasing of the input and output, and+-- requires that /flen/ and /len/ are positive. Uses binary exponentiation.+foreign import ccall "acb_poly.h _acb_poly_pow_ui_trunc_binexp"+ _acb_poly_pow_ui_trunc_binexp :: Ptr CAcb -> Ptr CAcb -> CLong -> CULong -> CLong -> CLong -> IO ()++-- | /acb_poly_pow_ui_trunc_binexp/ /res/ /poly/ /exp/ /len/ /prec/ +-- +-- Sets /res/ to /poly/ raised to the power /exp/, truncated to length+-- /len/. Uses binary exponentiation.+foreign import ccall "acb_poly.h acb_poly_pow_ui_trunc_binexp"+ acb_poly_pow_ui_trunc_binexp :: Ptr CAcbPoly -> Ptr CAcbPoly -> CULong -> CLong -> CLong -> IO ()++-- | /_acb_poly_pow_ui/ /res/ /f/ /flen/ /exp/ /prec/ +-- +-- Sets /res/ to /{f, flen}/ raised to the power /exp/. Does not support+-- aliasing of the input and output, and requires that /flen/ is positive.+foreign import ccall "acb_poly.h _acb_poly_pow_ui"+ _acb_poly_pow_ui :: Ptr CAcb -> Ptr CAcb -> CLong -> CULong -> CLong -> IO ()++-- | /acb_poly_pow_ui/ /res/ /poly/ /exp/ /prec/ +-- +-- Sets /res/ to /poly/ raised to the power /exp/.+foreign import ccall "acb_poly.h acb_poly_pow_ui"+ acb_poly_pow_ui :: Ptr CAcbPoly -> Ptr CAcbPoly -> CULong -> CLong -> IO ()++-- | /_acb_poly_pow_series/ /h/ /f/ /flen/ /g/ /glen/ /len/ /prec/ +-- +-- Sets /{h, len}/ to the power series+-- \(f(x)^{g(x)} = \exp(g(x) \log f(x))\) truncated to length /len/. This+-- function detects special cases such as /g/ being an exact small integer+-- or \(\pm 1/2\), and computes such powers more efficiently. This function+-- does not support aliasing of the output with either of the input+-- operands. It requires that all lengths are positive, and assumes that+-- /flen/ and /glen/ do not exceed /len/.+foreign import ccall "acb_poly.h _acb_poly_pow_series"+ _acb_poly_pow_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_pow_series/ /h/ /f/ /g/ /len/ /prec/ +-- +-- Sets /h/ to the power series \(f(x)^{g(x)} = \exp(g(x) \log f(x))\)+-- truncated to length /len/. This function detects special cases such as+-- /g/ being an exact small integer or \(\pm 1/2\), and computes such+-- powers more efficiently.+foreign import ccall "acb_poly.h acb_poly_pow_series"+ acb_poly_pow_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /_acb_poly_pow_acb_series/ /h/ /f/ /flen/ /g/ /len/ /prec/ +-- +-- Sets /{h, len}/ to the power series \(f(x)^g = \exp(g \log f(x))\)+-- truncated to length /len/. This function detects special cases such as+-- /g/ being an exact small integer or \(\pm 1/2\), and computes such+-- powers more efficiently. This function does not support aliasing of the+-- output with either of the input operands. It requires that all lengths+-- are positive, and assumes that /flen/ does not exceed /len/.+foreign import ccall "acb_poly.h _acb_poly_pow_acb_series"+ _acb_poly_pow_acb_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_pow_acb_series/ /h/ /f/ /g/ /len/ /prec/ +-- +-- Sets /h/ to the power series \(f(x)^g = \exp(g \log f(x))\) truncated to+-- length /len/.+foreign import ccall "acb_poly.h acb_poly_pow_acb_series"+ acb_poly_pow_acb_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_sqrt_series"+ _acb_poly_sqrt_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_sqrt_series/ /g/ /h/ /n/ /prec/ +-- +-- Sets /g/ to the power series square root of /h/, truncated to length+-- /n/. Uses division-free Newton iteration for the reciprocal square root,+-- followed by a multiplication.+-- +-- The underscore method does not support aliasing of the input and output+-- arrays. It requires that /hlen/ and /n/ are greater than zero.+foreign import ccall "acb_poly.h acb_poly_sqrt_series"+ acb_poly_sqrt_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_rsqrt_series"+ _acb_poly_rsqrt_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_rsqrt_series/ /g/ /h/ /n/ /prec/ +-- +-- Sets /g/ to the reciprocal power series square root of /h/, truncated to+-- length /n/. Uses division-free Newton iteration.+-- +-- The underscore method does not support aliasing of the input and output+-- arrays. It requires that /hlen/ and /n/ are greater than zero.+foreign import ccall "acb_poly.h acb_poly_rsqrt_series"+ acb_poly_rsqrt_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_log_series"+ _acb_poly_log_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_log_series/ /res/ /f/ /n/ /prec/ +-- +-- Sets /res/ to the power series logarithm of /f/, truncated to length+-- /n/. Uses the formula \(\log(f(x)) = \int f'(x) / f(x) dx\), adding the+-- logarithm of the constant term in /f/ as the constant of integration.+-- +-- The underscore method supports aliasing of the input and output arrays.+-- It requires that /flen/ and /n/ are greater than zero.+foreign import ccall "acb_poly.h acb_poly_log_series"+ acb_poly_log_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_log1p_series"+ _acb_poly_log1p_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_log1p_series/ /res/ /f/ /n/ /prec/ +-- +-- Computes the power series \(\log(1+f)\), with better accuracy when the+-- constant term of /f/ is small.+foreign import ccall "acb_poly.h acb_poly_log1p_series"+ acb_poly_log1p_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_atan_series"+ _acb_poly_atan_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_atan_series/ /res/ /f/ /n/ /prec/ +-- +-- Sets /res/ the power series inverse tangent of /f/, truncated to length+-- /n/.+-- +-- Uses the formula+-- +-- \[`\]+-- \[\tan^{-1}(f(x)) = \int f'(x) / (1+f(x)^2) dx,\]+-- +-- adding the function of the constant term in /f/ as the constant of+-- integration.+-- +-- The underscore method supports aliasing of the input and output arrays.+-- It requires that /flen/ and /n/ are greater than zero.+foreign import ccall "acb_poly.h acb_poly_atan_series"+ acb_poly_atan_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_exp_series_basecase"+ _acb_poly_exp_series_basecase :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_exp_series_basecase"+ acb_poly_exp_series_basecase :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_exp_series"+ _acb_poly_exp_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_exp_series/ /f/ /h/ /n/ /prec/ +-- +-- Sets \(f\) to the power series exponential of \(h\), truncated to length+-- \(n\).+-- +-- The basecase version uses a simple recurrence for the coefficients,+-- requiring \(O(nm)\) operations where \(m\) is the length of \(h\).+-- +-- The main implementation uses Newton iteration, starting from a small+-- number of terms given by the basecase algorithm. The complexity is+-- \(O(M(n))\). Redundant operations in the Newton iteration are avoided by+-- using the scheme described in < [HZ2004]>.+-- +-- The underscore methods support aliasing and allow the input to be+-- shorter than the output, but require the lengths to be nonzero.+foreign import ccall "acb_poly.h acb_poly_exp_series"+ acb_poly_exp_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_exp_pi_i_series"+ _acb_poly_exp_pi_i_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_exp_pi_i_series/ /f/ /h/ /n/ /prec/ +-- +-- Sets /f/ to the power series \(\exp(\pi i h)\) truncated to length /n/.+-- The underscore method supports aliasing and allows the input to be+-- shorter than the output, but requires the lengths to be nonzero.+foreign import ccall "acb_poly.h acb_poly_exp_pi_i_series"+ acb_poly_exp_pi_i_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- | /_acb_poly_sin_cos_series/ /s/ /c/ /h/ /hlen/ /n/ /prec/ +-- +-- Sets /s/ and /c/ to the power series sine and cosine of /h/, computed+-- simultaneously. The underscore method supports aliasing and requires the+-- lengths to be nonzero.+foreign import ccall "acb_poly.h _acb_poly_sin_cos_series"+ _acb_poly_sin_cos_series :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_sin_series"+ _acb_poly_sin_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_sin_series"+ acb_poly_sin_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_cos_series"+ _acb_poly_cos_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_cos_series/ /c/ /h/ /n/ /prec/ +-- +-- Respectively evaluates the power series sine or cosine. These functions+-- simply wrap @_acb_poly_sin_cos_series@. The underscore methods support+-- aliasing and require the lengths to be nonzero.+foreign import ccall "acb_poly.h acb_poly_cos_series"+ acb_poly_cos_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_tan_series"+ _acb_poly_tan_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_tan_series/ /g/ /h/ /n/ /prec/ +-- +-- Sets /g/ to the power series tangent of /h/.+-- +-- For small /n/ takes the quotient of the sine and cosine as computed+-- using the basecase algorithm. For large /n/, uses Newton iteration to+-- invert the inverse tangent series. The complexity is \(O(M(n))\).+-- +-- The underscore version does not support aliasing, and requires the+-- lengths to be nonzero.+foreign import ccall "acb_poly.h acb_poly_tan_series"+ acb_poly_tan_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_sin_cos_pi_series"+ _acb_poly_sin_cos_pi_series :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_sin_cos_pi_series"+ acb_poly_sin_cos_pi_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_sin_pi_series"+ _acb_poly_sin_pi_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_sin_pi_series"+ acb_poly_sin_pi_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_cos_pi_series"+ _acb_poly_cos_pi_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_cos_pi_series"+ acb_poly_cos_pi_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_cot_pi_series"+ _acb_poly_cot_pi_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_cot_pi_series/ /c/ /h/ /n/ /prec/ +-- +-- Compute the respective trigonometric functions of the input multiplied+-- by \(\pi\).+foreign import ccall "acb_poly.h acb_poly_cot_pi_series"+ acb_poly_cot_pi_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_sinh_cosh_series_basecase"+ _acb_poly_sinh_cosh_series_basecase :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_sinh_cosh_series_basecase"+ acb_poly_sinh_cosh_series_basecase :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_sinh_cosh_series_exponential"+ _acb_poly_sinh_cosh_series_exponential :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_sinh_cosh_series_exponential"+ acb_poly_sinh_cosh_series_exponential :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_sinh_cosh_series"+ _acb_poly_sinh_cosh_series :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_sinh_cosh_series"+ acb_poly_sinh_cosh_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_sinh_series"+ _acb_poly_sinh_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_sinh_series"+ acb_poly_sinh_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_cosh_series"+ _acb_poly_cosh_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_cosh_series/ /c/ /h/ /n/ /prec/ +-- +-- Sets /s/ and /c/ respectively to the hyperbolic sine and cosine of the+-- power series /h/, truncated to length /n/.+-- +-- The implementations mirror those for sine and cosine, except that the+-- /exponential/ version computes both functions using the exponential+-- function instead of the hyperbolic tangent.+foreign import ccall "acb_poly.h acb_poly_cosh_series"+ acb_poly_cosh_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_sinc_series"+ _acb_poly_sinc_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_sinc_series/ /s/ /h/ /n/ /prec/ +-- +-- Sets /s/ to the sinc function of the power series /h/, truncated to+-- length /n/.+foreign import ccall "acb_poly.h acb_poly_sinc_series"+ acb_poly_sinc_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- Lambert W function ----------------------------------------------------------++foreign import ccall "acb_poly.h _acb_poly_lambertw_series"+ _acb_poly_lambertw_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CFmpz -> CInt -> CLong -> CLong -> IO ()++-- | /acb_poly_lambertw_series/ /res/ /z/ /k/ /flags/ /len/ /prec/ +-- +-- Sets /res/ to branch /k/ of the Lambert W function of the power series+-- /z/. The argument /flags/ is reserved for future use. The underscore+-- method allows aliasing, but assumes that the lengths are nonzero.+foreign import ccall "acb_poly.h acb_poly_lambertw_series"+ acb_poly_lambertw_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CFmpz -> CInt -> CLong -> CLong -> IO ()++-- Gamma function --------------------------------------------------------------++foreign import ccall "acb_poly.h _acb_poly_gamma_series"+ _acb_poly_gamma_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_gamma_series"+ acb_poly_gamma_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_rgamma_series"+ _acb_poly_rgamma_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_rgamma_series"+ acb_poly_rgamma_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_lgamma_series"+ _acb_poly_lgamma_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_lgamma_series"+ acb_poly_lgamma_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_digamma_series"+ _acb_poly_digamma_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_digamma_series/ /res/ /h/ /n/ /prec/ +-- +-- Sets /res/ to the series expansion of \(\Gamma(h(x))\),+-- \(1/\Gamma(h(x))\), or \(\log \Gamma(h(x))\), \(\psi(h(x))\), truncated+-- to length /n/.+-- +-- These functions first generate the Taylor series at the constant term of+-- /h/, and then call @_acb_poly_compose_series@. The Taylor coefficients+-- are generated using Stirling\'s series.+-- +-- The underscore methods support aliasing of the input and output arrays,+-- and require that /hlen/ and /n/ are greater than zero.+foreign import ccall "acb_poly.h acb_poly_digamma_series"+ acb_poly_digamma_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_rising_ui_series"+ _acb_poly_rising_ui_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CULong -> CLong -> CLong -> IO ()++-- | /acb_poly_rising_ui_series/ /res/ /f/ /r/ /trunc/ /prec/ +-- +-- Sets /res/ to the rising factorial \((f) (f+1) (f+2) \cdots (f+r-1)\),+-- truncated to length /trunc/. The underscore method assumes that /flen/,+-- /r/ and /trunc/ are at least 1, and does not support aliasing. Uses+-- binary splitting.+foreign import ccall "acb_poly.h acb_poly_rising_ui_series"+ acb_poly_rising_ui_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CULong -> CLong -> CLong -> IO ()++-- Power sums ------------------------------------------------------------------++foreign import ccall "acb_poly.h _acb_poly_powsum_series_naive"+ _acb_poly_powsum_series_naive :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /_acb_poly_powsum_series_naive_threaded/ /z/ /s/ /a/ /q/ /n/ /len/ /prec/ +-- +-- Computes+-- +-- \[`\]+-- \[z = S(s,a,n) = \sum_{k=0}^{n-1} \frac{q^k}{(k+a)^{s+t}}\]+-- +-- as a power series in \(t\) truncated to length /len/. This function+-- evaluates the sum naively term by term. The /threaded/ version splits+-- the computation over the number of threads returned by+-- /flint_get_num_threads()/.+foreign import ccall "acb_poly.h _acb_poly_powsum_series_naive_threaded"+ _acb_poly_powsum_series_naive_threaded :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /_acb_poly_powsum_one_series_sieved/ /z/ /s/ /n/ /len/ /prec/ +-- +-- Computes+-- +-- \[`\]+-- \[z = S(s,1,n) \sum_{k=1}^n \frac{1}{k^{s+t}}\]+-- +-- as a power series in \(t\) truncated to length /len/. This function+-- stores a table of powers that have already been calculated, computing+-- \((ij)^r\) as \(i^r j^r\) whenever \(k = ij\) is composite. As a further+-- optimization, it groups all even \(k\) and evaluates the sum as a+-- polynomial in \(2^{-(s+t)}\). This scheme requires about \(n / \log n\)+-- powers, \(n / 2\) multiplications, and temporary storage of \(n / 6\)+-- power series. Due to the extra power series multiplications, it is only+-- faster than the naive algorithm when /len/ is small.+foreign import ccall "acb_poly.h _acb_poly_powsum_one_series_sieved"+ _acb_poly_powsum_one_series_sieved :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- Zeta function ---------------------------------------------------------------++-- | /_acb_poly_zeta_em_choose_param/ /bound/ /N/ /M/ /s/ /a/ /d/ /target/ /prec/ +-- +-- Chooses /N/ and /M/ for Euler-Maclaurin summation of the Hurwitz zeta+-- function, using a default algorithm.+foreign import ccall "acb_poly.h _acb_poly_zeta_em_choose_param"+ _acb_poly_zeta_em_choose_param :: Ptr CMag -> Ptr CULong -> Ptr CULong -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_zeta_em_bound1"+ _acb_poly_zeta_em_bound1 :: Ptr CMag -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> CLong -> IO ()++-- | /_acb_poly_zeta_em_bound/ /vec/ /s/ /a/ /N/ /M/ /d/ /wp/ +-- +-- Compute bounds for Euler-Maclaurin evaluation of the Hurwitz zeta+-- function or its power series, using the formulas in < [Joh2013]>.+foreign import ccall "acb_poly.h _acb_poly_zeta_em_bound"+ _acb_poly_zeta_em_bound :: Ptr CArb -> Ptr CAcb -> Ptr CAcb -> CULong -> CULong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_zeta_em_tail_naive"+ _acb_poly_zeta_em_tail_naive :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /_acb_poly_zeta_em_tail_bsplit/ /z/ /s/ /Na/ /Nasx/ /M/ /len/ /prec/ +-- +-- Evaluates the tail in the Euler-Maclaurin sum for the Hurwitz zeta+-- function, respectively using the naive recurrence and binary splitting.+foreign import ccall "acb_poly.h _acb_poly_zeta_em_tail_bsplit"+ _acb_poly_zeta_em_tail_bsplit :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /_acb_poly_zeta_em_sum/ /z/ /s/ /a/ /deflate/ /N/ /M/ /d/ /prec/ +-- +-- Evaluates the truncated Euler-Maclaurin sum of order \(N, M\) for the+-- length-/d/ truncated Taylor series of the Hurwitz zeta function+-- \(\zeta(s,a)\) at \(s\), using a working precision of /prec/ bits. With+-- \(a = 1\), this gives the usual Riemann zeta function.+-- +-- If /deflate/ is nonzero, \(\zeta(s,a) - 1/(s-1)\) is evaluated (which+-- permits series expansion at \(s = 1\)).+foreign import ccall "acb_poly.h _acb_poly_zeta_em_sum"+ _acb_poly_zeta_em_sum :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CULong -> CULong -> CLong -> CLong -> IO ()++-- | /_acb_poly_zeta_cpx_series/ /z/ /s/ /a/ /deflate/ /d/ /prec/ +-- +-- Computes the series expansion of \(\zeta(s+x,a)\) (or+-- \(\zeta(s+x,a) - 1/(s+x-1)\) if /deflate/ is nonzero) to order /d/.+-- +-- This function wraps @_acb_poly_zeta_em_sum@, automatically choosing+-- default values for \(N, M\) using @_acb_poly_zeta_em_choose_param@ to+-- target an absolute truncation error of \(2^{-\operatorname{prec}}\).+foreign import ccall "acb_poly.h _acb_poly_zeta_cpx_series"+ _acb_poly_zeta_cpx_series :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CInt -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_zeta_series"+ _acb_poly_zeta_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CInt -> CLong -> CLong -> IO ()++-- | /acb_poly_zeta_series/ /res/ /f/ /a/ /deflate/ /n/ /prec/ +-- +-- Sets /res/ to the Hurwitz zeta function \(\zeta(s,a)\) where \(s\) a+-- power series and \(a\) is a constant, truncated to length /n/. To+-- evaluate the usual Riemann zeta function, set \(a = 1\).+-- +-- If /deflate/ is nonzero, evaluates \(\zeta(s,a) + 1/(1-s)\), which is+-- well-defined as a limit when the constant term of \(s\) is 1. In+-- particular, expanding \(\zeta(s,a) + 1/(1-s)\) with \(s = 1+x\) gives+-- the Stieltjes constants+-- +-- \[`\]+-- \[\sum_{k=0}^{n-1} \frac{(-1)^k}{k!} \gamma_k(a) x^k`.\]+-- +-- If \(a = 1\), this implementation uses the reflection formula if the+-- midpoint of the constant term of \(s\) is negative.+foreign import ccall "acb_poly.h acb_poly_zeta_series"+ acb_poly_zeta_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcb -> CInt -> CLong -> CLong -> IO ()++-- Other special functions -----------------------------------------------------++foreign import ccall "acb_poly.h _acb_poly_polylog_cpx_small"+ _acb_poly_polylog_cpx_small :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_polylog_cpx_zeta"+ _acb_poly_polylog_cpx_zeta :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /_acb_poly_polylog_cpx/ /w/ /s/ /z/ /len/ /prec/ +-- +-- Sets /w/ to the Taylor series with respect to /x/ of the polylogarithm+-- \(\operatorname{Li}_{s+x}(z)\), where /s/ and /z/ are given complex+-- constants. The output is computed to length /len/ which must be+-- positive. Aliasing between /w/ and /s/ or /z/ is not permitted.+-- +-- The /small/ version uses the standard power series expansion with+-- respect to /z/, convergent when \(|z| < 1\). The /zeta/ version+-- evaluates the polylogarithm as a sum of two Hurwitz zeta functions. The+-- default version automatically delegates to the /small/ version when /z/+-- is close to zero, and the /zeta/ version otherwise. For further details,+-- see @algorithms_polylogarithms@.+foreign import ccall "acb_poly.h _acb_poly_polylog_cpx"+ _acb_poly_polylog_cpx :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_polylog_series"+ _acb_poly_polylog_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /acb_poly_polylog_series/ /w/ /s/ /z/ /len/ /prec/ +-- +-- Sets /w/ to the polylogarithm \(\operatorname{Li}_{s}(z)\) where /s/ is+-- a given power series, truncating the output to length /len/. The+-- underscore method requires all lengths to be positive and supports+-- aliasing between all inputs and outputs.+foreign import ccall "acb_poly.h acb_poly_polylog_series"+ acb_poly_polylog_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_erf_series"+ _acb_poly_erf_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_erf_series/ /res/ /z/ /n/ /prec/ +-- +-- Sets /res/ to the error function of the power series /z/, truncated to+-- length /n/. These methods are provided for backwards compatibility. See+-- @acb_hypgeom_erf_series@, @acb_hypgeom_erfc_series@,+-- @acb_hypgeom_erfi_series@.+foreign import ccall "acb_poly.h acb_poly_erf_series"+ acb_poly_erf_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_agm1_series"+ _acb_poly_agm1_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++-- | /acb_poly_agm1_series/ /res/ /z/ /n/ /prec/ +-- +-- Sets /res/ to the arithmetic-geometric mean of 1 and the power series+-- /z/, truncated to length /n/.+foreign import ccall "acb_poly.h acb_poly_agm1_series"+ acb_poly_agm1_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++-- See the @acb_elliptic.h \<acb-elliptic>@ module for power series of+-- elliptic functions. The following wrappers are available for backwards+-- compatibility.+--+foreign import ccall "acb_poly.h _acb_poly_elliptic_k_series"+ _acb_poly_elliptic_k_series :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_elliptic_k_series"+ acb_poly_elliptic_k_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_elliptic_p_series"+ _acb_poly_elliptic_p_series :: Ptr CAcb -> Ptr CAcb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h acb_poly_elliptic_p_series"+ acb_poly_elliptic_p_series :: Ptr CAcbPoly -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> CLong -> IO ()++-- Root-finding ----------------------------------------------------------------++foreign import ccall "acb_poly.h _acb_poly_root_bound_fujiwara"+ _acb_poly_root_bound_fujiwara :: Ptr CMag -> Ptr CAcb -> CLong -> IO ()++-- | /acb_poly_root_bound_fujiwara/ /bound/ /poly/ +-- +-- Sets /bound/ to an upper bound for the magnitude of all the complex+-- roots of /poly/. Uses Fujiwara\'s bound+-- +-- \[`\]+-- \[2 \max \left\{\left|\frac{a_{n-1}}{a_n}\right|,+-- \left|\frac{a_{n-2}}{a_n}\right|^{1/2},+-- \cdots,+-- \left|\frac{a_1}{a_n}\right|^{1/(n-1)},+-- \left|\frac{a_0}{2a_n}\right|^{1/n}+-- \right\}\]+-- +-- where \(a_0, \ldots, a_n\) are the coefficients of /poly/.+foreign import ccall "acb_poly.h acb_poly_root_bound_fujiwara"+ acb_poly_root_bound_fujiwara :: Ptr CMag -> Ptr CAcbPoly -> IO ()++-- | /_acb_poly_root_inclusion/ /r/ /m/ /poly/ /polyder/ /len/ /prec/ +-- +-- Given any complex number \(m\), and a nonconstant polynomial \(f\) and+-- its derivative \(f'\), sets /r/ to a complex interval centered on \(m\)+-- that is guaranteed to contain at least one root of \(f\). Such an+-- interval is obtained by taking a ball of radius \(|f(m)/f'(m)| n\) where+-- \(n\) is the degree of \(f\). Proof: assume that the distance to the+-- nearest root exceeds \(r = |f(m)/f'(m)| n\). Then+-- +-- \[`\]+-- \[\left|\frac{f'(m)}{f(m)}\right| =+-- \left|\sum_i \frac{1}{m-\zeta_i}\right|+-- \le \sum_i \frac{1}{|m-\zeta_i|}+-- < \frac{n}{r} = \left|\frac{f'(m)}{f(m)}\right|\]+-- +-- which is a contradiction (see < [Kob2010]>).+foreign import ccall "acb_poly.h _acb_poly_root_inclusion"+ _acb_poly_root_inclusion :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /_acb_poly_validate_roots/ /roots/ /poly/ /len/ /prec/ +-- +-- Given a list of approximate roots of the input polynomial, this function+-- sets a rigorous bounding interval for each root, and determines which+-- roots are isolated from all the other roots. It then rearranges the list+-- of roots so that the isolated roots are at the front of the list, and+-- returns the count of isolated roots.+-- +-- If the return value equals the degree of the polynomial, then all roots+-- have been found. If the return value is smaller, all the remaining+-- output intervals are guaranteed to contain roots, but it is possible+-- that not all of the polynomial\'s roots are contained among them.+foreign import ccall "acb_poly.h _acb_poly_validate_roots"+ _acb_poly_validate_roots :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO CLong++-- | /_acb_poly_refine_roots_durand_kerner/ /roots/ /poly/ /len/ /prec/ +-- +-- Refines the given roots simultaneously using a single iteration of the+-- Durand-Kerner method. The radius of each root is set to an approximation+-- of the correction, giving a rough estimate of its error (not a rigorous+-- bound).+foreign import ccall "acb_poly.h _acb_poly_refine_roots_durand_kerner"+ _acb_poly_refine_roots_durand_kerner :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO ()++foreign import ccall "acb_poly.h _acb_poly_find_roots"+ _acb_poly_find_roots :: Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> CLong -> IO CLong++-- | /acb_poly_find_roots/ /roots/ /poly/ /initial/ /maxiter/ /prec/ +-- +-- Attempts to compute all the roots of the given nonzero polynomial /poly/+-- using a working precision of /prec/ bits. If /n/ denotes the degree of+-- /poly/, the function writes /n/ approximate roots with rigorous error+-- bounds to the preallocated array /roots/, and returns the number of+-- roots that are isolated.+-- +-- If the return value equals the degree of the polynomial, then all roots+-- have been found. If the return value is smaller, all the output+-- intervals are guaranteed to contain roots, but it is possible that not+-- all of the polynomial\'s roots are contained among them.+-- +-- The roots are computed numerically by performing several steps with the+-- Durand-Kerner method and terminating if the estimated accuracy of the+-- roots approaches the working precision or if the number of steps exceeds+-- /maxiter/, which can be set to zero in order to use a default value.+-- Finally, the approximate roots are validated rigorously.+-- +-- Initial values for the iteration can be provided as the array /initial/.+-- If /initial/ is set to /NULL/, default values \((0.4+0.9i)^k\) are used.+-- +-- The polynomial is assumed to be squarefree. If there are repeated roots,+-- the iteration is likely to find them (with low numerical accuracy), but+-- the error bounds will not converge as the precision increases.+foreign import ccall "acb_poly.h acb_poly_find_roots"+ acb_poly_find_roots :: Ptr CAcb -> Ptr CAcbPoly -> Ptr CAcb -> CLong -> CLong -> IO CLong++foreign import ccall "acb_poly.h _acb_poly_validate_real_roots"+ _acb_poly_validate_real_roots :: Ptr CAcb -> Ptr CAcb -> CLong -> CLong -> IO CInt++-- | /acb_poly_validate_real_roots/ /roots/ /poly/ /prec/ +-- +-- Given a strictly real polynomial /poly/ (of length /len/) and isolating+-- intervals for all its complex roots, determines if all the real roots+-- are separated from the non-real roots. If this function returns nonzero,+-- every root enclosure that touches the real axis (as tested by applying+-- @arb_contains_zero@ to the imaginary part) corresponds to a real root+-- (its imaginary part can be set to zero), and every other root enclosure+-- corresponds to a non-real root (with known sign for the imaginary part).+-- +-- If this function returns zero, then the signs of the imaginary parts are+-- not known for certain, based on the accuracy of the inputs and the+-- working precision /prec/.+foreign import ccall "acb_poly.h acb_poly_validate_real_roots"+ acb_poly_validate_real_roots :: Ptr CAcb -> Ptr CAcbPoly -> CLong -> IO CInt+
+ src/Data/Number/Flint/Acb/Poly/Instances.hs view
@@ -0,0 +1,64 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Acb.Poly.Instances (+ AcbPoly (..)+ , module GHC.Exts+) where++import Test.QuickCheck++import GHC.Exts++import System.IO.Unsafe+import Control.Monad++import Foreign.Ptr+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Alloc (free)+import Foreign.Marshal.Array (advancePtr)++import Data.Number.Flint.Acb+import Data.Number.Flint.Acb.Instances+import Data.Number.Flint.Acb.Poly++import Data.Number.Flint.UFD++instance Show AcbPoly where+ show p = snd $ unsafePerformIO $ do+ withAcbPoly p $ \p -> do+ cs <- acb_poly_get_strd p 16+ s <- peekCString cs+ free cs+ return s++instance IsList AcbPoly where+ type Item AcbPoly = Acb+ fromList c = unsafePerformIO $ do+ p <- newAcbPoly+ withAcbPoly p $ \p -> + forM_ [0..length c-1] $ \j ->+ withAcb (c!!j) $ \a -> + acb_poly_set_coeff_acb p (fromIntegral j) a+ return p+ toList p = snd $ unsafePerformIO $ + withAcbPoly p $ \p -> do+ d <- acb_poly_degree p+ forM [0..d] $ \j -> do+ c <- newAcb+ withAcb c $ \c -> acb_poly_get_coeff_acb c p j+ return c++lift2 f x y = unsafePerformIO $ do+ result <- newAcbPoly+ withAcbPoly result $ \result -> do+ withAcbPoly x $ \x -> do+ withAcbPoly y $ \y -> do+ f result x y+ return result++lift1 f x = unsafePerformIO $ do+ result <- newAcbPoly+ withAcbPoly result $ \result ->+ withAcbPoly x $ \x ->+ f result x+ return result
+ src/Data/Number/Flint/Acb/Types.hs view
@@ -0,0 +1,6 @@+-- {-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Acb.Types (+ module Data.Number.Flint.Acb.Types.FFI+ ) where++import Data.Number.Flint.Acb.Types.FFI
+ src/Data/Number/Flint/Acb/Types/FFI.hsc view
@@ -0,0 +1,30 @@+{-|+module : Data.Number.Flint.Acb.Types.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Acb.Types.FFI where++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint.Internal+import Data.Number.Flint.Arb.Types++#include <flint/acb.h>++-- | An CArb consists of a pair of Arb:s. +data Acb = Acb {-# UNPACK #-} !(ForeignPtr CAcb)+data CAcb = CAcb CArb CArb++-- | An Acf structure consists of a pair of arf_struct:s. An acf_t is+-- defined as an array of length one of type acf_struct, permitting an+-- acf_t to be passed by reference.+data Acf = Acf {-# UNPACK #-} !(ForeignPtr CAcf)+data CAcf = CAcf CArf CArf
+ src/Data/Number/Flint/Arb.hs view
@@ -0,0 +1,53 @@+{-|+module : Data.Number.Flint.Arb+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++An @Arb@ represents a ball over the real numbers, that is, an interval+\([m \pm r] \equiv [m-r, m+r]\) where the midpoint \(m\) and the radius+\(r\) are (extended) real numbers and \(r\) is nonnegative (possibly+infinite). The result of an (approximate) operation done on @arb_t@+variables is a ball which contains the result of the (mathematically+exact) operation applied to any choice of points in the input balls. In+general, the output ball is not the smallest possible.++The precision parameter passed to each function roughly indicates the+precision to which calculations on the midpoint are carried out+(operations on the radius are always done using a fixed, small+precision.)++For arithmetic operations, the precision parameter currently simply+specifies the precision of the corresponding @arf_t@ operation. In the+future, the arithmetic might be made faster by incorporating sloppy+rounding (typically equivalent to a loss of 1-2 bits of effective+working precision) when the result is known to be inexact (while still+propagating errors rigorously, of course). Arithmetic operations done on+exact input with exactly representable output are always guaranteed to+produce exact output.++For more complex operations, the precision parameter indicates a minimum+working precision (algorithms might allocate extra internal precision to+attempt to produce an output accurate to the requested number of bits,+especially when the required precision can be estimated easily, but this+is not generally required).++If the precision is increased and the inputs either are exact or are+computed with increased accuracy as well, the output should converge+proportionally, absent any bugs. The general intended strategy for using+ball arithmetic is to add a few guard bits, and then repeat the+calculation as necessary with an exponentially increasing number of+guard bits (Ziv\'s strategy) until the result is exact enough for one\'s+purposes (typically the first attempt will be successful).++The following balls with an infinite or NaN component are permitted, and+may be returned as output from functions.++-}++module Data.Number.Flint.Arb (+ module Data.Number.Flint.Arb.FFI+ ) where++import Data.Number.Flint.Arb.FFI+
+ src/Data/Number/Flint/Arb/Arf.hs view
@@ -0,0 +1,26 @@+{-|+module : Data.Number.Flint.Arb.Arf+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++A variable of type @Arf@ holds an arbitrary-precision binary+floating-point number: that is, a rational number of the form \(x c\dot 2^y\)+where \(x, y \in \mathbb{Z}\) and \(x\) is odd, or one of the special+values zero, plus infinity, minus infinity, or NaN (not-a-number). There+is currently no support for negative zero, unsigned infinity, or a NaN+with a payload.++The /exponent/ of a finite and nonzero floating-point number can be+defined in different ways: for example, as the component /y/ above, or+as the unique integer /e/ such that \(x cdot 2^y = m cdot 2^e\) +where \(0.5 \le |m| < 1\). The internal representation of an @Arf@ stores+the exponent in the latter format.+-}++module Data.Number.Flint.Arb.Arf (+ module Data.Number.Flint.Arb.Arf.FFI+ ) where++import Data.Number.Flint.Arb.Arf.FFI+
+ src/Data/Number/Flint/Arb/Arf/FFI.hsc view
@@ -0,0 +1,1270 @@+{-|+module : Data.Number.Flint.Arb.Arf.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Arb.Arf.FFI (+ -- * Arbitrary-precision floating-point numbers+ Arf (..)+ , CArf+ , newArf+ , withArf+ , withNewArf+ -- * Memory management+ , arf_init+ , arf_clear+ , arf_allocated_bytes+ -- * Special values+ , arf_zero+ , arf_one+ , arf_pos_inf+ , arf_neg_inf+ , arf_nan+ , arf_is_zero+ , arf_is_one+ , arf_is_pos_inf+ , arf_is_neg_inf+ , arf_is_nan+ , arf_is_inf+ , arf_is_normal+ , arf_is_special+ , arf_is_finite+ -- * Assignment, rounding and conversions+ , ArfRnd (..)+ -- | Specifies that the result of an operation should be rounded to+ -- the nearest representable number in the direction towards zero.+ , arf_rnd_up+ -- | Specifies that the result of an operation should be rounded to+ -- the nearest representable number in the direction away from zero.+ , arf_rnd_down+ -- | Specifies that the result of an operation should be rounded to+ -- the nearest representable number in the direction towards minus+ -- infinity.+ , arf_rnd_floor+ -- | Specifies that the result of an operation should be rounded to+ -- the nearest representable number in the direction towards plus+ -- infinity.+ , arf_rnd_ceil+ -- | Specifies that the result of an operation should be rounded to+ -- the nearest representable number, rounding to even if there is a+ -- tie between two values.+ , arf_rnd_near+ -- | If passed as the precision parameter to a function, indicates+ -- that no rounding is to be performed. __Warning__: use of this value+ -- is unsafe in general. It must only be passed as input under the+ -- following two conditions:+ -- + -- * The operation in question can inherently be viewed as an exact operation+ -- in \(\mathbb{Z}[\tfrac{1}{2}]\) for all possible inputs, provided that+ -- the precision is large enough. Examples include addition,+ -- multiplication, conversion from integer types to arbitrary-precision+ -- floating-point types, and evaluation of some integer-valued functions.+ --+ -- * The exact result of the operation will certainly fit in memory.+ -- Note that, for example, adding two numbers whose exponents are far+ -- apart can easily produce an exact result that is far too large to+ -- store in memory.+ --+ -- The typical use case is to work with small integer values, double+ -- precision constants, and the like. It is also useful when writing+ -- test code. If in doubt, simply try with some convenient high precision+ -- instead of using this special value, and check that the result is exact.+ , arf_prec_exact+ , arf_set+ , arf_set_mpz+ , arf_set_fmpz+ , arf_set_ui+ , arf_set_si+ , arf_set_mpfr+ , arf_set_d+ , arf_swap+ , arf_init_set_ui+ , arf_init_set_si+ , arf_set_round+ , arf_set_round_si+ , arf_set_round_ui+ , arf_set_round_mpz+ , arf_set_round_fmpz+ , arf_set_si_2exp_si+ , arf_set_ui_2exp_si+ , arf_set_fmpz_2exp+ , arf_set_round_fmpz_2exp+ , arf_get_fmpz_2exp+ , arf_frexp+ , arf_get_d+ , arf_get_mpfr+ , arf_get_fmpz+ , arf_get_si+ , arf_get_fmpz_fixed_fmpz+ , arf_get_fmpz_fixed_si+ , arf_floor+ , arf_ceil+ , arf_get_fmpq+ -- * Comparisons and bounds+ , arf_equal+ , arf_equal_si+ , arf_equal_ui+ , arf_equal_d+ , arf_cmp+ , arf_cmp_si+ , arf_cmp_ui+ , arf_cmp_d+ , arf_cmpabs+ , arf_cmpabs_ui+ , arf_cmpabs_d+ , arf_cmpabs_mag+ , arf_cmp_2exp_si+ , arf_cmpabs_2exp_si+ , arf_sgn+ , arf_min+ , arf_max+ , arf_bits+ , arf_is_int+ , arf_is_int_2exp_si+ , arf_abs_bound_lt_2exp_fmpz+ , arf_abs_bound_le_2exp_fmpz+ , arf_abs_bound_lt_2exp_si+ -- * Magnitude functions+ , arf_get_mag+ , arf_get_mag_lower+ , arf_set_mag+ , mag_init_set_arf+ , mag_fast_init_set_arf+ , arf_mag_set_ulp+ , arf_mag_add_ulp+ , arf_mag_fast_add_ulp+ -- * Shallow assignment+ , arf_init_set_shallow+ , arf_init_set_mag_shallow+ , arf_init_neg_shallow+ , arf_init_neg_mag_shallow+ -- * Random number generation+ , arf_randtest+ , arf_randtest_not_zero+ , arf_randtest_special+ , arf_urandom+ -- * Input and output+ , arf_debug+ , arf_print+ , arf_printd+ , arf_get_str+ , arf_fprint+ , arf_fprintd+ , arf_dump_str+ , arf_load_str+ , arf_dump_file+ , arf_load_file+ -- * Addition and multiplication+ , arf_abs+ , arf_neg+ , arf_neg_round+ , arf_add+ , arf_add_si+ , arf_add_ui+ , arf_add_fmpz+ , arf_add_fmpz_2exp+ , arf_sub+ , arf_sub_si+ , arf_sub_ui+ , arf_sub_fmpz+ , arf_mul_2exp_si+ , arf_mul_2exp_fmpz+ , arf_mul+ , arf_mul_ui+ , arf_mul_si+ , arf_mul_mpz+ , arf_mul_fmpz+ , arf_addmul+ , arf_addmul_ui+ , arf_addmul_si+ , arf_addmul_mpz+ , arf_addmul_fmpz+ , arf_submul+ , arf_submul_ui+ , arf_submul_si+ , arf_submul_mpz+ , arf_submul_fmpz+ , arf_fma+ , arf_sosq+ -- * Summation+ , arf_sum+ -- * Dot products+ , arf_approx_dot+ -- * Division+ , arf_div+ , arf_div_ui+ , arf_ui_div+ , arf_div_si+ , arf_si_div+ , arf_div_fmpz+ , arf_fmpz_div+ , arf_fmpz_div_fmpz+ -- * Square roots+ , arf_sqrt+ , arf_sqrt_ui+ , arf_sqrt_fmpz+ , arf_rsqrt+ , arf_root+ -- * Complex arithmetic+ , arf_complex_mul+ , arf_complex_mul_fallback+ , arf_complex_sqr+ -- * Low-level methods+ , _arf_get_integer_mpn+ , _arf_set_mpn_fixed+ , _arf_set_round_ui+ , _arf_set_round_uiui+ , _arf_set_round_mpn+) where ++-- Arbitrary-precision floating-point numbers ----------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable+import Foreign.Marshal.Alloc+import Foreign.C.Types+import Foreign.C.String++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq++import Data.Number.Flint.Arb.Types++#define ARF_INLINES_C+#include <flint/arf.h>++-- arf_t -----------------------------------------------------------------------++-- | Createst a new `CArf` structure encapsulated in `Arf`.+newArf = do+ p <- mallocForeignPtr+ withForeignPtr p arf_init+ addForeignPtrFinalizer p_arf_clear p+ return $ Arf p+ +-- | Access to the C pointer in `Arf` structure.+{-# INLINE withArf #-}+withArf (Arf p) f = withForeignPtr p $ fmap (Arf p,) . f++withNewArf f = do+ x <- newArf+ withArf x $ \x -> f x+ +-- Memory management -----------------------------------------------------------++-- | /arf_init/ /x/ +--+-- Initializes the variable /x/ for use. Its value is set to zero.+foreign import ccall "arf.h arf_init"+ arf_init :: Ptr CArf -> IO ()++-- | /arf_clear/ /x/ +--+-- Clears the variable /x/, freeing or recycling its allocated memory.+foreign import ccall "arf.h arf_clear"+ arf_clear :: Ptr CArf -> IO ()++foreign import ccall "arf.h &arf_clear"+ p_arf_clear :: FunPtr (Ptr CArf -> IO ())++-- | /arf_allocated_bytes/ /x/ +--+-- Returns the total number of bytes heap-allocated internally by this+-- object. The count excludes the size of the structure itself. Add+-- @sizeof(arf_struct)@ to get the size of the object as a whole.+foreign import ccall "arf.h arf_allocated_bytes"+ arf_allocated_bytes :: Ptr CArf -> IO CLong++-- Special values --------------------------------------------------------------++-- | /arf_zero/ /res/ +--+foreign import ccall "arf.h arf_zero"+ arf_zero :: Ptr CArf -> IO ()++-- | /arf_one/ /res/ +--+foreign import ccall "arf.h arf_one"+ arf_one :: Ptr CArf -> IO ()++-- | /arf_pos_inf/ /res/ +--+foreign import ccall "arf.h arf_pos_inf"+ arf_pos_inf :: Ptr CArf -> IO ()++-- | /arf_neg_inf/ /res/ +--+foreign import ccall "arf.h arf_neg_inf"+ arf_neg_inf :: Ptr CArf -> IO ()++-- | /arf_nan/ /res/ +--+-- Sets /res/ respectively to 0, 1, \(+\infty\), \(-\infty\), NaN.+foreign import ccall "arf.h arf_nan"+ arf_nan :: Ptr CArf -> IO ()++-- | /arf_is_zero/ /x/ +--+foreign import ccall "arf.h arf_is_zero"+ arf_is_zero :: Ptr CArf -> IO CInt++-- | /arf_is_one/ /x/ +--+foreign import ccall "arf.h arf_is_one"+ arf_is_one :: Ptr CArf -> IO CInt++-- | /arf_is_pos_inf/ /x/ +--+foreign import ccall "arf.h arf_is_pos_inf"+ arf_is_pos_inf :: Ptr CArf -> IO CInt++-- | /arf_is_neg_inf/ /x/ +--+foreign import ccall "arf.h arf_is_neg_inf"+ arf_is_neg_inf :: Ptr CArf -> IO CInt++-- | /arf_is_nan/ /x/ +--+-- Returns nonzero iff /x/ respectively equals 0, 1, \(+\infty\),+-- \(-\infty\), NaN.+foreign import ccall "arf.h arf_is_nan"+ arf_is_nan :: Ptr CArf -> IO CInt++-- | /arf_is_inf/ /x/ +--+-- Returns nonzero iff /x/ equals either \(+\infty\) or \(-\infty\).+foreign import ccall "arf.h arf_is_inf"+ arf_is_inf :: Ptr CArf -> IO CInt++-- | /arf_is_normal/ /x/ +--+-- Returns nonzero iff /x/ is a finite, nonzero floating-point value, i.e.+-- not one of the special values 0, \(+\infty\), \(-\infty\), NaN.+foreign import ccall "arf.h arf_is_normal"+ arf_is_normal :: Ptr CArf -> IO CInt++-- | /arf_is_special/ /x/ +--+-- Returns nonzero iff /x/ is one of the special values 0, \(+\infty\),+-- \(-\infty\), NaN, i.e. not a finite, nonzero floating-point value.+foreign import ccall "arf.h arf_is_special"+ arf_is_special :: Ptr CArf -> IO CInt++-- | /arf_is_finite/ /x/ +--+-- Returns nonzero iff /x/ is a finite floating-point value, i.e. not one+-- of the values \(+\infty\), \(-\infty\), NaN. (Note that this is not+-- equivalent to the negation of @arf_is_inf@.)+foreign import ccall "arf.h arf_is_finite"+ arf_is_finite :: Ptr CArf -> IO CInt++-- Assignment, rounding and conversions ----------------------------------------++-- | /arf_set/ /res/ /x/ +--+foreign import ccall "arf.h arf_set"+ arf_set :: Ptr CArf -> Ptr CArf -> IO ()++-- | /arf_set_mpz/ /res/ /x/ +--+foreign import ccall "arf.h arf_set_mpz"+ arf_set_mpz :: Ptr CArf -> Ptr CMpz -> IO ()++-- | /arf_set_fmpz/ /res/ /x/ +--+foreign import ccall "arf.h arf_set_fmpz"+ arf_set_fmpz :: Ptr CArf -> Ptr CFmpz -> IO ()++-- | /arf_set_ui/ /res/ /x/ +--+foreign import ccall "arf.h arf_set_ui"+ arf_set_ui :: Ptr CArf -> CULong -> IO ()++-- | /arf_set_si/ /res/ /x/ +--+foreign import ccall "arf.h arf_set_si"+ arf_set_si :: Ptr CArf -> CLong -> IO ()++-- | /arf_set_mpfr/ /res/ /x/ +--+foreign import ccall "arf.h arf_set_mpfr"+ arf_set_mpfr :: Ptr CArf -> Ptr CMpfr -> IO ()++-- | /arf_set_d/ /res/ /x/ +--+-- Sets /res/ to the exact value of /x/.+foreign import ccall "arf.h arf_set_d"+ arf_set_d :: Ptr CArf -> CDouble -> IO ()++-- | /arf_swap/ /x/ /y/ +--+-- Swaps /x/ and /y/ efficiently.+foreign import ccall "arf.h arf_swap"+ arf_swap :: Ptr CArf -> Ptr CArf -> IO ()++-- | /arf_init_set_ui/ /res/ /x/ +--+foreign import ccall "arf.h arf_init_set_ui"+ arf_init_set_ui :: Ptr CArf -> CULong -> IO ()++-- | /arf_init_set_si/ /res/ /x/ +--+-- Initializes /res/ and sets it to /x/ in a single operation.+foreign import ccall "arf.h arf_init_set_si"+ arf_init_set_si :: Ptr CArf -> CLong -> IO ()++-- | /arf_set_round/ /res/ /x/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_set_round"+ arf_set_round :: Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_set_round_si/ /res/ /x/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_set_round_si"+ arf_set_round_si :: Ptr CArf -> CLong -> CLong -> ArfRnd -> IO CInt++-- | /arf_set_round_ui/ /res/ /x/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_set_round_ui"+ arf_set_round_ui :: Ptr CArf -> CULong -> CLong -> ArfRnd -> IO CInt++-- | /arf_set_round_mpz/ /res/ /x/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_set_round_mpz"+ arf_set_round_mpz :: Ptr CArf -> Ptr CMpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_set_round_fmpz/ /res/ /x/ /prec/ /rnd/ +--+-- Sets /res/ to /x/, rounded to /prec/ bits in the direction specified by+-- /rnd/.+foreign import ccall "arf.h arf_set_round_fmpz"+ arf_set_round_fmpz :: Ptr CArf -> Ptr CFmpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_set_si_2exp_si/ /res/ /m/ /e/ +--+foreign import ccall "arf.h arf_set_si_2exp_si"+ arf_set_si_2exp_si :: Ptr CArf -> CLong -> CLong -> IO ()++-- | /arf_set_ui_2exp_si/ /res/ /m/ /e/ +--+foreign import ccall "arf.h arf_set_ui_2exp_si"+ arf_set_ui_2exp_si :: Ptr CArf -> CULong -> CLong -> IO ()++-- | /arf_set_fmpz_2exp/ /res/ /m/ /e/ +--+-- Sets /res/ to \(m \cdot 2^e\).+foreign import ccall "arf.h arf_set_fmpz_2exp"+ arf_set_fmpz_2exp :: Ptr CArf -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /arf_set_round_fmpz_2exp/ /res/ /x/ /e/ /prec/ /rnd/ +--+-- Sets /res/ to \(x \cdot 2^e\), rounded to /prec/ bits in the direction+-- specified by /rnd/.+foreign import ccall "arf.h arf_set_round_fmpz_2exp"+ arf_set_round_fmpz_2exp :: Ptr CArf -> Ptr CFmpz -> Ptr CFmpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_get_fmpz_2exp/ /m/ /e/ /x/ +--+-- Sets /m/ and /e/ to the unique integers such that \(x = m \cdot 2^e\)+-- and /m/ is odd, provided that /x/ is a nonzero finite fraction. If /x/+-- is zero, both /m/ and /e/ are set to zero. If /x/ is infinite or NaN,+-- the result is undefined.+foreign import ccall "arf.h arf_get_fmpz_2exp"+ arf_get_fmpz_2exp :: Ptr CFmpz -> Ptr CFmpz -> Ptr CArf -> IO ()++-- | /arf_frexp/ /m/ /e/ /x/ +--+-- Writes /x/ as \(m \cdot 2^e\), where \(0.5 \le |m| < 1\) if /x/ is a+-- normal value. If /x/ is a special value, copies this to /m/ and sets /e/+-- to zero. Note: for the inverse operation (/ldexp/), use+-- @arf_mul_2exp_fmpz@.+foreign import ccall "arf.h arf_frexp"+ arf_frexp :: Ptr CArf -> Ptr CFmpz -> Ptr CArf -> IO ()++-- | /arf_get_d/ /x/ /rnd/ +--+-- Returns /x/ rounded to a double in the direction specified by /rnd/.+-- This method rounds correctly when overflowing or underflowing the double+-- exponent range (this was not the case in an earlier version).+foreign import ccall "arf.h arf_get_d"+ arf_get_d :: Ptr CArf -> ArfRnd -> IO CDouble++-- | /arf_get_mpfr/ /res/ /x/ /rnd/ +--+-- Sets the MPFR variable /res/ to the value of /x/. If the precision of+-- /x/ is too small to allow /res/ to be represented exactly, it is rounded+-- in the specified MPFR rounding mode. The return value (-1, 0 or 1)+-- indicates the direction of rounding, following the convention of the+-- MPFR library.+-- +-- If /x/ has an exponent too large or small to fit in the MPFR type, the+-- result overflows to an infinity or underflows to a (signed) zero, and+-- the corresponding MPFR exception flags are set.+foreign import ccall "arf.h arf_get_mpfr"+ arf_get_mpfr :: Ptr CMpfr -> Ptr CArf -> CMpfrRnd -> IO CInt++-- | /arf_get_fmpz/ /res/ /x/ /rnd/ +--+-- Sets /res/ to /x/ rounded to the nearest integer in the direction+-- specified by /rnd/. If rnd is /ARFRND_NEAR/, rounds to the nearest even+-- integer in case of a tie. Returns inexact (beware: accordingly returns+-- whether /x/ is /not/ an integer).+-- +-- This method aborts if /x/ is infinite or NaN, or if the exponent of /x/+-- is so large that allocating memory for the result fails.+-- +-- Warning: this method will allocate a huge amount of memory to store the+-- result if the exponent of /x/ is huge. Memory allocation could succeed+-- even if the required space is far larger than the physical memory+-- available on the machine, resulting in swapping. It is recommended to+-- check that /x/ is within a reasonable range before calling this method.+foreign import ccall "arf.h arf_get_fmpz"+ arf_get_fmpz :: Ptr CFmpz -> Ptr CArf -> ArfRnd -> IO CInt++-- | /arf_get_si/ /x/ /rnd/ +--+-- Returns /x/ rounded to the nearest integer in the direction specified by+-- /rnd/. If /rnd/ is /ARFRND_NEAR/, rounds to the nearest even integer in+-- case of a tie. Aborts if /x/ is infinite, NaN, or the value is too large+-- to fit in a slong.+foreign import ccall "arf.h arf_get_si"+ arf_get_si :: Ptr CArf -> ArfRnd -> IO CLong++-- | /arf_get_fmpz_fixed_fmpz/ /res/ /x/ /e/ +--+foreign import ccall "arf.h arf_get_fmpz_fixed_fmpz"+ arf_get_fmpz_fixed_fmpz :: Ptr CFmpz -> Ptr CArf -> Ptr CFmpz -> IO CInt++-- | /arf_get_fmpz_fixed_si/ /res/ /x/ /e/ +--+-- Converts /x/ to a mantissa with predetermined exponent, i.e. sets /res/+-- to an integer /y/ such that \(y \times 2^e \approx x\), truncating if+-- necessary. Returns 0 if exact and 1 if truncation occurred.+-- +-- The warnings for @arf_get_fmpz@ apply.+foreign import ccall "arf.h arf_get_fmpz_fixed_si"+ arf_get_fmpz_fixed_si :: Ptr CFmpz -> Ptr CArf -> CLong -> IO CInt++-- | /arf_floor/ /res/ /x/ +--+foreign import ccall "arf.h arf_floor"+ arf_floor :: Ptr CArf -> Ptr CArf -> IO ()++-- | /arf_ceil/ /res/ /x/ +--+-- Sets /res/ to \(\lfloor x \rfloor\) and \(\lceil x \rceil\)+-- respectively. The result is always represented exactly, requiring no+-- more bits to store than the input. To round the result to a+-- floating-point number with a lower precision, call @arf_set_round@+-- afterwards.+foreign import ccall "arf.h arf_ceil"+ arf_ceil :: Ptr CArf -> Ptr CArf -> IO ()++-- | /arf_get_fmpq/ /res/ /x/ +--+-- Set /res/ to the exact rational value of /x/. This method aborts if /x/+-- is infinite or NaN, or if the exponent of /x/ is so large that+-- allocating memory for the result fails.+foreign import ccall "arf.h arf_get_fmpq"+ arf_get_fmpq :: Ptr CFmpq -> Ptr CArf -> IO ()++-- Comparisons and bounds ------------------------------------------------------++-- | /arf_equal/ /x/ /y/ +foreign import ccall "arf.h arf_equal"+ arf_equal :: Ptr CArf -> Ptr CArf -> IO CInt+-- | /arf_equal_si/ /x/ /y/ +foreign import ccall "arf.h arf_equal_si"+ arf_equal_si :: Ptr CArf -> CLong -> IO CInt+-- | /arf_equal_ui/ /x/ /y/ +foreign import ccall "arf.h arf_equal_ui"+ arf_equal_ui :: Ptr CArf -> CULong -> IO CInt+-- | /arf_equal_d/ /x/ /y/ +--+-- Returns nonzero iff /x/ and /y/ are exactly equal. NaN is not treated+-- specially, i.e. NaN compares as equal to itself.+-- +-- For comparison with a /double/, the values -0 and +0 are both treated as+-- zero, and all NaN values are treated as identical.+foreign import ccall "arf.h arf_equal_d"+ arf_equal_d :: Ptr CArf -> CDouble -> IO CInt++-- | /arf_cmp/ /x/ /y/ +--+foreign import ccall "arf.h arf_cmp"+ arf_cmp :: Ptr CArf -> Ptr CArf -> IO CInt++-- | /arf_cmp_si/ /x/ /y/ +--+foreign import ccall "arf.h arf_cmp_si"+ arf_cmp_si :: Ptr CArf -> CLong -> IO CInt++-- | /arf_cmp_ui/ /x/ /y/ +--+foreign import ccall "arf.h arf_cmp_ui"+ arf_cmp_ui :: Ptr CArf -> CULong -> IO CInt++-- | /arf_cmp_d/ /x/ /y/ +--+-- Returns negative, zero, or positive, depending on whether /x/ is+-- respectively smaller, equal, or greater compared to /y/. Comparison with+-- NaN is undefined.+foreign import ccall "arf.h arf_cmp_d"+ arf_cmp_d :: Ptr CArf -> CDouble -> IO CInt++-- | /arf_cmpabs/ /x/ /y/ +--+foreign import ccall "arf.h arf_cmpabs"+ arf_cmpabs :: Ptr CArf -> Ptr CArf -> IO CInt++-- | /arf_cmpabs_ui/ /x/ /y/ +--+foreign import ccall "arf.h arf_cmpabs_ui"+ arf_cmpabs_ui :: Ptr CArf -> CULong -> IO CInt++-- | /arf_cmpabs_d/ /x/ /y/ +--+foreign import ccall "arf.h arf_cmpabs_d"+ arf_cmpabs_d :: Ptr CArf -> CDouble -> IO CInt++-- | /arf_cmpabs_mag/ /x/ /y/ +--+-- Compares the absolute values of /x/ and /y/.+foreign import ccall "arf.h arf_cmpabs_mag"+ arf_cmpabs_mag :: Ptr CArf -> Ptr CMag -> IO CInt++-- | /arf_cmp_2exp_si/ /x/ /e/ +--+foreign import ccall "arf.h arf_cmp_2exp_si"+ arf_cmp_2exp_si :: Ptr CArf -> CLong -> IO CInt++-- | /arf_cmpabs_2exp_si/ /x/ /e/ +--+-- Compares /x/ (respectively its absolute value) with \(2^e\).+foreign import ccall "arf.h arf_cmpabs_2exp_si"+ arf_cmpabs_2exp_si :: Ptr CArf -> CLong -> IO CInt++-- | /arf_sgn/ /x/ +--+-- Returns \(-1\), \(0\) or \(+1\) according to the sign of /x/. The sign+-- of NaN is undefined.+foreign import ccall "arf.h arf_sgn"+ arf_sgn :: Ptr CArf -> IO CInt++-- | /arf_min/ /res/ /a/ /b/ +--+foreign import ccall "arf.h arf_min"+ arf_min :: Ptr CArf -> Ptr CArf -> Ptr CArf -> IO ()++-- | /arf_max/ /res/ /a/ /b/ +--+-- Sets /res/ respectively to the minimum and the maximum of /a/ and /b/.+foreign import ccall "arf.h arf_max"+ arf_max :: Ptr CArf -> Ptr CArf -> Ptr CArf -> IO ()++-- | /arf_bits/ /x/ +--+-- Returns the number of bits needed to represent the absolute value of the+-- mantissa of /x/, i.e. the minimum precision sufficient to represent /x/+-- exactly. Returns 0 if /x/ is a special value.+foreign import ccall "arf.h arf_bits"+ arf_bits :: Ptr CArf -> IO CLong++-- | /arf_is_int/ /x/ +--+-- Returns nonzero iff /x/ is integer-valued.+foreign import ccall "arf.h arf_is_int"+ arf_is_int :: Ptr CArf -> IO CInt++-- | /arf_is_int_2exp_si/ /x/ /e/ +--+-- Returns nonzero iff /x/ equals \(n 2^e\) for some integer /n/.+foreign import ccall "arf.h arf_is_int_2exp_si"+ arf_is_int_2exp_si :: Ptr CArf -> CLong -> IO CInt++-- | /arf_abs_bound_lt_2exp_fmpz/ /res/ /x/ +--+-- Sets /res/ to the smallest integer /b/ such that \(|x| < 2^b\). If /x/+-- is zero, infinity or NaN, the result is undefined.+foreign import ccall "arf.h arf_abs_bound_lt_2exp_fmpz"+ arf_abs_bound_lt_2exp_fmpz :: Ptr CFmpz -> Ptr CArf -> IO ()++-- | /arf_abs_bound_le_2exp_fmpz/ /res/ /x/ +--+-- Sets /res/ to the smallest integer /b/ such that \(|x| \le 2^b\). If /x/+-- is zero, infinity or NaN, the result is undefined.+foreign import ccall "arf.h arf_abs_bound_le_2exp_fmpz"+ arf_abs_bound_le_2exp_fmpz :: Ptr CFmpz -> Ptr CArf -> IO ()++-- | /arf_abs_bound_lt_2exp_si/ /x/ +--+-- Returns the smallest integer /b/ such that \(|x| < 2^b\), clamping the+-- result to lie between -/ARF_PREC_EXACT/ and /ARF_PREC_EXACT/ inclusive.+-- If /x/ is zero, -/ARF_PREC_EXACT/ is returned, and if /x/ is infinity or+-- NaN, /ARF_PREC_EXACT/ is returned.+foreign import ccall "arf.h arf_abs_bound_lt_2exp_si"+ arf_abs_bound_lt_2exp_si :: Ptr CArf -> IO CLong++-- Magnitude functions ---------------------------------------------------------++-- | /arf_get_mag/ /res/ /x/ +--+-- Sets /res/ to an upper bound for the absolute value of /x/.+foreign import ccall "arf.h arf_get_mag"+ arf_get_mag :: Ptr CMag -> Ptr CArf -> IO ()++-- | /arf_get_mag_lower/ /res/ /x/ +--+-- Sets /res/ to a lower bound for the absolute value of /x/.+foreign import ccall "arf.h arf_get_mag_lower"+ arf_get_mag_lower :: Ptr CMag -> Ptr CArf -> IO ()++-- | /arf_set_mag/ /res/ /x/ +--+-- Sets /res/ to /x/. This operation is exact.+foreign import ccall "arf.h arf_set_mag"+ arf_set_mag :: Ptr CArf -> Ptr CMag -> IO ()++-- | /mag_init_set_arf/ /res/ /x/ +--+-- Initializes /res/ and sets it to an upper bound for /x/.+foreign import ccall "arf.h mag_init_set_arf"+ mag_init_set_arf :: Ptr CMag -> Ptr CArf -> IO ()++-- | /mag_fast_init_set_arf/ /res/ /x/ +--+-- Initializes /res/ and sets it to an upper bound for /x/. Assumes that+-- the exponent of /res/ is small (this function is unsafe).+foreign import ccall "arf.h mag_fast_init_set_arf"+ mag_fast_init_set_arf :: Ptr CMag -> Ptr CArf -> IO ()++-- | /arf_mag_set_ulp/ /res/ /x/ /prec/ +--+-- Sets /res/ to the magnitude of the unit in the last place (ulp) of /x/+-- at precision /prec/.+foreign import ccall "arf.h arf_mag_set_ulp"+ arf_mag_set_ulp :: Ptr CMag -> Ptr CArf -> CLong -> IO ()++-- | /arf_mag_add_ulp/ /res/ /x/ /y/ /prec/ +--+-- Sets /res/ to an upper bound for the sum of /x/ and the magnitude of the+-- unit in the last place (ulp) of /y/ at precision /prec/.+foreign import ccall "arf.h arf_mag_add_ulp"+ arf_mag_add_ulp :: Ptr CMag -> Ptr CMag -> Ptr CArf -> CLong -> IO ()++-- | /arf_mag_fast_add_ulp/ /res/ /x/ /y/ /prec/ +--+-- Sets /res/ to an upper bound for the sum of /x/ and the magnitude of the+-- unit in the last place (ulp) of /y/ at precision /prec/. Assumes that+-- all exponents are small.+foreign import ccall "arf.h arf_mag_fast_add_ulp"+ arf_mag_fast_add_ulp :: Ptr CMag -> Ptr CMag -> Ptr CArf -> CLong -> IO ()++-- Shallow assignment ----------------------------------------------------------++-- | /arf_init_set_shallow/ /z/ /x/ +--+foreign import ccall "arf.h arf_init_set_shallow"+ arf_init_set_shallow :: Ptr CArf -> Ptr CArf -> IO ()++-- | /arf_init_set_mag_shallow/ /z/ /x/ +--+-- Initializes /z/ to a shallow copy of /x/. A shallow copy just involves+-- copying struct data (no heap allocation is performed).+-- +-- The target variable /z/ may not be cleared or modified in any way (it+-- can only be used as constant input to functions), and may not be used+-- after /x/ has been cleared. Moreover, after /x/ has been assigned+-- shallowly to /z/, no modification of /x/ is permitted as slong as /z/ is+-- in use.+foreign import ccall "arf.h arf_init_set_mag_shallow"+ arf_init_set_mag_shallow :: Ptr CArf -> Ptr CMag -> IO ()++-- | /arf_init_neg_shallow/ /z/ /x/ +--+foreign import ccall "arf.h arf_init_neg_shallow"+ arf_init_neg_shallow :: Ptr CArf -> Ptr CArf -> IO ()++-- | /arf_init_neg_mag_shallow/ /z/ /x/ +--+-- Initializes /z/ shallowly to the negation of /x/.+foreign import ccall "arf.h arf_init_neg_mag_shallow"+ arf_init_neg_mag_shallow :: Ptr CArf -> Ptr CMag -> IO ()++-- Random number generation ----------------------------------------------------++-- | /arf_randtest/ /res/ /state/ /bits/ /mag_bits/ +--+-- Generates a finite random number whose mantissa has precision at most+-- /bits/ and whose exponent has at most /mag_bits/ bits. The values are+-- distributed non-uniformly: special bit patterns are generated with high+-- probability in order to allow the test code to exercise corner cases.+foreign import ccall "arf.h arf_randtest"+ arf_randtest :: Ptr CArf -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /arf_randtest_not_zero/ /res/ /state/ /bits/ /mag_bits/ +--+-- Identical to @arf_randtest@, except that zero is never produced as an+-- output.+foreign import ccall "arf.h arf_randtest_not_zero"+ arf_randtest_not_zero :: Ptr CArf -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /arf_randtest_special/ /res/ /state/ /bits/ /mag_bits/ +--+-- Identical to @arf_randtest@, except that the output occasionally is set+-- to an infinity or NaN.+foreign import ccall "arf.h arf_randtest_special"+ arf_randtest_special :: Ptr CArf -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /arf_urandom/ /res/ /state/ /bits/ /rnd/ +--+-- Sets /res/ to a uniformly distributed random number in the interval+-- \([0, 1]\). The method uses rounding from integers to floats based on+-- the rounding mode /rnd/.+foreign import ccall "arf.h arf_urandom"+ arf_urandom :: Ptr CArf -> Ptr CFRandState -> CLong -> ArfRnd -> IO ()++-- Input and output ------------------------------------------------------------++-- | /arf_debug/ /x/ +--+-- Prints information about the internal representation of /x/.+foreign import ccall "arf.h arf_debug"+ arf_debug :: Ptr CArf -> IO ()++-- | /arf_print/ /x/ +--+-- Prints /x/ as an integer mantissa and exponent.+foreign import ccall "arf.h arf_print"+ arf_print :: Ptr CArf -> IO ()++-- | /arf_printd/ /x/ /d/ +--+-- Prints /x/ as a decimal floating-point number, rounding to /d/ digits.+-- Rounding is faithful (at most 1 ulp error).+arf_printd :: Ptr CArf -> CLong -> IO ()+arf_printd x digits = do+ cs <- arf_get_str x digits+ s <- peekCString cs+ free cs+ putStr s+ +-- | /arf_get_str/ /x/ /d/ +--+-- Returns /x/ as a decimal floating-point number, rounding to /d/ digits.+-- Rounding is faithful (at most 1 ulp error).+foreign import ccall "arf.h arf_get_str"+ arf_get_str :: Ptr CArf -> CLong -> IO CString++-- | /arf_fprint/ /file/ /x/ +--+-- Prints /x/ as an integer mantissa and exponent to the stream /file/.+foreign import ccall "arf.h arf_fprint"+ arf_fprint :: Ptr CFile -> Ptr CArf -> IO ()++-- | /arf_fprintd/ /file/ /y/ /d/ +--+-- Prints /x/ as a decimal floating-point number to the stream /file/,+-- rounding to /d/ digits. Rounding is faithful (at most 1 ulp error).+foreign import ccall "arf.h arf_fprintd"+ arf_fprintd :: Ptr CFile -> Ptr CArf -> CLong -> IO ()++-- | /arf_dump_str/ /x/ +--+-- Allocates a string and writes a binary representation of /x/ to it that+-- can be read by @arf_load_str@. The returned string needs to be+-- deallocated with /flint_free/.+foreign import ccall "arf.h arf_dump_str"+ arf_dump_str :: Ptr CArf -> IO CString++-- | /arf_load_str/ /x/ /str/ +--+-- Parses /str/ into /x/. Returns a nonzero value if /str/ is not formatted+-- correctly.+foreign import ccall "arf.h arf_load_str"+ arf_load_str :: Ptr CArf -> CString -> IO CInt++-- | /arf_dump_file/ /stream/ /x/ +--+-- Writes a binary representation of /x/ to /stream/ that can be read by+-- @arf_load_file@. Returns a nonzero value if the data could not be+-- written.+foreign import ccall "arf.h arf_dump_file"+ arf_dump_file :: Ptr CFile -> Ptr CArf -> IO CInt++-- | /arf_load_file/ /x/ /stream/ +--+-- Reads /x/ from /stream/. Returns a nonzero value if the data is not+-- formatted correctly or the read failed. Note that the data is assumed to+-- be delimited by a whitespace or end-of-file, i.e., when writing multiple+-- values with @arf_dump_file@ make sure to insert a whitespace to separate+-- consecutive values.+foreign import ccall "arf.h arf_load_file"+ arf_load_file :: Ptr CArf -> Ptr CFile -> IO CInt++-- Addition and multiplication -------------------------------------------------++-- | /arf_abs/ /res/ /x/ +--+-- Sets /res/ to the absolute value of /x/ exactly.+foreign import ccall "arf.h arf_abs"+ arf_abs :: Ptr CArf -> Ptr CArf -> IO ()++-- | /arf_neg/ /res/ /x/ +--+-- Sets /res/ to \(-x\) exactly.+foreign import ccall "arf.h arf_neg"+ arf_neg :: Ptr CArf -> Ptr CArf -> IO ()++-- | /arf_neg_round/ /res/ /x/ /prec/ /rnd/ +--+-- Sets /res/ to \(-x\).+foreign import ccall "arf.h arf_neg_round"+ arf_neg_round :: Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_add/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_add"+ arf_add :: Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_add_si/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_add_si"+ arf_add_si :: Ptr CArf -> Ptr CArf -> CLong -> CLong -> ArfRnd -> IO CInt++-- | /arf_add_ui/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_add_ui"+ arf_add_ui :: Ptr CArf -> Ptr CArf -> CULong -> CLong -> ArfRnd -> IO CInt++-- | /arf_add_fmpz/ /res/ /x/ /y/ /prec/ /rnd/ +--+-- Sets /res/ to \(x + y\).+foreign import ccall "arf.h arf_add_fmpz"+ arf_add_fmpz :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_add_fmpz_2exp/ /res/ /x/ /y/ /e/ /prec/ /rnd/ +--+-- Sets /res/ to \(x + y 2^e\).+foreign import ccall "arf.h arf_add_fmpz_2exp"+ arf_add_fmpz_2exp :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> Ptr CFmpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_sub/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_sub"+ arf_sub :: Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_sub_si/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_sub_si"+ arf_sub_si :: Ptr CArf -> Ptr CArf -> CLong -> CLong -> ArfRnd -> IO CInt++-- | /arf_sub_ui/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_sub_ui"+ arf_sub_ui :: Ptr CArf -> Ptr CArf -> CULong -> CLong -> ArfRnd -> IO CInt++-- | /arf_sub_fmpz/ /res/ /x/ /y/ /prec/ /rnd/ +--+-- Sets /res/ to \(x - y\).+foreign import ccall "arf.h arf_sub_fmpz"+ arf_sub_fmpz :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_mul_2exp_si/ /res/ /x/ /e/ +--+foreign import ccall "arf.h arf_mul_2exp_si"+ arf_mul_2exp_si :: Ptr CArf -> Ptr CArf -> CLong -> IO ()++-- | /arf_mul_2exp_fmpz/ /res/ /x/ /e/ +--+-- Sets /res/ to \(x 2^e\) exactly.+foreign import ccall "arf.h arf_mul_2exp_fmpz"+ arf_mul_2exp_fmpz :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> IO ()++-- | /arf_mul/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_mul_"+ arf_mul :: Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_mul_ui/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_mul_ui"+ arf_mul_ui :: Ptr CArf -> Ptr CArf -> CULong -> CLong -> ArfRnd -> IO CInt++-- | /arf_mul_si/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_mul_si"+ arf_mul_si :: Ptr CArf -> Ptr CArf -> CLong -> CLong -> ArfRnd -> IO CInt++-- | /arf_mul_mpz/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_mul_mpz"+ arf_mul_mpz :: Ptr CArf -> Ptr CArf -> Ptr CMpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_mul_fmpz/ /res/ /x/ /y/ /prec/ /rnd/ +--+-- Sets /res/ to \(x \cdot y\).+foreign import ccall "arf.h arf_mul_fmpz"+ arf_mul_fmpz :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_addmul/ /z/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_addmul"+ arf_addmul :: Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_addmul_ui/ /z/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_addmul_ui"+ arf_addmul_ui :: Ptr CArf -> Ptr CArf -> CULong -> CLong -> ArfRnd -> IO CInt++-- | /arf_addmul_si/ /z/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_addmul_si"+ arf_addmul_si :: Ptr CArf -> Ptr CArf -> CLong -> CLong -> ArfRnd -> IO CInt++-- | /arf_addmul_mpz/ /z/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_addmul_mpz"+ arf_addmul_mpz :: Ptr CArf -> Ptr CArf -> Ptr CMpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_addmul_fmpz/ /z/ /x/ /y/ /prec/ /rnd/ +--+-- Performs a fused multiply-add \(z = z + x \cdot y\), updating /z/+-- in-place.+foreign import ccall "arf.h arf_addmul_fmpz"+ arf_addmul_fmpz :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_submul/ /z/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_submul"+ arf_submul :: Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_submul_ui/ /z/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_submul_ui"+ arf_submul_ui :: Ptr CArf -> Ptr CArf -> CULong -> CLong -> ArfRnd -> IO CInt++-- | /arf_submul_si/ /z/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_submul_si"+ arf_submul_si :: Ptr CArf -> Ptr CArf -> CLong -> CLong -> ArfRnd -> IO CInt++-- | /arf_submul_mpz/ /z/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_submul_mpz"+ arf_submul_mpz :: Ptr CArf -> Ptr CArf -> Ptr CMpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_submul_fmpz/ /z/ /x/ /y/ /prec/ /rnd/ +--+-- Performs a fused multiply-subtract \(z = z - x \cdot y\), updating /z/+-- in-place.+foreign import ccall "arf.h arf_submul_fmpz"+ arf_submul_fmpz :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_fma/ /res/ /x/ /y/ /z/ /prec/ /rnd/ +--+-- Sets /res/ to \(x \cdot y + z\). This is equivalent to an /addmul/+-- except that /res/ and /z/ can be separate variables.+foreign import ccall "arf.h arf_fma"+ arf_fma :: Ptr CArf -> Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_sosq/ /res/ /x/ /y/ /prec/ /rnd/ +--+-- Sets /res/ to \(x^2 + y^2\), rounded to /prec/ bits in the direction+-- specified by /rnd/.+foreign import ccall "arf.h arf_sosq"+ arf_sosq :: Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- Summation -------------------------------------------------------------------++-- | /arf_sum/ /res/ /terms/ /len/ /prec/ /rnd/ +--+-- Sets /res/ to the sum of the array /terms/ of length /len/, rounded to+-- /prec/ bits in the direction specified by /rnd/. The sum is computed as+-- if done without any intermediate rounding error, with only a single+-- rounding applied to the final result. Unlike repeated calls to @arf_add@+-- with infinite precision, this function does not overflow if the+-- magnitudes of the terms are far apart. Warning: this function is+-- implemented naively, and the running time is quadratic with respect to+-- /len/ in the worst case.+foreign import ccall "arf.h arf_sum"+ arf_sum :: Ptr CArf -> Ptr CArf -> CLong -> CLong -> ArfRnd -> IO CInt++-- Dot products ----------------------------------------------------------------++-- | /arf_approx_dot/ /res/ /initial/ /subtract/ /x/ /xstep/ /y/ /ystep/ /len/ /prec/ /rnd/ +--+-- Computes an approximate dot product, with the same meaning of the+-- parameters as @arb_dot@. This operation is not correctly rounded: the+-- final rounding is done in the direction @rnd@ but intermediate roundings+-- are implementation-defined.+foreign import ccall "arf.h arf_approx_dot"+ arf_approx_dot :: Ptr CArf -> Ptr CArf -> CInt -> Ptr CArf -> CLong -> Ptr CArf -> CLong -> CLong -> CLong -> ArfRnd -> IO ()++-- Division --------------------------------------------------------------------++-- | /arf_div/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_div"+ arf_div :: Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_div_ui/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_div_ui"+ arf_div_ui :: Ptr CArf -> Ptr CArf -> CULong -> CLong -> ArfRnd -> IO CInt++-- | /arf_ui_div/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_ui_div"+ arf_ui_div :: Ptr CArf -> CULong -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_div_si/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_div_si"+ arf_div_si :: Ptr CArf -> Ptr CArf -> CLong -> CLong -> ArfRnd -> IO CInt++-- | /arf_si_div/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_si_div"+ arf_si_div :: Ptr CArf -> CLong -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_div_fmpz/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_div_fmpz"+ arf_div_fmpz :: Ptr CArf -> Ptr CArf -> Ptr CFmpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_fmpz_div/ /res/ /x/ /y/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_fmpz_div"+ arf_fmpz_div :: Ptr CArf -> Ptr CFmpz -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_fmpz_div_fmpz/ /res/ /x/ /y/ /prec/ /rnd/ +--+-- Sets /res/ to \(x / y\), rounded to /prec/ bits in the direction+-- specified by /rnd/, returning nonzero iff the operation is inexact. The+-- result is NaN if /y/ is zero.+foreign import ccall "arf.h arf_fmpz_div_fmpz"+ arf_fmpz_div_fmpz :: Ptr CArf -> Ptr CFmpz -> Ptr CFmpz -> CLong -> ArfRnd -> IO CInt++-- Square roots ----------------------------------------------------------------++-- | /arf_sqrt/ /res/ /x/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_sqrt"+ arf_sqrt :: Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_sqrt_ui/ /res/ /x/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_sqrt_ui"+ arf_sqrt_ui :: Ptr CArf -> CULong -> CLong -> ArfRnd -> IO CInt++-- | /arf_sqrt_fmpz/ /res/ /x/ /prec/ /rnd/ +--+-- Sets /res/ to \(\sqrt{x}\). The result is NaN if /x/ is negative.+foreign import ccall "arf.h arf_sqrt_fmpz"+ arf_sqrt_fmpz :: Ptr CArf -> Ptr CFmpz -> CLong -> ArfRnd -> IO CInt++-- | /arf_rsqrt/ /res/ /x/ /prec/ /rnd/ +--+-- Sets /res/ to \(1/\sqrt{x}\). The result is NaN if /x/ is negative, and+-- \(+\infty\) if /x/ is zero.+foreign import ccall "arf.h arf_rsqrt"+ arf_rsqrt :: Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_root/ /res/ /x/ /k/ /prec/ /rnd/ +--+-- Sets /res/ to \(x^{1/k}\). The result is NaN if /x/ is negative.+-- Warning: this function is a wrapper around the MPFR root function. It+-- gets slow and uses much memory for large /k/. Consider working with+-- @arb_root_ui@ for large /k/ instead of using this function directly.+foreign import ccall "arf.h arf_root"+ arf_root :: Ptr CArf -> Ptr CArf -> CULong -> CLong -> ArfRnd -> IO CInt++-- Complex arithmetic ----------------------------------------------------------++-- | /arf_complex_mul/ /e/ /f/ /a/ /b/ /c/ /d/ /prec/ /rnd/ +--+foreign import ccall "arf.h arf_complex_mul"+ arf_complex_mul :: Ptr CArf -> Ptr CArf -> Ptr CArf -> Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_complex_mul_fallback/ /e/ /f/ /a/ /b/ /c/ /d/ /prec/ /rnd/ +--+-- Computes the complex product \(e + fi = (a + bi)(c + di)\), rounding+-- both \(e\) and \(f\) correctly to /prec/ bits in the direction specified+-- by /rnd/. The first bit in the return code indicates inexactness of+-- \(e\), and the second bit indicates inexactness of \(f\).+-- +-- If any of the components /a/, /b/, /c/, /d/ is zero, two real+-- multiplications and no additions are done. This convention is used even+-- if any other part contains an infinity or NaN, and the behavior with+-- infinite\/NaN input is defined accordingly.+-- +-- The /fallback/ version is implemented naively, for testing purposes. No+-- squaring optimization is implemented.+foreign import ccall "arf.h arf_complex_mul_fallback"+ arf_complex_mul_fallback :: Ptr CArf -> Ptr CArf -> Ptr CArf -> Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- | /arf_complex_sqr/ /e/ /f/ /a/ /b/ /prec/ /rnd/ +--+-- Computes the complex square \(e + fi = (a + bi)^2\). This function has+-- identical semantics to @arf_complex_mul@ (with \(c = a, b = d\)), but is+-- faster.+foreign import ccall "arf.h arf_complex_sqr"+ arf_complex_sqr :: Ptr CArf -> Ptr CArf -> Ptr CArf -> Ptr CArf -> CLong -> ArfRnd -> IO CInt++-- Low-level methods -----------------------------------------------------------++-- | /_arf_get_integer_mpn/ /y/ /xp/ /xn/ /exp/ +--+-- Given a floating-point number /x/ represented by /xn/ limbs at /xp/ and+-- an exponent /exp/, writes the integer part of /x/ to /y/, returning+-- whether the result is inexact. The correct number of limbs is written+-- (no limbs are written if the integer part of /x/ is zero). Assumes that+-- @xp[0]@ is nonzero and that the top bit of @xp[xn-1]@ is set.+foreign import ccall "arf.h _arf_get_integer_mpn"+ _arf_get_integer_mpn :: Ptr CMp -> Ptr CMp -> CMpSize -> CLong -> IO CInt++-- | /_arf_set_mpn_fixed/ /z/ /xp/ /xn/ /fixn/ /negative/ /prec/ /rnd/ +--+-- Sets /z/ to the fixed-point number having /xn/ total limbs and /fixn/+-- fractional limbs, negated if /negative/ is set, rounding /z/ to /prec/+-- bits in the direction /rnd/ and returning whether the result is inexact.+-- Both /xn/ and /fixn/ must be nonnegative and not so large that the bit+-- shift would overflow an /slong/, but otherwise no assumptions are made+-- about the input.+foreign import ccall "arf.h _arf_set_mpn_fixed"+ _arf_set_mpn_fixed :: Ptr CArf -> Ptr CMp -> CMpSize -> CMpSize -> CInt -> CLong -> ArfRnd -> IO CInt++-- | /_arf_set_round_ui/ /z/ /x/ /sgnbit/ /prec/ /rnd/ +--+-- Sets /z/ to the integer /x/, negated if /sgnbit/ is 1, rounded to /prec/+-- bits in the direction specified by /rnd/. There are no assumptions on+-- /x/.+foreign import ccall "arf.h _arf_set_round_ui"+ _arf_set_round_ui :: Ptr CArf -> CULong -> CInt -> CLong -> ArfRnd -> IO CInt++-- | /_arf_set_round_uiui/ /z/ /fix/ /hi/ /lo/ /sgnbit/ /prec/ /rnd/ +--+-- Sets the mantissa of /z/ to the two-limb mantissa given by /hi/ and+-- /lo/, negated if /sgnbit/ is 1, rounded to /prec/ bits in the direction+-- specified by /rnd/. Requires that not both /hi/ and /lo/ are zero.+-- Writes the exponent shift to /fix/ without writing the exponent of /z/+-- directly.+foreign import ccall "arf.h _arf_set_round_uiui"+ _arf_set_round_uiui :: Ptr CArf -> Ptr CLong -> CMpLimb -> CMpLimb -> CInt -> CLong -> ArfRnd -> IO CInt++-- | /_arf_set_round_mpn/ /z/ /exp_shift/ /x/ /xn/ /sgnbit/ /prec/ /rnd/ +--+-- Sets the mantissa of /z/ to the mantissa given by the /xn/ limbs in /x/,+-- negated if /sgnbit/ is 1, rounded to /prec/ bits in the direction+-- specified by /rnd/. Returns the inexact flag. Requires that /xn/ is+-- positive and that the top limb of /x/ is nonzero. If /x/ has leading+-- zero bits, writes the shift to /exp_shift/. This method does not write+-- the exponent of /z/ directly. Requires that /x/ does not point to the+-- limbs of /z/.+foreign import ccall "arf.h _arf_set_round_mpn"+ _arf_set_round_mpn :: Ptr CArf -> Ptr CLong -> Ptr CMp -> CMpSize -> CInt -> CLong -> ArfRnd -> IO CInt+
+ src/Data/Number/Flint/Arb/Calc.hs view
@@ -0,0 +1,16 @@+{- |++This module provides functions for operations of calculus over the real+numbers (intended to include root-finding, optimization, integration,+and so on). It is planned that the module will include two types of+algorithms:++Any algorithms of the second kind will be clearly marked as such.+++-}+module Data.Number.Flint.Arb.Calc (+ module Data.Number.Flint.Arb.Calc.FFI+ ) where++import Data.Number.Flint.Arb.Calc.FFI
+ src/Data/Number/Flint/Arb/Calc/FFI.hsc view
@@ -0,0 +1,280 @@+{-|+module : Data.Number.Flint.Arb.Calc.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Arb.Calc.FFI (+ -- * Calculus with real-valued functions+ ArfInterval (..)+ , CArfInterval (..)+ , newArfInterval+ , withArfInterval+ , CArbCalcFunc+ , arf_interval_init+ , arf_interval_clear+ , _arf_interval_vec_init+ , _arf_interval_vec_clear+ , arf_interval_set+ , arf_interval_swap+ , arf_interval_get_arb+ , arf_interval_printd+ , arf_interval_fprintd+ , arb_calc_isolate_roots+ , arb_calc_refine_root_bisect+ -- * Newton-based root finding+ , arb_calc_newton_conv_factor+ , arb_calc_newton_step+ , arb_calc_refine_root_newton+) where++-- Calculus with real-valued functions -----------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, nullPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Int ( Int64 )+import Data.Functor ((<&>))++import Data.Number.Flint.Flint+import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.Types++#include <flint/flint.h>+#include <flint/arf_types.h>++-- arf_interval_t --------------------------------------------------------------++data ArfInterval = ArfInterval {-# UNPACK #-} !(ForeignPtr CArfInterval)+data CArfInterval = CArfInterval CArf CArf++instance Storable CArfInterval where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size arf_interval_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment arf_interval_t}+ peek = error "CArfInterval.peek: Not defined"+ poke = error "CArfInterval.poke: Not defined"++-- | Create a new `ArfInterval` structure.+newArfInterval = do+ x <- mallocForeignPtr+ withForeignPtr x arf_interval_init+ addForeignPtrFinalizer p_arf_interval_clear x+ return $ ArfInterval x++-- | Use `ArfInterval` structure.+{-# INLINE withArfInterval #-}+withArfInterval (ArfInterval x) f =+ withForeignPtr x $ \xp -> f xp <&> (ArfInterval x,)++-- | Use new `ArfInterval` structure.+{-# INLINE withNewArfInterval #-}+withNewArfInterval f = newArfInterval >>= flip withArfInterval f++-- arb_calc_func_t -------------------------------------------------------------++type CArbCalcFunc = Ptr CArb -> Ptr CArb -> Ptr () -> CLong -> CLong++-- Subdivision-based root finding ----------------------------------------------++-- | /arf_interval_init/ /v/ ++foreign import ccall "arb_calc.h arf_interval_init_"+ arf_interval_init :: Ptr CArfInterval -> IO ()++-- | /arf_interval_clear/ /v/ ++foreign import ccall "arb_calc.h arf_interval_clear_"+ arf_interval_clear :: Ptr CArfInterval -> IO ()++foreign import ccall "arb_calc.h &arf_interval_clear_"+ p_arf_interval_clear :: FunPtr (Ptr CArfInterval -> IO ())++-- | /_arf_interval_vec_init/ /n/ ++foreign import ccall "arb_calc.h _arf_interval_vec_init_"+ _arf_interval_vec_init :: CLong -> IO (Ptr CArfInterval)++-- | /_arf_interval_vec_clear/ /v/ /n/ ++foreign import ccall "arb_calc.h _arf_interval_vec_clear_"+ _arf_interval_vec_clear :: Ptr CArfInterval -> CLong -> IO ()++-- | /arf_interval_set/ /v/ /u/ ++foreign import ccall "arb_calc.h arf_interval_set_"+ arf_interval_set :: Ptr CArfInterval -> Ptr CArfInterval -> IO ()++-- | /arf_interval_swap/ /v/ /u/ ++foreign import ccall "arb_calc.h arf_interval_swap_"+ arf_interval_swap :: Ptr CArfInterval -> Ptr CArfInterval -> IO ()++-- | /arf_interval_get_arb/ /x/ /v/ /prec/ ++foreign import ccall "arb_calc.h arf_interval_get_arb_"+ arf_interval_get_arb :: Ptr CArb -> Ptr CArfInterval -> CLong -> IO ()++foreign import ccall "arb_calc.h arf_interval_get_strd"+ arf_interval_get_strd :: Ptr CArfInterval -> CLong -> IO CString++-- | /arf_interval_printd/ /v/ /n/ +--+-- Helper functions for endpoint-based intervals.+arf_interval_printd :: Ptr CArfInterval -> CLong -> IO ()+arf_interval_printd x digits = do+ printCStr (`arf_interval_get_strd` digits) x+ return ()++-- | /arf_interval_fprintd/ /file/ /v/ /n/ +--+-- Helper functions for endpoint-based intervals.+foreign import ccall "arb_calc.h arf_interval_fprintd"+ arf_interval_fprintd :: Ptr CFile -> Ptr CArfInterval -> CLong -> IO ()++-- | /arb_calc_isolate_roots/ /found/ /flags/ /func/ /param/ /interval/ /maxdepth/ /maxeval/ /maxfound/ /prec/ +--+-- Rigorously isolates single roots of a real analytic function on the+-- interior of an interval.+-- +-- This routine writes an array of /n/ interesting subintervals of+-- /interval/ to /found/ and corresponding flags to /flags/, returning the+-- integer /n/. The output has the following properties:+-- +-- - The function has no roots on /interval/ outside of the output+-- subintervals.+-- - Subintervals are sorted in increasing order (with no overlap except+-- possibly starting and ending with the same point).+-- - Subintervals with a flag of 1 contain exactly one (single) root.+-- - Subintervals with any other flag may or may not contain roots.+-- +-- If no flags other than 1 occur, all roots of the function on /interval/+-- have been isolated. If there are output subintervals on which the+-- existence or nonexistence of roots could not be determined, the user may+-- attempt further searches on those subintervals (possibly with increased+-- precision and\/or increased bounds for the breaking criteria). Note that+-- roots of multiplicity higher than one and roots located exactly at+-- endpoints cannot be isolated by the algorithm.+-- +-- The following breaking criteria are implemented:+-- +-- - At most /maxdepth/ recursive subdivisions are attempted. The+-- smallest details that can be distinguished are therefore about+-- \(2^{-\text{maxdepth}}\) times the width of /interval/. A typical,+-- reasonable value might be between 20 and 50.+-- - If the total number of tested subintervals exceeds /maxeval/, the+-- algorithm is terminated and any untested subintervals are added to+-- the output. The total number of calls to /func/ is thereby+-- restricted to a small multiple of /maxeval/ (the actual count can be+-- slightly higher depending on implementation details). A typical,+-- reasonable value might be between 100 and 100000.+-- - The algorithm terminates if /maxfound/ roots have been isolated. In+-- particular, setting /maxfound/ to 1 can be used to locate just one+-- root of the function even if there are numerous roots. To try to+-- find all roots, /LONG_MAX/ may be passed.+-- +-- The argument /prec/ denotes the precision used to evaluate the function.+-- It is possibly also used for some other arithmetic operations performed+-- internally by the algorithm. Note that it probably does not make sense+-- for /maxdepth/ to exceed /prec/.+-- +-- Warning: it is assumed that subdivision points of /interval/ can be+-- represented exactly as floating-point numbers in memory. Do not pass+-- \(1 \pm 2^{-10^{100}}\) as input.+foreign import ccall "arb_calc.h arb_calc_isolate_roots"+ arb_calc_isolate_roots :: Ptr (Ptr CArfInterval) -> Ptr (Ptr CInt) -> FunPtr CArbCalcFunc -> Ptr () -> Ptr CArfInterval -> CLong -> CLong -> CLong -> CLong -> IO CLong++-- | /arb_calc_refine_root_bisect/ /r/ /func/ /param/ /start/ /iter/ /prec/ +--+-- Given an interval /start/ known to contain a single root of /func/,+-- refines it using /iter/ bisection steps. The algorithm can return a+-- failure code if the sign of the function at an evaluation point is+-- ambiguous. The output /r/ is set to a valid isolating interval (possibly+-- just /start/) even if the algorithm fails.+foreign import ccall "arb_calc.h arb_calc_refine_root_bisect"+ arb_calc_refine_root_bisect :: Ptr CArfInterval -> FunPtr CArbCalcFunc -> Ptr () -> Ptr CArfInterval -> CLong -> CLong -> IO CInt++-- Newton-based root finding ---------------------------------------------------++-- | /arb_calc_newton_conv_factor/ /conv_factor/ /func/ /param/ /conv_region/ /prec/ +--+-- Given an interval \(I\) specified by /conv_region/, evaluates a bound+-- for \(C = \sup_{t,u \in I} \frac{1}{2} |f''(t)| / |f'(u)|\), where \(f\)+-- is the function specified by /func/ and /param/. The bound is obtained+-- by evaluating \(f'(I)\) and \(f''(I)\) directly. If \(f\) is+-- ill-conditioned, \(I\) may need to be extremely precise in order to get+-- an effective, finite bound for /C/.+foreign import ccall "arb_calc.h arb_calc_newton_conv_factor"+ arb_calc_newton_conv_factor :: Ptr CArf -> FunPtr CArbCalcFunc -> Ptr () -> Ptr CArb -> CLong -> IO ()++-- | /arb_calc_newton_step/ /xnew/ /func/ /param/ /x/ /conv_region/ /conv_factor/ /prec/ +--+-- Performs a single step with an interval version of Newton\'s method. The+-- input consists of the function \(f\) specified by /func/ and /param/, a+-- ball \(x = [m-r, m+r]\) known to contain a single root of \(f\), a ball+-- \(I\) (/conv_region/) containing \(x\) with an associated bound+-- (/conv_factor/) for+-- \(C = \sup_{t,u \in I} \frac{1}{2} |f''(t)| / |f'(u)|\), and a working+-- precision /prec/.+-- +-- The Newton update consists of setting \(x' = [m'-r', m'+r']\) where+-- \(m' = m - f(m) / f'(m)\) and \(r' = C r^2\). The expression+-- \(m - f(m) / f'(m)\) is evaluated using ball arithmetic at a working+-- precision of /prec/ bits, and the rounding error during this evaluation+-- is accounted for in the output. We now check that \(x' \in I\) and+-- \(r' < r\). If both conditions are satisfied, we set /xnew/ to \(x'\)+-- and return /ARB_CALC_SUCCESS/. If either condition fails, we set /xnew/+-- to \(x\) and return /ARB_CALC_NO_CONVERGENCE/, indicating that no+-- progress is made.+foreign import ccall "arb_calc.h arb_calc_newton_step"+ arb_calc_newton_step :: Ptr CArb+ -> FunPtr CArbCalcFunc+ -> Ptr ()+ -> Ptr CArb+ -> Ptr CArb+ -> Ptr CArf+ -> CLong+ -> IO CInt++-- | /arb_calc_refine_root_newton/ /r/ /func/ /param/ /start/ /conv_region/ /conv_factor/ /eval_extra_prec/ /prec/ +--+-- Refines a precise estimate of a single root of a function to high+-- precision by performing several Newton steps, using nearly optimally+-- chosen doubling precision steps.+-- +-- The inputs are defined as for /arb_calc_newton_step/, except for the+-- precision parameters: /prec/ is the target accuracy and+-- /eval_extra_prec/ is the estimated number of guard bits that need to be+-- added to evaluate the function accurately close to the root (for+-- example, if the function is a polynomial with large coefficients of+-- alternating signs and Horner\'s rule is used to evaluate it, the extra+-- precision should typically be approximately the bit size of the+-- coefficients).+-- +-- This function returns /ARB_CALC_SUCCESS/ if all attempted Newton steps+-- are successful (note that this does not guarantee that the computed root+-- is accurate to /prec/ bits, which has to be verified by the user), only+-- that it is more accurate than the starting ball.+-- +-- On failure, /ARB_CALC_IMPRECISE_INPUT/ or /ARB_CALC_NO_CONVERGENCE/ may+-- be returned. In this case, /r/ is set to a ball for the root which is+-- valid but likely does have full accuracy (it can possibly just be equal+-- to the starting ball).+foreign import ccall "arb_calc.h arb_calc_refine_root_newton"+ arb_calc_refine_root_newton :: Ptr CArb+ -> FunPtr CArbCalcFunc+ -> Ptr ()+ -> Ptr CArb+ -> Ptr CArb+ -> Ptr CArf+ -> CLong+ -> CLong+ -> IO CInt+
+ src/Data/Number/Flint/Arb/FFI.hsc view
@@ -0,0 +1,2868 @@+{-|+module : Data.Number.Flint.Arb.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Arb.FFI (+ -- * Real numbers+ Arb (..)+ , CArb (..)+ , newArb+ , newArbFromFmpz+ , newArbFromFmpq+ , withArb+ , withNewArb+ , withNewArbFromFmpz+ , withNewArbFromFmpq+ -- * Memory management+ , arb_init+ , arb_clear+ , arb_midref+ , _arb_vec_init+ , _arb_vec_clear+ , arb_swap+ , arb_allocated_bytes+ , _arb_vec_allocated_bytes+ , _arb_vec_estimate_allocated_bytes+ -- * Assignment and rounding+ , arb_set+ , arb_set_arf+ , arb_set_si+ , arb_set_ui+ , arb_set_d+ , arb_set_fmpz+ , arb_set_fmpz_2exp+ , arb_set_round+ , arb_set_round_fmpz+ , arb_set_round_fmpz_2exp+ , arb_set_fmpq+ , arb_set_str+ , arb_get_str+ , arb_get_strd+ , arb_get_strn+ -- * Assignment of special values+ , arb_zero+ , arb_one+ , arb_pos_inf+ , arb_neg_inf+ , arb_zero_pm_inf+ , arb_indeterminate+ , arb_zero_pm_one+ , arb_unit_interval+ -- * Input and output+ , ArbStrOption (..)+ -- | Default print option+ , arb_str_none+ -- | If /arb_str_more/ is added to flags, more (possibly incorrect)+ -- digits may be printed+ , arb_str_more+ -- | If /arb_str_no_radius/ is added to /flags/, the radius is not+ -- included in the output if at least 1 digit of the midpoint can be+ -- printed.+ , arb_str_no_radius+ -- | By adding a multiple m of /arb_str_condense/ to /flags/, strings of+ -- more than three times m consecutive digits are condensed, only+ -- printing the leading and trailing m digits along with brackets+ -- indicating the number of digits omitted (useful when computing+ -- values to extremely high precision).+ , arb_str_condense+ , arb_print+ , arb_fprint+ , arb_printd+ , arb_fprintd+ , arb_printn+ , arb_fprintn+ , arb_dump_str+ , arb_load_str+ , arb_dump_file+ , arb_load_file+ -- * Random number generation+ , arb_randtest+ , arb_randtest_exact+ , arb_randtest_precise+ , arb_randtest_wide+ , arb_randtest_special+ , arb_get_rand_fmpq+ , arb_urandom+ -- * Radius and interval operations+ , arb_get_mid_arb+ , arb_get_rad_arb+ , arb_add_error_arf+ , arb_add_error_mag+ , arb_add_error+ , arb_add_error_2exp_si+ , arb_add_error_2exp_fmpz+ , arb_union+ , arb_intersection+ , arb_nonnegative_part+ , arb_get_abs_ubound_arf+ , arb_get_abs_lbound_arf+ , arb_get_ubound_arf+ , arb_get_lbound_arf+ , arb_get_mag+ , arb_get_mag_lower+ , arb_get_mag_lower_nonnegative+ , arb_get_interval_fmpz_2exp+ , arb_set_interval_mag+ , arb_set_interval_arf+ , arb_set_interval_mpfr+ , arb_set_interval_neg_pos_mag+ , arb_get_interval_arf+ , arb_get_interval_mpfr+ , arb_rel_error_bits+ , arb_rel_accuracy_bits+ , arb_rel_one_accuracy_bits+ , arb_bits+ , arb_trim+ , arb_get_unique_fmpz+ , arb_floor+ , arb_get_fmpz_mid_rad_10exp+ , arb_can_round_arf+ , arb_can_round_mpfr+ -- * Comparisons+ , arb_is_zero+ , arb_is_nonzero+ , arb_is_one+ , arb_is_finite+ , arb_is_exact+ , arb_is_int+ , arb_is_int_2exp_si+ , arb_equal+ , arb_equal_si+ , arb_is_positive+ , arb_is_nonnegative+ , arb_is_negative+ , arb_is_nonpositive+ , arb_overlaps+ , arb_contains_arf+ , arb_contains_fmpq+ , arb_contains_fmpz+ , arb_contains_si+ , arb_contains_mpfr+ , arb_contains+ , arb_contains_int+ , arb_contains_zero+ , arb_contains_negative+ , arb_contains_nonpositive+ , arb_contains_positive+ , arb_contains_nonnegative+ , arb_contains_interior+ , arb_eq+ , arb_ne+ , arb_lt+ , arb_le+ , arb_gt+ , arb_ge+ -- * Arithmetic+ , arb_neg+ , arb_neg_round+ , arb_abs+ , arb_nonnegative_abs+ , arb_sgn+ , arb_sgn_nonzero+ , arb_min+ , arb_max+ , arb_add+ , arb_add_arf+ , arb_add_ui+ , arb_add_si+ , arb_add_fmpz+ , arb_add_fmpz_2exp+ , arb_sub+ , arb_sub_arf+ , arb_sub_ui+ , arb_sub_si+ , arb_sub_fmpz+ , arb_mul+ , arb_mul_arf+ , arb_mul_si+ , arb_mul_ui+ , arb_mul_fmpz+ , arb_mul_2exp_si+ , arb_mul_2exp_fmpz+ , arb_addmul+ , arb_addmul_arf+ , arb_addmul_si+ , arb_addmul_ui+ , arb_addmul_fmpz+ , arb_submul+ , arb_submul_arf+ , arb_submul_si+ , arb_submul_ui+ , arb_submul_fmpz+ , arb_fma+ , arb_inv+ , arb_div+ , arb_div_arf+ , arb_div_si+ , arb_div_ui+ , arb_div_fmpz+ , arb_fmpz_div_fmpz+ , arb_ui_div+ , arb_div_2expm1_ui+ -- * Dot product+ , arb_dot_precise+ , arb_approx_dot+ , arb_dot_ui+ -- * Powers and roots+ , arb_sqrt+ , arb_sqrt_arf+ , arb_sqrt_fmpz+ , arb_sqrt_ui+ , arb_sqrtpos+ , arb_hypot+ , arb_rsqrt+ , arb_rsqrt_ui+ , arb_sqrt1pm1+ , arb_root_ui+ , arb_root+ , arb_sqr+ , arb_pow_fmpz_binexp+ , arb_pow_fmpz+ , arb_pow_ui+ , arb_ui_pow_ui+ , arb_si_pow_ui+ , arb_pow_fmpq+ , arb_pow+ -- * Exponentials and logarithms+ , arb_log_ui+ , arb_log_fmpz+ , arb_log_arf+ , arb_log+ , arb_log_ui_from_prev+ , arb_log1p+ , arb_log_base_ui+ , arb_log_hypot+ , arb_exp+ , arb_expm1+ , arb_exp_invexp+ -- * Trigonometric functions+ , arb_sin+ , arb_cos+ , arb_sin_cos+ , arb_sin_pi+ , arb_cos_pi+ , arb_sin_cos_pi+ , arb_tan+ , arb_cot+ , arb_sin_cos_pi_fmpq+ , arb_sin_pi_fmpq+ , arb_cos_pi_fmpq+ , arb_tan_pi+ , arb_cot_pi+ , arb_sec+ , arb_csc+ , arb_csc_pi+ , arb_sinc+ , arb_sinc_pi+ -- * Inverse trigonometric functions+ , arb_atan_arf+ , arb_atan+ , arb_atan2+ , arb_asin+ , arb_acos+ -- * Hyperbolic functions+ , arb_sinh+ , arb_cosh+ , arb_sinh_cosh+ , arb_tanh+ , arb_coth+ , arb_sech+ , arb_csch+ -- * Inverse hyperbolic functions+ , arb_atanh+ , arb_asinh+ , arb_acosh+ -- * Constants+ , arb_const_pi+ , arb_const_sqrt_pi+ , arb_const_log_sqrt2pi+ , arb_const_log2+ , arb_const_log10+ , arb_const_euler+ , arb_const_catalan+ , arb_const_e+ , arb_const_khinchin+ , arb_const_glaisher+ , arb_const_apery+ -- * Lambert W function+ , arb_lambertw+ -- * Gamma function and factorials+ , arb_rising_ui+ , arb_rising_fmpq_ui+ , arb_fac_ui+ , arb_doublefac_ui+ , arb_bin_ui+ , arb_bin_uiui+ , arb_gamma+ , arb_lgamma+ , arb_rgamma+ , arb_digamma+ -- * Zeta function+ , arb_zeta_ui_vec_borwein+ , arb_zeta_ui_asymp+ , arb_zeta_ui_euler_product+ , arb_zeta_ui_bernoulli+ , arb_zeta_ui_borwein_bsplit+ , arb_zeta_ui_vec+ , arb_zeta_ui_vec_even+ , arb_zeta_ui_vec_odd+ , arb_zeta_ui+ , arb_zeta+ , arb_hurwitz_zeta+ -- * Bernoulli numbers and polynomials+ , arb_bernoulli_ui+ , arb_bernoulli_fmpz+ , arb_bernoulli_ui_zeta+ , arb_bernoulli_poly_ui+ , arb_power_sum_vec+ -- * Polylogarithms+ , arb_polylog+ , arb_polylog_si+ -- * Other special functions+ , arb_fib_fmpz+ , arb_agm+ , arb_chebyshev_t_ui+ , arb_chebyshev_u_ui+ , arb_chebyshev_t2_ui+ , arb_chebyshev_u2_ui+ , arb_bell_sum_bsplit+ , arb_bell_sum_taylor+ , arb_bell_fmpz+ , arb_bell_ui+ , arb_euler_number_fmpz+ , arb_fmpz_euler_number_ui_multi_mod+ , arb_partitions_fmpz+ , arb_partitions_ui+ , arb_primorial_nth_ui+ , arb_primorial_ui+ -- * Internals for computing elementary functions+ , _arb_atan_taylor_naive+ , _arb_atan_taylor_rs+ , _arb_exp_taylor_naive+ , _arb_exp_taylor_rs+ , _arb_sin_cos_taylor_naive+ , _arb_sin_cos_taylor_rs+ , _arb_get_mpn_fixed_mod_log2+ , _arb_get_mpn_fixed_mod_pi4+ , _arb_exp_taylor_bound+ , arb_exp_arf_bb+ , _arb_exp_sum_bs_simple+ , _arb_exp_sum_bs_powtab+ , arb_exp_arf_rs_generic+ , _arb_atan_sum_bs_simple+ , _arb_atan_sum_bs_powtab+ , arb_atan_arf_bb+ , arb_atan_frac_bsplit+ , arb_sin_cos_arf_generic+ , arb_sin_cos_arf_bb+ , arb_sin_cos_wide+ , arb_sin_cos_generic+ , arb_log_primes_vec_bsplit+ , _arb_log_p_ensure_cached+ , arb_exp_arf_log_reduction+ , arb_exp_arf_generic+ , arb_exp_arf+ , arb_log_newton+ , arb_atan_gauss_primes_vec_bsplit+ , _arb_atan_gauss_p_ensure_cached+ , arb_sin_cos_arf_atan_reduction+ , arb_atan_newton+ -- * Vector functions+ , _arb_vec_zero+ , _arb_vec_is_zero+ , _arb_vec_is_finite+ , _arb_vec_set+ , _arb_vec_set_round+ , _arb_vec_swap+ , _arb_vec_neg+ , _arb_vec_sub+ , _arb_vec_add+ , _arb_vec_scalar_mul+ , _arb_vec_scalar_div+ , _arb_vec_scalar_mul_fmpz+ , _arb_vec_scalar_mul_2exp_si+ , _arb_vec_scalar_addmul+ , _arb_vec_get_mag+ , _arb_vec_bits+ , _arb_vec_set_powers+ , _arb_vec_add_error_arf_vec+ , _arb_vec_add_error_mag_vec+ , _arb_vec_indeterminate+ , _arb_vec_trim+ , _arb_vec_get_unique_fmpz_vec+) where++-- Real numbers ----------------------------------------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Alloc ++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Arb.Types++#include <flint/arb.h>++-- Types -----------------------------------------------------------------------++newArb = do+ x <- mallocForeignPtr+ withForeignPtr x arb_init+ addForeignPtrFinalizer p_arb_clear x+ return $ Arb x++newArbFromFmpz value = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ arb_init x+ withFmpz value $ \value -> do+ arb_set_fmpz x value+ addForeignPtrFinalizer p_arb_clear x+ return $ Arb x++newArbFromFmpq value prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ arb_init x+ withFmpq value $ \value -> do+ arb_set_fmpq x value prec+ addForeignPtrFinalizer p_arb_clear x+ return $ Arb x++withArb (Arb p) f = do+ withForeignPtr p $ \fp -> (Arb p,) <$> f fp++withNewArb f = do+ x <- newArb+ withArb x f++withNewArbFromFmpz value f = do+ x <- newArbFromFmpz value+ withArb x f++withNewArbFromFmpq value prec f = do+ x <- newArbFromFmpq value prec+ withArb x f++-- Memory management -----------------------------------------------------------++-- | /arb_init/ /x/ +-- +-- Initializes the variable /x/ for use. Its midpoint and radius are both+-- set to zero.+foreign import ccall "arb.h arb_init"+ arb_init :: Ptr CArb -> IO ()++-- | /arb_clear/ /x/ +-- +-- Clears the variable /x/, freeing or recycling its allocated memory.+foreign import ccall "arb.h arb_clear"+ arb_clear :: Ptr CArb -> IO ()++foreign import ccall "arb.h &arb_clear"+ p_arb_clear :: FunPtr (Ptr CArb -> IO ())++foreign import ccall "arb.h arb_midref_"+ arb_midref :: Ptr CArb -> IO (Ptr CArf)+ +-- | /_arb_vec_init/ /n/ +-- +-- Returns a pointer to an array of /n/ initialized @arb_struct@ entries.+foreign import ccall "arb.h _arb_vec_init"+ _arb_vec_init :: CLong -> IO (Ptr CArb)++-- | /_arb_vec_clear/ /v/ /n/ +-- +-- Clears an array of /n/ initialized @arb_struct@ entries.+foreign import ccall "arb.h _arb_vec_clear"+ _arb_vec_clear :: Ptr CArb -> CLong -> IO ()++-- | /arb_swap/ /x/ /y/ +-- +-- Swaps /x/ and /y/ efficiently.+foreign import ccall "arb.h arb_swap"+ arb_swap :: Ptr CArb -> Ptr CArb -> IO ()++-- | /arb_allocated_bytes/ /x/ +-- +-- Returns the total number of bytes heap-allocated internally by this+-- object. The count excludes the size of the structure itself. Add+-- @sizeof(arb_struct)@ to get the size of the object as a whole.+foreign import ccall "arb.h arb_allocated_bytes"+ arb_allocated_bytes :: Ptr CArb -> IO CLong++-- | /_arb_vec_allocated_bytes/ /vec/ /len/ +-- +-- Returns the total number of bytes allocated for this vector, i.e. the+-- space taken up by the vector itself plus the sum of the internal heap+-- allocation sizes for all its member elements.+foreign import ccall "arb.h _arb_vec_allocated_bytes"+ _arb_vec_allocated_bytes :: Ptr CArb -> CLong -> IO CLong++-- | /_arb_vec_estimate_allocated_bytes/ /len/ /prec/ +-- +-- Estimates the number of bytes that need to be allocated for a vector of+-- /len/ elements with /prec/ bits of precision, including the space for+-- internal limb data. This function returns a /double/ to avoid overflow+-- issues when both /len/ and /prec/ are large.+-- +-- This is only an approximation of the physical memory that will be used+-- by an actual vector. In practice, the space varies with the content of+-- the numbers; for example, zeros and small integers require no internal+-- heap allocation even if the precision is huge. The estimate assumes that+-- exponents will not be bignums. The actual amount may also be higher or+-- lower due to overhead in the memory allocator or overcommitment by the+-- operating system.+foreign import ccall "arb.h _arb_vec_estimate_allocated_bytes"+ _arb_vec_estimate_allocated_bytes :: CLong -> CLong -> IO CDouble++-- Assignment and rounding -----------------------------------------------------++foreign import ccall "arb.h arb_set"+ arb_set :: Ptr CArb -> Ptr CArb -> IO ()++foreign import ccall "arb.h arb_set_arf"+ arb_set_arf :: Ptr CArb -> Ptr CArf -> IO ()++foreign import ccall "arb.h arb_set_si"+ arb_set_si :: Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_set_ui"+ arb_set_ui :: Ptr CArb -> CULong -> IO ()++foreign import ccall "arb.h arb_set_d"+ arb_set_d :: Ptr CArb -> CDouble -> IO ()++-- | /arb_set_fmpz/ /y/ /x/ +-- +-- Sets /y/ to the value of /x/ without rounding.+foreign import ccall "arb.h arb_set_fmpz"+ arb_set_fmpz :: Ptr CArb -> Ptr CFmpz -> IO ()++-- | /arb_set_fmpz_2exp/ /y/ /x/ /e/ +-- +-- Sets /y/ to \(x \cdot 2^e\).+foreign import ccall "arb.h arb_set_fmpz_2exp"+ arb_set_fmpz_2exp :: Ptr CArb -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "arb.h arb_set_round"+ arb_set_round :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_set_round_fmpz/ /y/ /x/ /prec/ +-- +-- Sets /y/ to the value of /x/, rounded to /prec/ bits in the direction+-- towards zero.+foreign import ccall "arb.h arb_set_round_fmpz"+ arb_set_round_fmpz :: Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_set_round_fmpz_2exp/ /y/ /x/ /e/ /prec/ +-- +-- Sets /y/ to \(x \cdot 2^e\), rounded to /prec/ bits in the direction+-- towards zero.+foreign import ccall "arb.h arb_set_round_fmpz_2exp"+ arb_set_round_fmpz_2exp :: Ptr CArb -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_set_fmpq/ /y/ /x/ /prec/ +-- +-- Sets /y/ to the rational number /x/, rounded to /prec/ bits in the+-- direction towards zero.+foreign import ccall "arb.h arb_set_fmpq"+ arb_set_fmpq :: Ptr CArb -> Ptr CFmpq -> CLong -> IO ()++-- | /arb_set_str/ /res/ /inp/ /prec/ +-- +-- Sets /res/ to the value specified by the human-readable string /inp/.+-- The input may be a decimal floating-point literal, such as \"25\",+-- \"0.001\", \"7e+141\" or \"-31.4159e-1\", and may also consist of two+-- such literals separated by the symbol \"+\/-\" and optionally enclosed+-- in brackets, e.g. \"[3.25 +\/- 0.0001]\", or simply \"[+\/- 10]\" with+-- an implicit zero midpoint. The output is rounded to /prec/ bits, and if+-- the binary-to-decimal conversion is inexact, the resulting error is+-- added to the radius.+-- +-- The symbols \"inf\" and \"nan\" are recognized (a nan midpoint results+-- in an indeterminate interval, with infinite radius).+-- +-- Returns 0 if successful and nonzero if unsuccessful. If unsuccessful,+-- the result is set to an indeterminate interval.+foreign import ccall "arb.h arb_set_str"+ arb_set_str :: Ptr CArb -> CString -> CLong -> IO CInt++-- | /arb_get_str/ /x/ /n/ /flags/ +-- +-- Returns a nice human-readable representation of /x/, with at most /n/+-- digits of the midpoint printed.+-- +-- With default flags, the output can be parsed back with @arb_set_str@,+-- and this is guaranteed to produce an interval containing the original+-- interval /x/.+-- +-- By default, the output is rounded so that the value given for the+-- midpoint is correct up to 1 ulp (unit in the last decimal place).+-- +-- If /ARB_STR_MORE/ is added to /flags/, more (possibly incorrect) digits+-- may be printed.+-- +-- If /ARB_STR_NO_RADIUS/ is added to /flags/, the radius is not included+-- in the output. Unless /ARB_STR_MORE/ is set, the output is rounded so+-- that the midpoint is correct to 1 ulp. As a special case, if there are+-- no significant digits after rounding, the result will be shown as+-- @0e+n@, meaning that the result is between @-1e+n@ and @1e+n@ (following+-- the contract that the output is correct to within one unit in the only+-- shown digit).+-- +-- By adding a multiple /m/ of /ARB_STR_CONDENSE/ to /flags/, strings of+-- more than three times /m/ consecutive digits are condensed, only+-- printing the leading and trailing /m/ digits along with brackets+-- indicating the number of digits omitted (useful when computing values to+-- extremely high precision).+foreign import ccall "arb.h arb_get_str"+ arb_get_str :: Ptr CArb -> CLong -> ArbStrOption -> IO CString++foreign import ccall "arb.h arb_get_strd"+ arb_get_strd :: Ptr CArb -> CLong -> IO CString++foreign import ccall "arb.h arb_get_strn"+ arb_get_strn :: Ptr CArb -> CLong -> IO CString++foreign import ccall "arb.h arb_get_str_"+ arb_get_str_ :: Ptr CArb -> IO CString++-- Assignment of special values ------------------------------------------------++-- | /arb_zero/ /x/ +-- +-- Sets /x/ to zero.+foreign import ccall "arb.h arb_zero"+ arb_zero :: Ptr CArb -> IO ()++-- | /arb_one/ /f/ +-- +-- Sets /x/ to the exact integer 1.+foreign import ccall "arb.h arb_one"+ arb_one :: Ptr CArb -> IO ()++-- | /arb_pos_inf/ /x/ +-- +-- Sets /x/ to positive infinity, with a zero radius.+foreign import ccall "arb.h arb_pos_inf"+ arb_pos_inf :: Ptr CArb -> IO ()++-- | /arb_neg_inf/ /x/ +-- +-- Sets /x/ to negative infinity, with a zero radius.+foreign import ccall "arb.h arb_neg_inf"+ arb_neg_inf :: Ptr CArb -> IO ()++-- | /arb_zero_pm_inf/ /x/ +-- +-- Sets /x/ to \([0 \pm \infty]\), representing the whole extended real+-- line.+foreign import ccall "arb.h arb_zero_pm_inf"+ arb_zero_pm_inf :: Ptr CArb -> IO ()++-- | /arb_indeterminate/ /x/ +-- +-- Sets /x/ to \([\operatorname{NaN} \pm \infty]\), representing an+-- indeterminate result.+foreign import ccall "arb.h arb_indeterminate"+ arb_indeterminate :: Ptr CArb -> IO ()++-- | /arb_zero_pm_one/ /x/ +-- +-- Sets /x/ to the interval \([0 \pm 1]\).+foreign import ccall "arb.h arb_zero_pm_one"+ arb_zero_pm_one :: Ptr CArb -> IO ()++-- | /arb_unit_interval/ /x/ +-- +-- Sets /x/ to the interval \([0, 1]\).+foreign import ccall "arb.h arb_unit_interval"+ arb_unit_interval :: Ptr CArb -> IO ()++-- Input and output ------------------------------------------------------------++-- | /arb_print/+--+-- The /arb_print.../ function prints the internal representation to+-- standard output.+--+arb_print :: Ptr CArb -> IO ()+arb_print x = do+ cstr <- arb_get_str_ x+ str <- peekCString cstr+ putStr str+ free cstr++-- | /arb_fprint/ /file/ /x/ +-- +-- Prints the internal representation of /x/ to the stream file /file/.+foreign import ccall "arb.h arb_fprint"+ arb_fprint :: Ptr CFile -> Ptr CArb -> IO ()++-- | /arb_printd/ /file/ /x/ /digits/ +-- +-- Prints /x/ in decimal to standard output. The printed value of the+-- radius is not adjusted to compensate for the fact that the+-- binary-to-decimal conversion of both the midpoint and the radius+-- introduces additional error.+arb_printd x prec = do+ cstr <- arb_get_strd x prec+ str <- peekCString cstr+ putStr str+ free cstr+ +-- | /arb_fprintd/ /file/ /x/ /digits/ +-- +-- Prints /x/ in decimal to stream file /file/. The printed value of+-- the radius is not adjusted to compensate for the fact that the+-- binary-to-decimal conversion of both the midpoint and the radius+-- introduces additional error.+foreign import ccall "arb.h arb_fprintd"+ arb_fprintd :: Ptr CFile -> Ptr CArb -> CLong -> IO ()+++-- | /arb_printn/ /file/ /x/ /digits/ /flags/ +-- +-- Prints a nice decimal representation of /x/. By default, the output+-- shows the midpoint with a guaranteed error of at most one unit in the+-- last decimal place. In addition, an explicit error bound is printed so+-- that the displayed decimal interval is guaranteed to enclose /x/. See+-- @arb_get_str@ for details.+arb_printn :: Ptr CArb -> CLong -> ArbStrOption -> IO ()+arb_printn x prec opt = do+ cstr <- arb_get_str x prec opt+ str <- peekCString cstr+ putStr str+ free cstr++-- | /arb_fprintn/ /file/ /x/ /digits/ /flags/ +-- +-- Prints a nice decimal representation of /x/. By default, the output+-- shows the midpoint with a guaranteed error of at most one unit in the+-- last decimal place. In addition, an explicit error bound is printed so+-- that the displayed decimal interval is guaranteed to enclose /x/. See+-- @arb_get_str@ for details.+foreign import ccall "arb.h arb_fprintn"+ arb_fprintn :: Ptr CFile -> Ptr CArb -> CLong -> ArbStrOption -> IO ()++-- | /arb_dump_str/ /x/ +-- +-- Returns a serialized representation of /x/ as a null-terminated ASCII+-- string that can be read by @arb_load_str@. The format consists of four+-- hexadecimal integers representing the midpoint mantissa, midpoint+-- exponent, radius mantissa and radius exponent (with special values to+-- indicate zero, infinity and NaN values), separated by single spaces. The+-- returned string needs to be deallocated with /flint_free/.+foreign import ccall "arb.h arb_dump_str"+ arb_dump_str :: Ptr CArb -> IO CString++-- | /arb_load_str/ /x/ /str/ +-- +-- Sets /x/ to the serialized representation given in /str/. Returns a+-- nonzero value if /str/ is not formatted correctly (see @arb_dump_str@).+foreign import ccall "arb.h arb_load_str"+ arb_load_str :: Ptr CArb -> CString -> IO CInt++-- | /arb_dump_file/ /stream/ /x/ +-- +-- Writes a serialized ASCII representation of /x/ to /stream/ in a form+-- that can be read by @arb_load_file@. Returns a nonzero value if the data+-- could not be written.+foreign import ccall "arb.h arb_dump_file"+ arb_dump_file :: Ptr CFile -> Ptr CArb -> IO CInt++-- | /arb_load_file/ /x/ /stream/ +-- +-- Reads /x/ from a serialized ASCII representation in /stream/. Returns a+-- nonzero value if the data is not formatted correctly or the read failed.+-- Note that the data is assumed to be delimited by a whitespace or+-- end-of-file, i.e., when writing multiple values with @arb_dump_file@+-- make sure to insert a whitespace to separate consecutive values.+-- +-- It is possible to serialize and deserialize a vector as follows+-- (warning: without error handling):+-- +-- > fp = fopen("data.txt", "w");+-- > for (i = 0; i < n; i++)+-- > {+-- > arb_dump_file(fp, vec + i);+-- > fprintf(fp, "\n"); // or any whitespace character+-- > }+-- > fclose(fp);+-- >+-- > fp = fopen("data.txt", "r");+-- > for (i = 0; i < n; i++)+-- > {+-- > arb_load_file(vec + i, fp);+-- > }+-- > fclose(fp);+foreign import ccall "arb.h arb_load_file"+ arb_load_file :: Ptr CArb -> Ptr CFile -> IO CInt++-- Random number generation ----------------------------------------------------++-- | /arb_randtest/ /x/ /state/ /prec/ /mag_bits/ +-- +-- Generates a random ball. The midpoint and radius will both be finite.+foreign import ccall "arb.h arb_randtest"+ arb_randtest :: Ptr CArb -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /arb_randtest_exact/ /x/ /state/ /prec/ /mag_bits/ +-- +-- Generates a random number with zero radius.+foreign import ccall "arb.h arb_randtest_exact"+ arb_randtest_exact :: Ptr CArb -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /arb_randtest_precise/ /x/ /state/ /prec/ /mag_bits/ +-- +-- Generates a random number with radius around \(2^{-\text{prec}}\) the+-- magnitude of the midpoint.+foreign import ccall "arb.h arb_randtest_precise"+ arb_randtest_precise :: Ptr CArb -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /arb_randtest_wide/ /x/ /state/ /prec/ /mag_bits/ +-- +-- Generates a random number with midpoint and radius chosen independently,+-- possibly giving a very large interval.+foreign import ccall "arb.h arb_randtest_wide"+ arb_randtest_wide :: Ptr CArb -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /arb_randtest_special/ /x/ /state/ /prec/ /mag_bits/ +-- +-- Generates a random interval, possibly having NaN or an infinity as the+-- midpoint and possibly having an infinite radius.+foreign import ccall "arb.h arb_randtest_special"+ arb_randtest_special :: Ptr CArb -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /arb_get_rand_fmpq/ /q/ /state/ /x/ /bits/ +-- +-- Sets /q/ to a random rational number from the interval represented by+-- /x/. A denominator is chosen by multiplying the binary denominator of+-- /x/ by a random integer up to /bits/ bits.+-- +-- The outcome is undefined if the midpoint or radius of /x/ is non-finite,+-- or if the exponent of the midpoint or radius is so large or small that+-- representing the endpoints as exact rational numbers would cause+-- overflows.+foreign import ccall "arb.h arb_get_rand_fmpq"+ arb_get_rand_fmpq :: Ptr CFmpq -> Ptr CFRandState -> Ptr CArb -> CLong -> IO ()++-- | /arb_urandom/ /x/ /state/ /prec/ +-- +-- Sets /x/ to a uniformly distributed random number in the interval+-- \([0, 1]\). The method uses rounding from integers to floats, hence the+-- radius might not be \(0\).+foreign import ccall "arb.h arb_urandom"+ arb_urandom :: Ptr CArb -> Ptr CFRandState -> CLong -> IO ()++-- Radius and interval operations ----------------------------------------------++-- | /arb_get_mid_arb/ /m/ /x/ +-- +-- Sets /m/ to the midpoint of /x/.+foreign import ccall "arb.h arb_get_mid_arb"+ arb_get_mid_arb :: Ptr CArb -> Ptr CArb -> IO ()++-- | /arb_get_rad_arb/ /r/ /x/ +-- +-- Sets /r/ to the radius of /x/.+foreign import ccall "arb.h arb_get_rad_arb"+ arb_get_rad_arb :: Ptr CArb -> Ptr CArb -> IO ()++foreign import ccall "arb.h arb_add_error_arf"+ arb_add_error_arf :: Ptr CArb -> Ptr CArf -> IO ()++foreign import ccall "arb.h arb_add_error_mag"+ arb_add_error_mag :: Ptr CArb -> Ptr CMag -> IO ()++-- | /arb_add_error/ /x/ /err/ +-- +-- Adds the absolute value of /err/ to the radius of /x/ (the operation is+-- done in-place).+foreign import ccall "arb.h arb_add_error"+ arb_add_error :: Ptr CArb -> Ptr CArb -> IO ()++foreign import ccall "arb.h arb_add_error_2exp_si"+ arb_add_error_2exp_si :: Ptr CArb -> CLong -> IO ()++-- | /arb_add_error_2exp_fmpz/ /x/ /e/ +-- +-- Adds \(2^e\) to the radius of /x/.+foreign import ccall "arb.h arb_add_error_2exp_fmpz"+ arb_add_error_2exp_fmpz :: Ptr CArb -> Ptr CFmpz -> IO ()++-- | /arb_union/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ to a ball containing both /x/ and /y/.+foreign import ccall "arb.h arb_union"+ arb_union :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_intersection/ /z/ /x/ /y/ /prec/ +-- +-- If /x/ and /y/ overlap according to @arb_overlaps@, then /z/ is set to a+-- ball containing the intersection of /x/ and /y/ and a nonzero value is+-- returned. Otherwise zero is returned and the value of /z/ is undefined.+-- If /x/ or /y/ contains NaN, the result is NaN.+foreign import ccall "arb.h arb_intersection"+ arb_intersection :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO CInt++-- | /arb_nonnegative_part/ /res/ /x/ +-- +-- Sets /res/ to the intersection of /x/ with \([0,\infty]\). If /x/ is+-- nonnegative, an exact copy is made. If /x/ is finite and contains+-- negative numbers, an interval of the form \([r/2 \pm r/2]\) is produced,+-- which certainly contains no negative points. In the special case when+-- /x/ is strictly negative, /res/ is set to zero.+foreign import ccall "arb.h arb_nonnegative_part"+ arb_nonnegative_part :: Ptr CArb -> Ptr CArb -> IO ()++-- | /arb_get_abs_ubound_arf/ /u/ /x/ /prec/ +-- +-- Sets /u/ to the upper bound for the absolute value of /x/, rounded up to+-- /prec/ bits. If /x/ contains NaN, the result is NaN.+foreign import ccall "arb.h arb_get_abs_ubound_arf"+ arb_get_abs_ubound_arf :: Ptr CArf -> Ptr CArb -> CLong -> IO ()++-- | /arb_get_abs_lbound_arf/ /u/ /x/ /prec/ +-- +-- Sets /u/ to the lower bound for the absolute value of /x/, rounded down+-- to /prec/ bits. If /x/ contains NaN, the result is NaN.+foreign import ccall "arb.h arb_get_abs_lbound_arf"+ arb_get_abs_lbound_arf :: Ptr CArf -> Ptr CArb -> CLong -> IO ()++-- | /arb_get_ubound_arf/ /u/ /x/ /prec/ +-- +-- Sets /u/ to the upper bound for the value of /x/, rounded up to /prec/+-- bits. If /x/ contains NaN, the result is NaN.+foreign import ccall "arb.h arb_get_ubound_arf"+ arb_get_ubound_arf :: Ptr CArf -> Ptr CArb -> CLong -> IO ()++-- | /arb_get_lbound_arf/ /u/ /x/ /prec/ +-- +-- Sets /u/ to the lower bound for the value of /x/, rounded down to /prec/+-- bits. If /x/ contains NaN, the result is NaN.+foreign import ccall "arb.h arb_get_lbound_arf"+ arb_get_lbound_arf :: Ptr CArf -> Ptr CArb -> CLong -> IO ()++-- | /arb_get_mag/ /z/ /x/ +-- +-- Sets /z/ to an upper bound for the absolute value of /x/. If /x/+-- contains NaN, the result is positive infinity.+foreign import ccall "arb.h arb_get_mag"+ arb_get_mag :: Ptr CMag -> Ptr CArb -> IO ()++-- | /arb_get_mag_lower/ /z/ /x/ +-- +-- Sets /z/ to a lower bound for the absolute value of /x/. If /x/ contains+-- NaN, the result is zero.+foreign import ccall "arb.h arb_get_mag_lower"+ arb_get_mag_lower :: Ptr CMag -> Ptr CArb -> IO ()++-- | /arb_get_mag_lower_nonnegative/ /z/ /x/ +-- +-- Sets /z/ to a lower bound for the signed value of /x/, or zero if /x/+-- overlaps with the negative half-axis. If /x/ contains NaN, the result is+-- zero.+foreign import ccall "arb.h arb_get_mag_lower_nonnegative"+ arb_get_mag_lower_nonnegative :: Ptr CMag -> Ptr CArb -> IO ()++-- | /arb_get_interval_fmpz_2exp/ /a/ /b/ /exp/ /x/ +-- +-- Computes the exact interval represented by /x/, in the form of an+-- integer interval multiplied by a power of two, i.e.+-- \(x = [a, b] \times 2^{\text{exp}}\). The result is normalized by+-- removing common trailing zeros from /a/ and /b/.+-- +-- This method aborts if /x/ is infinite or NaN, or if the difference+-- between the exponents of the midpoint and the radius is so large that+-- allocating memory for the result fails.+-- +-- Warning: this method will allocate a huge amount of memory to store the+-- result if the exponent difference is huge. Memory allocation could+-- succeed even if the required space is far larger than the physical+-- memory available on the machine, resulting in swapping. It is+-- recommended to check that the midpoint and radius of /x/ both are within+-- a reasonable range before calling this method.+foreign import ccall "arb.h arb_get_interval_fmpz_2exp"+ arb_get_interval_fmpz_2exp :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CArb -> IO ()++foreign import ccall "arb.h arb_set_interval_mag"+ arb_set_interval_mag :: Ptr CArb -> Ptr CMag -> Ptr CMag -> CLong -> IO ()++foreign import ccall "arb.h arb_set_interval_arf"+ arb_set_interval_arf :: Ptr CArb -> Ptr CArf -> Ptr CArf -> CLong -> IO ()++-- | /arb_set_interval_mpfr/ /x/ /a/ /b/ /prec/ +-- +-- Sets /x/ to a ball containing the interval \([a, b]\). We require that+-- \(a \le b\).+foreign import ccall "arb.h arb_set_interval_mpfr"+ arb_set_interval_mpfr :: Ptr CArb -> Ptr CMpfr -> Ptr CMpfr -> CLong -> IO ()++-- | /arb_set_interval_neg_pos_mag/ /x/ /a/ /b/ /prec/ +-- +-- Sets /x/ to a ball containing the interval \([-a, b]\).+foreign import ccall "arb.h arb_set_interval_neg_pos_mag"+ arb_set_interval_neg_pos_mag :: Ptr CArb -> Ptr CMag -> Ptr CMag -> CLong -> IO ()++foreign import ccall "arb.h arb_get_interval_arf"+ arb_get_interval_arf :: Ptr CArf -> Ptr CArf -> Ptr CArb -> CLong -> IO ()++-- | /arb_get_interval_mpfr/ /a/ /b/ /x/ +-- +-- Constructs an interval \([a, b]\) containing the ball /x/. The MPFR+-- version uses the precision of the output variables.+foreign import ccall "arb.h arb_get_interval_mpfr"+ arb_get_interval_mpfr :: Ptr CMpfr -> Ptr CMpfr -> Ptr CArb -> IO ()++-- | /arb_rel_error_bits/ /x/ +-- +-- Returns the effective relative error of /x/ measured in bits, defined as+-- the difference between the position of the top bit in the radius and the+-- top bit in the midpoint, plus one. The result is clamped between+-- plus\/minus /ARF_PREC_EXACT/.+foreign import ccall "arb.h arb_rel_error_bits"+ arb_rel_error_bits :: Ptr CArb -> IO CLong++-- | /arb_rel_accuracy_bits/ /x/ +-- +-- Returns the effective relative accuracy of /x/ measured in bits, equal+-- to the negative of the return value from @arb_rel_error_bits@.+foreign import ccall "arb.h arb_rel_accuracy_bits"+ arb_rel_accuracy_bits :: Ptr CArb -> IO CLong++-- | /arb_rel_one_accuracy_bits/ /x/ +-- +-- Given a ball with midpoint /m/ and radius /r/, returns an approximation+-- of the relative accuracy of \([\max(1,|m|) \pm r]\) measured in bits.+foreign import ccall "arb.h arb_rel_one_accuracy_bits"+ arb_rel_one_accuracy_bits :: Ptr CArb -> IO CLong++-- | /arb_bits/ /x/ +-- +-- Returns the number of bits needed to represent the absolute value of the+-- mantissa of the midpoint of /x/, i.e. the minimum precision sufficient+-- to represent /x/ exactly. Returns 0 if the midpoint of /x/ is a special+-- value.+foreign import ccall "arb.h arb_bits"+ arb_bits :: Ptr CArb -> IO CLong++-- | /arb_trim/ /y/ /x/ +-- +-- Sets /y/ to a trimmed copy of /x/: rounds /x/ to a number of bits equal+-- to the accuracy of /x/ (as indicated by its radius), plus a few guard+-- bits. The resulting ball is guaranteed to contain /x/, but is more+-- economical if /x/ has less than full accuracy.+foreign import ccall "arb.h arb_trim"+ arb_trim :: Ptr CArb -> Ptr CArb -> IO ()++-- | /arb_get_unique_fmpz/ /z/ /x/ +-- +-- If /x/ contains a unique integer, sets /z/ to that value and returns+-- nonzero. Otherwise (if /x/ represents no integers or more than one+-- integer), returns zero.+-- +-- This method aborts if there is a unique integer but that integer is so+-- large that allocating memory for the result fails.+-- +-- Warning: this method will allocate a huge amount of memory to store the+-- result if there is a unique integer and that integer is huge. Memory+-- allocation could succeed even if the required space is far larger than+-- the physical memory available on the machine, resulting in swapping. It+-- is recommended to check that the midpoint of /x/ is within a reasonable+-- range before calling this method.+foreign import ccall "arb.h arb_get_unique_fmpz"+ arb_get_unique_fmpz :: Ptr CFmpz -> Ptr CArb -> IO CInt++-- | /arb_floor/ /y/ /x/ /prec/ +-- +-- Sets /y/ to a ball containing respectively, \(\lfloor x \rfloor\) and+-- \(\lceil x \rceil\), \(\operatorname{trunc}(x)\),+-- \(\operatorname{nint}(x)\), with the midpoint of /y/ rounded to at most+-- /prec/ bits.+foreign import ccall "arb.h arb_floor"+ arb_floor :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_get_fmpz_mid_rad_10exp/ /mid/ /rad/ /exp/ /x/ /n/ +-- +-- Assuming that /x/ is finite and not exactly zero, computes integers+-- /mid/, /rad/, /exp/ such that \(x \in [m-r, m+r] \times 10^e\) and such+-- that the larger out of /mid/ and /rad/ has at least /n/ digits plus a+-- few guard digits. If /x/ is infinite or exactly zero, the outputs are+-- all set to zero.+foreign import ccall "arb.h arb_get_fmpz_mid_rad_10exp"+ arb_get_fmpz_mid_rad_10exp :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_can_round_arf"+ arb_can_round_arf :: Ptr CArb -> CLong -> ArfRnd -> IO CInt++-- | /arb_can_round_mpfr/ /x/ /prec/ /rnd/ +-- +-- Returns nonzero if rounding the midpoint of /x/ to /prec/ bits in the+-- direction /rnd/ is guaranteed to give the unique correctly rounded+-- floating-point approximation for the real number represented by /x/.+-- +-- In other words, if this function returns nonzero, applying+-- @arf_set_round@, or @arf_get_mpfr@, or @arf_get_d@ to the midpoint of+-- /x/ is guaranteed to return a correctly rounded /arf_t/, /mpfr_t/+-- (provided that /prec/ is the precision of the output variable), or+-- /double/ (provided that /prec/ is 53). Moreover, @arf_get_mpfr@ is+-- guaranteed to return the correct ternary value according to MPFR+-- semantics.+-- +-- Note that the /mpfr/ version of this function takes an MPFR rounding+-- mode symbol as input, while the /arf/ version takes an /arf/ rounding+-- mode symbol. Otherwise, the functions are identical.+-- +-- This function may perform a fast, inexact test; that is, it may return+-- zero in some cases even when correct rounding actually is possible.+-- +-- To be conservative, zero is returned when /x/ is non-finite, even if it+-- is an \"exact\" infinity.+foreign import ccall "arb.h arb_can_round_mpfr"+ arb_can_round_mpfr :: Ptr CArb -> CLong -> CMpfrRnd -> IO CInt++-- Comparisons -----------------------------------------------------------------++-- | /arb_is_zero/ /x/ +-- +-- Returns nonzero iff the midpoint and radius of /x/ are both zero.+foreign import ccall "arb.h arb_is_zero"+ arb_is_zero :: Ptr CArb -> IO CInt++-- | /arb_is_nonzero/ /x/ +-- +-- Returns nonzero iff zero is not contained in the interval represented by+-- /x/.+foreign import ccall "arb.h arb_is_nonzero"+ arb_is_nonzero :: Ptr CArb -> IO CInt++-- | /arb_is_one/ /f/ +-- +-- Returns nonzero iff /x/ is exactly 1.+foreign import ccall "arb.h arb_is_one"+ arb_is_one :: Ptr CArb -> IO CInt++-- | /arb_is_finite/ /x/ +-- +-- Returns nonzero iff the midpoint and radius of /x/ are both finite+-- floating-point numbers, i.e. not infinities or NaN.+foreign import ccall "arb.h arb_is_finite"+ arb_is_finite :: Ptr CArb -> IO CInt++-- | /arb_is_exact/ /x/ +-- +-- Returns nonzero iff the radius of /x/ is zero.+foreign import ccall "arb.h arb_is_exact"+ arb_is_exact :: Ptr CArb -> IO CInt++-- | /arb_is_int/ /x/ +-- +-- Returns nonzero iff /x/ is an exact integer.+foreign import ccall "arb.h arb_is_int"+ arb_is_int :: Ptr CArb -> IO CInt++-- | /arb_is_int_2exp_si/ /x/ /e/ +-- +-- Returns nonzero iff /x/ exactly equals \(n 2^e\) for some integer /n/.+foreign import ccall "arb.h arb_is_int_2exp_si"+ arb_is_int_2exp_si :: Ptr CArb -> CLong -> IO CInt++-- | /arb_equal/ /x/ /y/ +-- +-- Returns nonzero iff /x/ and /y/ are equal as balls, i.e. have both the+-- same midpoint and radius.+-- +-- Note that this is not the same thing as testing whether both /x/ and /y/+-- certainly represent the same real number, unless either /x/ or /y/ is+-- exact (and neither contains NaN). To test whether both operands /might/+-- represent the same mathematical quantity, use @arb_overlaps@ or+-- @arb_contains@, depending on the circumstance.+foreign import ccall "arb.h arb_equal"+ arb_equal :: Ptr CArb -> Ptr CArb -> IO CInt++-- | /arb_equal_si/ /x/ /y/ +-- +-- Returns nonzero iff /x/ is equal to the integer /y/.+foreign import ccall "arb.h arb_equal_si"+ arb_equal_si :: Ptr CArb -> CLong -> IO CInt++foreign import ccall "arb.h arb_is_positive"+ arb_is_positive :: Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_is_nonnegative"+ arb_is_nonnegative :: Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_is_negative"+ arb_is_negative :: Ptr CArb -> IO CInt++-- | /arb_is_nonpositive/ /x/ +-- +-- Returns nonzero iff all points /p/ in the interval represented by /x/+-- satisfy, respectively, \(p > 0\), \(p \ge 0\), \(p < 0\), \(p \le 0\).+-- If /x/ contains NaN, returns zero.+foreign import ccall "arb.h arb_is_nonpositive"+ arb_is_nonpositive :: Ptr CArb -> IO CInt++-- | /arb_overlaps/ /x/ /y/ +-- +-- Returns nonzero iff /x/ and /y/ have some point in common. If either /x/+-- or /y/ contains NaN, this function always returns nonzero (as a NaN+-- could be anything, it could in particular contain any number that is+-- included in the other operand).+foreign import ccall "arb.h arb_overlaps"+ arb_overlaps :: Ptr CArb -> Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_contains_arf"+ arb_contains_arf :: Ptr CArb -> Ptr CArf -> IO CInt++foreign import ccall "arb.h arb_contains_fmpq"+ arb_contains_fmpq :: Ptr CArb -> Ptr CFmpq -> IO CInt++foreign import ccall "arb.h arb_contains_fmpz"+ arb_contains_fmpz :: Ptr CArb -> Ptr CFmpz -> IO CInt++foreign import ccall "arb.h arb_contains_si"+ arb_contains_si :: Ptr CArb -> CLong -> IO CInt++foreign import ccall "arb.h arb_contains_mpfr"+ arb_contains_mpfr :: Ptr CArb -> Ptr CMpfr -> IO CInt++-- | /arb_contains/ /x/ /y/ +-- +-- Returns nonzero iff the given number (or ball) /y/ is contained in the+-- interval represented by /x/.+-- +-- If /x/ contains NaN, this function always returns nonzero (as it could+-- represent anything, and in particular could represent all the points+-- included in /y/). If /y/ contains NaN and /x/ does not, it always+-- returns zero.+foreign import ccall "arb.h arb_contains"+ arb_contains :: Ptr CArb -> Ptr CArb -> IO CInt++-- | /arb_contains_int/ /x/ +-- +-- Returns nonzero iff the interval represented by /x/ contains an integer.+foreign import ccall "arb.h arb_contains_int"+ arb_contains_int :: Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_contains_zero"+ arb_contains_zero :: Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_contains_negative"+ arb_contains_negative :: Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_contains_nonpositive"+ arb_contains_nonpositive :: Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_contains_positive"+ arb_contains_positive :: Ptr CArb -> IO CInt++-- | /arb_contains_nonnegative/ /x/ +-- +-- Returns nonzero iff there is any point /p/ in the interval represented+-- by /x/ satisfying, respectively, \(p = 0\), \(p < 0\), \(p \le 0\),+-- \(p > 0\), \(p \ge 0\). If /x/ contains NaN, returns nonzero.+foreign import ccall "arb.h arb_contains_nonnegative"+ arb_contains_nonnegative :: Ptr CArb -> IO CInt++-- | /arb_contains_interior/ /x/ /y/ +-- +-- Tests if /y/ is contained in the interior of /x/; that is, contained in+-- /x/ and not touching either endpoint.+foreign import ccall "arb.h arb_contains_interior"+ arb_contains_interior :: Ptr CArb -> Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_eq"+ arb_eq :: Ptr CArb -> Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_ne"+ arb_ne :: Ptr CArb -> Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_lt"+ arb_lt :: Ptr CArb -> Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_le"+ arb_le :: Ptr CArb -> Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_gt"+ arb_gt :: Ptr CArb -> Ptr CArb -> IO CInt++-- | /arb_ge/ /x/ /y/ +-- +-- Respectively performs the comparison \(x = y\), \(x \ne y\), \(x < y\),+-- \(x \le y\), \(x > y\), \(x \ge y\) in a mathematically meaningful way.+-- If the comparison \(t \, (\operatorname{op}) \, u\) holds for all+-- \(t \in x\) and all \(u \in y\), returns 1. Otherwise, returns 0.+-- +-- The balls /x/ and /y/ are viewed as subintervals of the extended real+-- line. Note that balls that are formally different can compare as equal+-- under this definition: for example,+-- \([-\infty \pm 3] = [-\infty \pm 0]\). Also+-- \([-\infty] \le [\infty \pm \infty]\).+-- +-- The output is always 0 if either input has NaN as midpoint.+foreign import ccall "arb.h arb_ge"+ arb_ge :: Ptr CArb -> Ptr CArb -> IO CInt++-- Arithmetic ------------------------------------------------------------------++foreign import ccall "arb.h arb_neg"+ arb_neg :: Ptr CArb -> Ptr CArb -> IO ()++-- | /arb_neg_round/ /y/ /x/ /prec/ +-- +-- Sets /y/ to the negation of /x/.+foreign import ccall "arb.h arb_neg_round"+ arb_neg_round :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_abs/ /y/ /x/ +-- +-- Sets /y/ to the absolute value of /x/. No attempt is made to improve the+-- interval represented by /x/ if it contains zero.+foreign import ccall "arb.h arb_abs"+ arb_abs :: Ptr CArb -> Ptr CArb -> IO ()++-- | /arb_nonnegative_abs/ /y/ /x/ +-- +-- Sets /y/ to the absolute value of /x/. If /x/ is finite and it contains+-- zero, sets /y/ to some interval \([r \pm r]\) that contains the absolute+-- value of /x/.+foreign import ccall "arb.h arb_nonnegative_abs"+ arb_nonnegative_abs :: Ptr CArb -> Ptr CArb -> IO ()++-- | /arb_sgn/ /y/ /x/ +-- +-- Sets /y/ to the sign function of /x/. The result is \([0 \pm 1]\) if /x/+-- contains both zero and nonzero numbers.+foreign import ccall "arb.h arb_sgn"+ arb_sgn :: Ptr CArb -> Ptr CArb -> IO ()++-- | /arb_sgn_nonzero/ /x/ +-- +-- Returns 1 if /x/ is strictly positive, -1 if /x/ is strictly negative,+-- and 0 if /x/ is zero or a ball containing zero so that its sign is not+-- determined.+foreign import ccall "arb.h arb_sgn_nonzero"+ arb_sgn_nonzero :: Ptr CArb -> IO CInt++foreign import ccall "arb.h arb_min"+ arb_min :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_max/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ respectively to the minimum and the maximum of /x/ and /y/.+foreign import ccall "arb.h arb_max"+ arb_max :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_add"+ arb_add :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_add_arf"+ arb_add_arf :: Ptr CArb -> Ptr CArb -> Ptr CArf -> CLong -> IO ()++foreign import ccall "arb.h arb_add_ui"+ arb_add_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++foreign import ccall "arb.h arb_add_si"+ arb_add_si :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_add_fmpz/ /z/ /x/ /y/ /prec/ +-- +-- Sets \(z = x + y\), rounded to /prec/ bits. The precision can be+-- /ARF_PREC_EXACT/ provided that the result fits in memory.+foreign import ccall "arb.h arb_add_fmpz"+ arb_add_fmpz :: Ptr CArb -> Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_add_fmpz_2exp/ /z/ /x/ /m/ /e/ /prec/ +-- +-- Sets \(z = x + m \cdot 2^e\), rounded to /prec/ bits. The precision can+-- be /ARF_PREC_EXACT/ provided that the result fits in memory.+foreign import ccall "arb.h arb_add_fmpz_2exp"+ arb_add_fmpz_2exp :: Ptr CArb -> Ptr CArb -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "arb.h arb_sub"+ arb_sub :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_sub_arf"+ arb_sub_arf :: Ptr CArb -> Ptr CArb -> Ptr CArf -> CLong -> IO ()++foreign import ccall "arb.h arb_sub_ui"+ arb_sub_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++foreign import ccall "arb.h arb_sub_si"+ arb_sub_si :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_sub_fmpz/ /z/ /x/ /y/ /prec/ +-- +-- Sets \(z = x - y\), rounded to /prec/ bits. The precision can be+-- /ARF_PREC_EXACT/ provided that the result fits in memory.+foreign import ccall "arb.h arb_sub_fmpz"+ arb_sub_fmpz :: Ptr CArb -> Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "arb.h arb_mul"+ arb_mul :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_mul_arf"+ arb_mul_arf :: Ptr CArb -> Ptr CArb -> Ptr CArf -> CLong -> IO ()++foreign import ccall "arb.h arb_mul_si"+ arb_mul_si :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++foreign import ccall "arb.h arb_mul_ui"+ arb_mul_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_mul_fmpz/ /z/ /x/ /y/ /prec/ +-- +-- Sets \(z = x \cdot y\), rounded to /prec/ bits. The precision can be+-- /ARF_PREC_EXACT/ provided that the result fits in memory.+foreign import ccall "arb.h arb_mul_fmpz"+ arb_mul_fmpz :: Ptr CArb -> Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "arb.h arb_mul_2exp_si"+ arb_mul_2exp_si :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_mul_2exp_fmpz/ /y/ /x/ /e/ +-- +-- Sets /y/ to /x/ multiplied by \(2^e\).+foreign import ccall "arb.h arb_mul_2exp_fmpz"+ arb_mul_2exp_fmpz :: Ptr CArb -> Ptr CArb -> Ptr CFmpz -> IO ()++foreign import ccall "arb.h arb_addmul"+ arb_addmul :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_addmul_arf"+ arb_addmul_arf :: Ptr CArb -> Ptr CArb -> Ptr CArf -> CLong -> IO ()++foreign import ccall "arb.h arb_addmul_si"+ arb_addmul_si :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++foreign import ccall "arb.h arb_addmul_ui"+ arb_addmul_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_addmul_fmpz/ /z/ /x/ /y/ /prec/ +-- +-- Sets \(z = z + x \cdot y\), rounded to prec bits. The precision can be+-- /ARF_PREC_EXACT/ provided that the result fits in memory.+foreign import ccall "arb.h arb_addmul_fmpz"+ arb_addmul_fmpz :: Ptr CArb -> Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "arb.h arb_submul"+ arb_submul :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_submul_arf"+ arb_submul_arf :: Ptr CArb -> Ptr CArb -> Ptr CArf -> CLong -> IO ()++foreign import ccall "arb.h arb_submul_si"+ arb_submul_si :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++foreign import ccall "arb.h arb_submul_ui"+ arb_submul_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_submul_fmpz/ /z/ /x/ /y/ /prec/ +-- +-- Sets \(z = z - x \cdot y\), rounded to prec bits. The precision can be+-- /ARF_PREC_EXACT/ provided that the result fits in memory.+foreign import ccall "arb.h arb_submul_fmpz"+ arb_submul_fmpz :: Ptr CArb -> Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_fma/ /res/ /x/ /y/ /z/ /prec/ +-- +-- Sets /res/ to \(x \cdot y + z\). This is equivalent to an /addmul/+-- except that /res/ and /z/ can be separate variables.+foreign import ccall "arb.h arb_fma"+ arb_fma :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_inv/ /z/ /x/ /prec/ +-- +-- Sets /z/ to \(1 / x\).+foreign import ccall "arb.h arb_inv"+ arb_inv :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_div"+ arb_div :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_div_arf"+ arb_div_arf :: Ptr CArb -> Ptr CArb -> Ptr CArf -> CLong -> IO ()++foreign import ccall "arb.h arb_div_si"+ arb_div_si :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++foreign import ccall "arb.h arb_div_ui"+ arb_div_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++foreign import ccall "arb.h arb_div_fmpz"+ arb_div_fmpz :: Ptr CArb -> Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "arb.h arb_fmpz_div_fmpz"+ arb_fmpz_div_fmpz :: Ptr CArb -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_ui_div/ /z/ /x/ /y/ /prec/ +-- +-- Sets \(z = x / y\), rounded to /prec/ bits. If /y/ contains zero, /z/ is+-- set to \(0 \pm \infty\). Otherwise, error propagation uses the rule+-- +-- \[`+-- \left| \frac{x}{y} - \frac{x+\xi_1 a}{y+\xi_2 b} \right| =+-- \left|\frac{x \xi_2 b - y \xi_1 a}{y (y+\xi_2 b)}\right| \le+-- \frac{|xb|+|ya|}{|y| (|y|-b)}\]+-- +-- where \(-1 \le \xi_1, \xi_2 \le 1\), and where the triangle inequality+-- has been applied to the numerator and the reverse triangle inequality+-- has been applied to the denominator.+foreign import ccall "arb.h arb_ui_div"+ arb_ui_div :: Ptr CArb -> CULong -> Ptr CArb -> CLong -> IO ()++-- | /arb_div_2expm1_ui/ /z/ /x/ /n/ /prec/ +-- +-- Sets \(z = x / (2^n - 1)\), rounded to /prec/ bits.+foreign import ccall "arb.h arb_div_2expm1_ui"+ arb_div_2expm1_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++-- Dot product -----------------------------------------------------------------++-- | /arb_dot_precise/ /res/ /s/ /subtract/ /x/ /xstep/ /y/ /ystep/ /len/ /prec/ +-- +-- Computes the dot product of the vectors /x/ and /y/, setting /res/ to+-- \(s + (-1)^{subtract} \sum_{i=0}^{len-1} x_i y_i\).+-- +-- The initial term /s/ is optional and can be omitted by passing /NULL/+-- (equivalently, \(s = 0\)). The parameter /subtract/ must be 0 or 1. The+-- length /len/ is allowed to be negative, which is equivalent to a length+-- of zero. The parameters /xstep/ or /ystep/ specify a step length for+-- traversing subsequences of the vectors /x/ and /y/; either can be+-- negative to step in the reverse direction starting from the initial+-- pointer. Aliasing is allowed between /res/ and /s/ but not between /res/+-- and the entries of /x/ and /y/.+-- +-- The default version determines the optimal precision for each term and+-- performs all internal calculations using mpn arithmetic with minimal+-- overhead. This is the preferred way to compute a dot product; it is+-- generally much faster and more precise than a simple loop.+-- +-- The /simple/ version performs fused multiply-add operations in a simple+-- loop. This can be used for testing purposes and is also used as a+-- fallback by the default version when the exponents are out of range for+-- the optimized code.+-- +-- The /precise/ version computes the dot product exactly up to the final+-- rounding. This can be extremely slow and is only intended for testing.+foreign import ccall "arb.h arb_dot_precise"+ arb_dot_precise :: Ptr CArb -> Ptr CArb -> CInt -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_approx_dot/ /res/ /s/ /subtract/ /x/ /xstep/ /y/ /ystep/ /len/ /prec/ +-- +-- Computes an approximate dot product /without error bounds/. The radii of+-- the inputs are ignored (only the midpoints are read) and only the+-- midpoint of the output is written.+foreign import ccall "arb.h arb_approx_dot"+ arb_approx_dot :: Ptr CArb -> Ptr CArb -> CInt -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_dot_ui/ /res/ /initial/ /subtract/ /x/ /xstep/ /y/ /ystep/ /len/ /prec/ +-- +-- Equivalent to @arb_dot@, but with integers in the array /y/. The /uiui/+-- and /siui/ versions take an array of double-limb integers as input; the+-- /siui/ version assumes that these represent signed integers in two\'s+-- complement form.+foreign import ccall "arb.h arb_dot_ui"+ arb_dot_ui :: Ptr CArb -> Ptr CArb -> CInt -> Ptr CArb -> CLong -> Ptr CULong -> CLong -> CLong -> CLong -> IO ()++-- Powers and roots ------------------------------------------------------------++foreign import ccall "arb.h arb_sqrt"+ arb_sqrt :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_sqrt_arf"+ arb_sqrt_arf :: Ptr CArb -> Ptr CArf -> CLong -> IO ()++foreign import ccall "arb.h arb_sqrt_fmpz"+ arb_sqrt_fmpz :: Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_sqrt_ui/ /z/ /x/ /prec/ +-- +-- Sets /z/ to the square root of /x/, rounded to /prec/ bits.+-- +-- If \(x = m \pm x\) where \(m \ge r \ge 0\), the propagated error is+-- bounded by+-- \(\sqrt{m} - \sqrt{m-r} = \sqrt{m} (1 - \sqrt{1 - r/m}) \le \sqrt{m} (r/m + (r/m)^2)/2\).+foreign import ccall "arb.h arb_sqrt_ui"+ arb_sqrt_ui :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_sqrtpos/ /z/ /x/ /prec/ +-- +-- Sets /z/ to the square root of /x/, assuming that /x/ represents a+-- nonnegative number (i.e. discarding any negative numbers in the input+-- interval).+foreign import ccall "arb.h arb_sqrtpos"+ arb_sqrtpos :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypot/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ to \(\sqrt{x^2 + y^2}\).+foreign import ccall "arb.h arb_hypot"+ arb_hypot :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_rsqrt"+ arb_rsqrt :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_rsqrt_ui/ /z/ /x/ /prec/ +-- +-- Sets /z/ to the reciprocal square root of /x/, rounded to /prec/ bits.+-- At high precision, this is faster than computing a square root.+foreign import ccall "arb.h arb_rsqrt_ui"+ arb_rsqrt_ui :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_sqrt1pm1/ /z/ /x/ /prec/ +-- +-- Sets \(z = \sqrt{1+x}-1\), computed accurately when \(x \approx 0\).+foreign import ccall "arb.h arb_sqrt1pm1"+ arb_sqrt1pm1 :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_root_ui/ /z/ /x/ /k/ /prec/ +-- +-- Sets /z/ to the /k/-th root of /x/, rounded to /prec/ bits. This+-- function selects between different algorithms. For large /k/, it+-- evaluates \(\exp(\log(x)/k)\). For small /k/, it uses @arf_root@ at the+-- midpoint and computes a propagated error bound as follows: if input+-- interval is \([m-r, m+r]\) with \(r \le m\), the error is largest at+-- \(m-r\) where it satisfies+-- +-- \[`\]+-- \[m^{1/k} - (m-r)^{1/k} = m^{1/k} [1 - (1-r/m)^{1/k}]\]+-- \[= m^{1/k} [1 - \exp(\log(1-r/m)/k)]\]+-- \[\le m^{1/k} \min(1, -\log(1-r/m)/k)\]+-- \[= m^{1/k} \min(1, \log(1+r/(m-r))/k).\]+-- +-- This is evaluated using @mag_log1p@.+foreign import ccall "arb.h arb_root_ui"+ arb_root_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_root/ /z/ /x/ /k/ /prec/ +-- +-- Alias for @arb_root_ui@, provided for backwards compatibility.+foreign import ccall "arb.h arb_root"+ arb_root :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_sqr/ /y/ /x/ /prec/ +-- +-- Sets /y/ to be the square of /x/.+foreign import ccall "arb.h arb_sqr"+ arb_sqr :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_pow_fmpz_binexp"+ arb_pow_fmpz_binexp :: Ptr CArb -> Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "arb.h arb_pow_fmpz"+ arb_pow_fmpz :: Ptr CArb -> Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "arb.h arb_pow_ui"+ arb_pow_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++foreign import ccall "arb.h arb_ui_pow_ui"+ arb_ui_pow_ui :: Ptr CArb -> CULong -> CULong -> CLong -> IO ()++-- | /arb_si_pow_ui/ /y/ /b/ /e/ /prec/ +-- +-- Sets \(y = b^e\) using binary exponentiation (with an initial division+-- if \(e < 0\)). Provided that /b/ and /e/ are small enough and the+-- exponent is positive, the exact power can be computed by setting the+-- precision to /ARF_PREC_EXACT/.+-- +-- Note that these functions can get slow if the exponent is extremely+-- large (in such cases @arb_pow@ may be superior).+foreign import ccall "arb.h arb_si_pow_ui"+ arb_si_pow_ui :: Ptr CArb -> CLong -> CULong -> CLong -> IO ()++-- | /arb_pow_fmpq/ /y/ /x/ /a/ /prec/ +-- +-- Sets \(y = b^e\), computed as \(y = (b^{1/q})^p\) if the denominator of+-- \(e = p/q\) is small, and generally as \(y = \exp(e \log b)\).+-- +-- Note that this function can get slow if the exponent is extremely large+-- (in such cases @arb_pow@ may be superior).+foreign import ccall "arb.h arb_pow_fmpq"+ arb_pow_fmpq :: Ptr CArb -> Ptr CArb -> Ptr CFmpq -> CLong -> IO ()++-- | /arb_pow/ /z/ /x/ /y/ /prec/ +-- +-- Sets \(z = x^y\), computed using binary exponentiation if \(y\) is a+-- small exact integer, as \(z = (x^{1/2})^{2y}\) if \(y\) is a small exact+-- half-integer, and generally as \(z = \exp(y \log x)\), except giving the+-- obvious finite result if \(x\) is \(a \pm a\) and \(y\) is positive.+foreign import ccall "arb.h arb_pow"+ arb_pow :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- Exponentials and logarithms -------------------------------------------------++foreign import ccall "arb.h arb_log_ui"+ arb_log_ui :: Ptr CArb -> CULong -> CLong -> IO ()++foreign import ccall "arb.h arb_log_fmpz"+ arb_log_fmpz :: Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "arb.h arb_log_arf"+ arb_log_arf :: Ptr CArb -> Ptr CArf -> CLong -> IO ()++-- | /arb_log/ /z/ /x/ /prec/ +-- +-- Sets \(z = \log(x)\).+-- +-- At low to medium precision (up to about 4096 bits), @arb_log_arf@ uses+-- table-based argument reduction and fast Taylor series evaluation via+-- @_arb_atan_taylor_rs@. At high precision, it falls back to MPFR. The+-- function @arb_log@ simply calls @arb_log_arf@ with the midpoint as+-- input, and separately adds the propagated error.+foreign import ccall "arb.h arb_log"+ arb_log :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_log_ui_from_prev/ /log_k1/ /k1/ /log_k0/ /k0/ /prec/ +-- +-- Computes \(\log(k_1)\), given \(\log(k_0)\) where \(k_0 < k_1\). At high+-- precision, this function uses the formula+-- \(\log(k_1) = \log(k_0) + 2 \operatorname{atanh}((k_1-k_0)/(k_1+k_0))\),+-- evaluating the inverse hyperbolic tangent using binary splitting (for+-- best efficiency, \(k_0\) should be large and \(k_1 - k_0\) should be+-- small). Otherwise, it ignores \(\log(k_0)\) and evaluates the logarithm+-- the usual way.+foreign import ccall "arb.h arb_log_ui_from_prev"+ arb_log_ui_from_prev :: Ptr CArb -> CULong -> Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_log1p/ /z/ /x/ /prec/ +-- +-- Sets \(z = \log(1+x)\), computed accurately when \(x \approx 0\).+foreign import ccall "arb.h arb_log1p"+ arb_log1p :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_log_base_ui/ /res/ /x/ /b/ /prec/ +-- +-- Sets /res/ to \(\log_b(x)\). The result is computed exactly when+-- possible.+foreign import ccall "arb.h arb_log_base_ui"+ arb_log_base_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_log_hypot/ /res/ /x/ /y/ /prec/ +-- +-- Sets /res/ to \(\log(\sqrt{x^2+y^2})\).+foreign import ccall "arb.h arb_log_hypot"+ arb_log_hypot :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_exp/ /z/ /x/ /prec/ +-- +-- Sets \(z = \exp(x)\). Error propagation is done using the following+-- rule: assuming \(x = m \pm r\), the error is largest at \(m + r\), and+-- we have \(\exp(m+r) - \exp(m) = \exp(m) (\exp(r)-1) \le r \exp(m+r)\).+foreign import ccall "arb.h arb_exp"+ arb_exp :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_expm1/ /z/ /x/ /prec/ +-- +-- Sets \(z = \exp(x)-1\), using a more accurate method when+-- \(x \approx 0\).+foreign import ccall "arb.h arb_expm1"+ arb_expm1 :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_exp_invexp/ /z/ /w/ /x/ /prec/ +-- +-- Sets \(z = \exp(x)\) and \(w = \exp(-x)\). The second exponential is+-- computed from the first using a division, but propagated error bounds+-- are computed separately.+foreign import ccall "arb.h arb_exp_invexp"+ arb_exp_invexp :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- Trigonometric functions -----------------------------------------------------++foreign import ccall "arb.h arb_sin"+ arb_sin :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_cos"+ arb_cos :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_sin_cos/ /s/ /c/ /x/ /prec/ +-- +-- Sets \(s = \sin(x)\), \(c = \cos(x)\).+foreign import ccall "arb.h arb_sin_cos"+ arb_sin_cos :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_sin_pi"+ arb_sin_pi :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_cos_pi"+ arb_cos_pi :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_sin_cos_pi/ /s/ /c/ /x/ /prec/ +-- +-- Sets \(s = \sin(\pi x)\), \(c = \cos(\pi x)\).+foreign import ccall "arb.h arb_sin_cos_pi"+ arb_sin_cos_pi :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_tan/ /y/ /x/ /prec/ +-- +-- Sets \(y = \tan(x) = \sin(x) / \cos(y)\).+foreign import ccall "arb.h arb_tan"+ arb_tan :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_cot/ /y/ /x/ /prec/ +-- +-- Sets \(y = \cot(x) = \cos(x) / \sin(y)\).+foreign import ccall "arb.h arb_cot"+ arb_cot :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_sin_cos_pi_fmpq"+ arb_sin_cos_pi_fmpq :: Ptr CArb -> Ptr CArb -> Ptr CFmpq -> CLong -> IO ()++foreign import ccall "arb.h arb_sin_pi_fmpq"+ arb_sin_pi_fmpq :: Ptr CArb -> Ptr CFmpq -> CLong -> IO ()++-- | /arb_cos_pi_fmpq/ /c/ /x/ /prec/ +-- +-- Sets \(s = \sin(\pi x)\), \(c = \cos(\pi x)\) where \(x\) is a rational+-- number (whose numerator and denominator are assumed to be reduced). We+-- first use trigonometric symmetries to reduce the argument to the octant+-- \([0, 1/4]\). Then we either multiply by a numerical approximation of+-- \(\pi\) and evaluate the trigonometric function the usual way, or we use+-- algebraic methods, depending on which is estimated to be faster. Since+-- the argument has been reduced to the first octant, the first of these+-- two methods gives full accuracy even if the original argument is close+-- to some root other the origin.+foreign import ccall "arb.h arb_cos_pi_fmpq"+ arb_cos_pi_fmpq :: Ptr CArb -> Ptr CFmpq -> CLong -> IO ()++-- | /arb_tan_pi/ /y/ /x/ /prec/ +-- +-- Sets \(y = \tan(\pi x)\).+foreign import ccall "arb.h arb_tan_pi"+ arb_tan_pi :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_cot_pi/ /y/ /x/ /prec/ +-- +-- Sets \(y = \cot(\pi x)\).+foreign import ccall "arb.h arb_cot_pi"+ arb_cot_pi :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_sec/ /res/ /x/ /prec/ +-- +-- Computes \(\sec(x) = 1 / \cos(x)\).+foreign import ccall "arb.h arb_sec"+ arb_sec :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_csc/ /res/ /x/ /prec/ +-- +-- Computes \(\csc(x) = 1 / \sin(x)\).+foreign import ccall "arb.h arb_csc"+ arb_csc :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_csc_pi/ /res/ /x/ /prec/ +-- +-- Computes \(\csc(\pi x) = 1 / \sin(\pi x)\).+foreign import ccall "arb.h arb_csc_pi"+ arb_csc_pi :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_sinc/ /z/ /x/ /prec/ +-- +-- Sets \(z = \operatorname{sinc}(x) = \sin(x) / x\).+foreign import ccall "arb.h arb_sinc"+ arb_sinc :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_sinc_pi/ /z/ /x/ /prec/ +-- +-- Sets \(z = \operatorname{sinc}(\pi x) = \sin(\pi x) / (\pi x)\).+foreign import ccall "arb.h arb_sinc_pi"+ arb_sinc_pi :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- Inverse trigonometric functions ---------------------------------------------++foreign import ccall "arb.h arb_atan_arf"+ arb_atan_arf :: Ptr CArb -> Ptr CArf -> CLong -> IO ()++-- | /arb_atan/ /z/ /x/ /prec/ +-- +-- Sets \(z = \operatorname{atan}(x)\).+-- +-- At low to medium precision (up to about 4096 bits), @arb_atan_arf@ uses+-- table-based argument reduction and fast Taylor series evaluation via+-- @_arb_atan_taylor_rs@. At high precision, it falls back to MPFR. The+-- function @arb_atan@ simply calls @arb_atan_arf@ with the midpoint as+-- input, and separately adds the propagated error.+-- +-- The function @arb_atan_arf@ uses lookup tables if possible, and+-- otherwise falls back to @arb_atan_arf_bb@.+foreign import ccall "arb.h arb_atan"+ arb_atan :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_atan2/ /z/ /b/ /a/ /prec/ +-- +-- Sets /r/ to an the argument (phase) of the complex number \(a + bi\),+-- with the branch cut discontinuity on \((-\infty,0]\). We define+-- \(\operatorname{atan2}(0,0) = 0\), and for \(a < 0\),+-- \(\operatorname{atan2}(0,a) = \pi\).+foreign import ccall "arb.h arb_atan2"+ arb_atan2 :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_asin/ /z/ /x/ /prec/ +-- +-- Sets+-- \(z = \operatorname{asin}(x) = \operatorname{atan}(x / \sqrt{1-x^2})\).+-- If \(x\) is not contained in the domain \([-1,1]\), the result is an+-- indeterminate interval.+foreign import ccall "arb.h arb_asin"+ arb_asin :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_acos/ /z/ /x/ /prec/ +-- +-- Sets \(z = \operatorname{acos}(x) = \pi/2 - \operatorname{asin}(x)\). If+-- \(x\) is not contained in the domain \([-1,1]\), the result is an+-- indeterminate interval.+foreign import ccall "arb.h arb_acos"+ arb_acos :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- Hyperbolic functions --------------------------------------------------------++foreign import ccall "arb.h arb_sinh"+ arb_sinh :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_cosh"+ arb_cosh :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_sinh_cosh/ /s/ /c/ /x/ /prec/ +-- +-- Sets \(s = \sinh(x)\), \(c = \cosh(x)\). If the midpoint of \(x\) is+-- close to zero and the hyperbolic sine is to be computed, evaluates+-- \((e^{2x}\pm1) / (2e^x)\) via @arb_expm1@ to avoid loss of accuracy.+-- Otherwise evaluates \((e^x \pm e^{-x}) / 2\).+foreign import ccall "arb.h arb_sinh_cosh"+ arb_sinh_cosh :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_tanh/ /y/ /x/ /prec/ +-- +-- Sets \(y = \tanh(x) = \sinh(x) / \cosh(x)\), evaluated via @arb_expm1@+-- as \(\tanh(x) = (e^{2x} - 1) / (e^{2x} + 1)\) if \(|x|\) is small, and+-- as \(\tanh(\pm x) = 1 - 2 e^{\mp 2x} / (1 + e^{\mp 2x})\) if \(|x|\) is+-- large.+foreign import ccall "arb.h arb_tanh"+ arb_tanh :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_coth/ /y/ /x/ /prec/ +-- +-- Sets \(y = \coth(x) = \cosh(x) / \sinh(x)\), evaluated using the same+-- strategy as @arb_tanh@.+foreign import ccall "arb.h arb_coth"+ arb_coth :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_sech/ /res/ /x/ /prec/ +-- +-- Computes \(\operatorname{sech}(x) = 1 / \cosh(x)\).+foreign import ccall "arb.h arb_sech"+ arb_sech :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_csch/ /res/ /x/ /prec/ +-- +-- Computes \(\operatorname{csch}(x) = 1 / \sinh(x)\).+foreign import ccall "arb.h arb_csch"+ arb_csch :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- Inverse hyperbolic functions ------------------------------------------------++-- | /arb_atanh/ /z/ /x/ /prec/ +-- +-- Sets \(z = \operatorname{atanh}(x)\).+foreign import ccall "arb.h arb_atanh"+ arb_atanh :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_asinh/ /z/ /x/ /prec/ +-- +-- Sets \(z = \operatorname{asinh}(x)\).+foreign import ccall "arb.h arb_asinh"+ arb_asinh :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_acosh/ /z/ /x/ /prec/ +-- +-- Sets \(z = \operatorname{acosh}(x)\). If \(x < 1\), the result is an+-- indeterminate interval.+foreign import ccall "arb.h arb_acosh"+ arb_acosh :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- Constants -------------------------------------------------------------------++-- The following functions cache the computed values to speed up repeated+-- calls at the same or lower precision. For further implementation+-- details, see @algorithms_constants@.+--+-- | /arb_const_pi/ /z/ /prec/ +-- +-- Computes \(\pi\).+foreign import ccall "arb.h arb_const_pi"+ arb_const_pi :: Ptr CArb -> CLong -> IO ()++-- | /arb_const_sqrt_pi/ /z/ /prec/ +-- +-- Computes \(\sqrt{\pi}\).+foreign import ccall "arb.h arb_const_sqrt_pi"+ arb_const_sqrt_pi :: Ptr CArb -> CLong -> IO ()++-- | /arb_const_log_sqrt2pi/ /z/ /prec/ +-- +-- Computes \(\log \sqrt{2 \pi}\).+foreign import ccall "arb.h arb_const_log_sqrt2pi"+ arb_const_log_sqrt2pi :: Ptr CArb -> CLong -> IO ()++-- | /arb_const_log2/ /z/ /prec/ +-- +-- Computes \(\log(2)\).+foreign import ccall "arb.h arb_const_log2"+ arb_const_log2 :: Ptr CArb -> CLong -> IO ()++-- | /arb_const_log10/ /z/ /prec/ +-- +-- Computes \(\log(10)\).+foreign import ccall "arb.h arb_const_log10"+ arb_const_log10 :: Ptr CArb -> CLong -> IO ()++-- | /arb_const_euler/ /z/ /prec/ +-- +-- Computes Euler\'s constant+-- \(\gamma = \lim_{k \rightarrow \infty} (H_k - \log k)\) where+-- \(H_k = 1 + 1/2 + \ldots + 1/k\).+foreign import ccall "arb.h arb_const_euler"+ arb_const_euler :: Ptr CArb -> CLong -> IO ()++-- | /arb_const_catalan/ /z/ /prec/ +-- +-- Computes Catalan\'s constant+-- \(C = \sum_{n=0}^{\infty} (-1)^n / (2n+1)^2\).+foreign import ccall "arb.h arb_const_catalan"+ arb_const_catalan :: Ptr CArb -> CLong -> IO ()++-- | /arb_const_e/ /z/ /prec/ +-- +-- Computes \(e = \exp(1)\).+foreign import ccall "arb.h arb_const_e"+ arb_const_e :: Ptr CArb -> CLong -> IO ()++-- | /arb_const_khinchin/ /z/ /prec/ +-- +-- Computes Khinchin\'s constant \(K_0\).+foreign import ccall "arb.h arb_const_khinchin"+ arb_const_khinchin :: Ptr CArb -> CLong -> IO ()++-- | /arb_const_glaisher/ /z/ /prec/ +-- +-- Computes the Glaisher-Kinkelin constant \(A = \exp(1/12 - \zeta'(-1))\).+foreign import ccall "arb.h arb_const_glaisher"+ arb_const_glaisher :: Ptr CArb -> CLong -> IO ()++-- | /arb_const_apery/ /z/ /prec/ +-- +-- Computes Apery\'s constant \(\zeta(3)\).+foreign import ccall "arb.h arb_const_apery"+ arb_const_apery :: Ptr CArb -> CLong -> IO ()++-- Lambert W function ----------------------------------------------------------++-- | /arb_lambertw/ /res/ /x/ /flags/ /prec/ +-- +-- Computes the Lambert W function, which solves the equation+-- \(w e^w = x\).+-- +-- The Lambert W function has infinitely many complex branches \(W_k(x)\),+-- two of which are real on a part of the real line. The principal branch+-- \(W_0(x)\) is selected by setting /flags/ to 0, and the \(W_{-1}\)+-- branch is selected by setting /flags/ to 1. The principal branch is+-- real-valued for \(x \ge -1/e\) (taking values in \([-1,+\infty)\)) and+-- the \(W_{-1}\) branch is real-valued for \(-1/e \le x < 0\) and takes+-- values in \((-\infty,-1]\). Elsewhere, the Lambert W function is complex+-- and @acb_lambertw@ should be used.+-- +-- The implementation first computes a floating-point approximation+-- heuristically and then computes a rigorously certified enclosure around+-- this approximation. Some asymptotic cases are handled specially. The+-- algorithm used to compute the Lambert W function is described in+-- < [Joh2017b]>, which follows the main ideas in < [CGHJK1996]>.+foreign import ccall "arb.h arb_lambertw"+ arb_lambertw :: Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- Gamma function and factorials -----------------------------------------------++-- | /arb_rising_ui/ /z/ /x/ /n/ /prec/ +-- +-- Computes the rising factorial \(z = x (x+1) (x+2) \cdots (x+n-1)\).+-- These functions are aliases for @arb_hypgeom_rising_ui@ and+-- @arb_hypgeom_rising@.+foreign import ccall "arb.h arb_rising_ui"+ arb_rising_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_rising_fmpq_ui/ /z/ /x/ /n/ /prec/ +-- +-- Computes the rising factorial \(z = x (x+1) (x+2) \cdots (x+n-1)\) using+-- binary splitting. If the denominator or numerator of /x/ is large+-- compared to /prec/, it is more efficient to convert /x/ to an+-- approximation and use @arb_rising_ui@.+foreign import ccall "arb.h arb_rising_fmpq_ui"+ arb_rising_fmpq_ui :: Ptr CArb -> Ptr CFmpq -> CULong -> CLong -> IO ()+++++-- | /arb_fac_ui/ /z/ /n/ /prec/ +-- +-- Computes the factorial \(z = n!\) via the gamma function.+foreign import ccall "arb.h arb_fac_ui"+ arb_fac_ui :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_doublefac_ui/ /z/ /n/ /prec/ +-- +-- Computes the double factorial \(z = n!!\) via the gamma function.+foreign import ccall "arb.h arb_doublefac_ui"+ arb_doublefac_ui :: Ptr CArb -> CULong -> CLong -> IO ()++foreign import ccall "arb.h arb_bin_ui"+ arb_bin_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_bin_uiui/ /z/ /n/ /k/ /prec/ +-- +-- Computes the binomial coefficient \(z = {n \choose k}\), via the rising+-- factorial as \({n \choose k} = (n-k+1)_k / k!\).+foreign import ccall "arb.h arb_bin_uiui"+ arb_bin_uiui :: Ptr CArb -> CULong -> CULong -> CLong -> IO ()++-- | /arb_gamma/ /z/ /x/ /prec/ +-- +-- Computes the gamma function \(z = \Gamma(x)\).+-- +-- These functions are aliases for @arb_hypgeom_gamma@,+-- @arb_hypgeom_gamma_fmpq@, @arb_hypgeom_gamma_fmpz@.+foreign import ccall "arb.h arb_gamma"+ arb_gamma :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_lgamma/ /z/ /x/ /prec/ +-- +-- Computes the logarithmic gamma function \(z = \log \Gamma(x)\). The+-- complex branch structure is assumed, so if \(x \le 0\), the result is an+-- indeterminate interval. This function is an alias for+-- @arb_hypgeom_lgamma@.+foreign import ccall "arb.h arb_lgamma"+ arb_lgamma :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_rgamma/ /z/ /x/ /prec/ +-- +-- Computes the reciprocal gamma function \(z = 1/\Gamma(x)\), avoiding+-- division by zero at the poles of the gamma function. This function is an+-- alias for @arb_hypgeom_rgamma@.+foreign import ccall "arb.h arb_rgamma"+ arb_rgamma :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_digamma/ /y/ /x/ /prec/ +-- +-- Computes the digamma function+-- \(z = \psi(x) = (\log \Gamma(x))' = \Gamma'(x) / \Gamma(x)\).+foreign import ccall "arb.h arb_digamma"+ arb_digamma :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- Zeta function ---------------------------------------------------------------++-- | /arb_zeta_ui_vec_borwein/ /z/ /start/ /num/ /step/ /prec/ +-- +-- Evaluates \(\zeta(s)\) at \(\mathrm{num}\) consecutive integers /s/+-- beginning with /start/ and proceeding in increments of /step/. Uses+-- Borwein\'s formula (< [Bor2000]>, < [GS2003]>), implemented to support+-- fast multi-evaluation (but also works well for a single /s/).+-- +-- Requires \(\mathrm{start} \ge 2\). For efficiency, the largest /s/+-- should be at most about as large as /prec/. Arguments approaching+-- /LONG_MAX/ will cause overflows. One should therefore only use this+-- function for /s/ up to about /prec/, and then switch to the Euler+-- product.+-- +-- The algorithm for single /s/ is basically identical to the one used in+-- MPFR (see < [MPFR2012]> for a detailed description). In particular, we+-- evaluate the sum backwards to avoid storing more than one \(d_k\)+-- coefficient, and use integer arithmetic throughout since it is+-- convenient and the terms turn out to be slightly larger than+-- \(2^\mathrm{prec}\). The only numerical error in the main loop comes+-- from the division by \(k^s\), which adds less than 1 unit of error per+-- term. For fast multi-evaluation, we repeatedly divide by+-- \(k^{\mathrm{step}}\). Each division reduces the input error and adds at+-- most 1 unit of additional rounding error, so by induction, the error per+-- term is always smaller than 2 units.+foreign import ccall "arb.h arb_zeta_ui_vec_borwein"+ arb_zeta_ui_vec_borwein :: Ptr CArb -> CULong -> CLong -> CULong -> CLong -> IO ()++foreign import ccall "arb.h arb_zeta_ui_asymp"+ arb_zeta_ui_asymp :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_zeta_ui_euler_product/ /z/ /s/ /prec/ +-- +-- Computes \(\zeta(s)\) using the Euler product. This is fast only if /s/+-- is large compared to the precision. Both methods are trivial wrappers+-- for @_acb_dirichlet_euler_product_real_ui@.+foreign import ccall "arb.h arb_zeta_ui_euler_product"+ arb_zeta_ui_euler_product :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_zeta_ui_bernoulli/ /x/ /s/ /prec/ +-- +-- Computes \(\zeta(s)\) for even /s/ via the corresponding Bernoulli+-- number.+foreign import ccall "arb.h arb_zeta_ui_bernoulli"+ arb_zeta_ui_bernoulli :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_zeta_ui_borwein_bsplit/ /x/ /s/ /prec/ +-- +-- Computes \(\zeta(s)\) for arbitrary \(s \ge 2\) using a binary splitting+-- implementation of Borwein\'s algorithm. This has quasilinear complexity+-- with respect to the precision (assuming that \(s\) is fixed).+foreign import ccall "arb.h arb_zeta_ui_borwein_bsplit"+ arb_zeta_ui_borwein_bsplit :: Ptr CArb -> CULong -> CLong -> IO ()++foreign import ccall "arb.h arb_zeta_ui_vec"+ arb_zeta_ui_vec :: Ptr CArb -> CULong -> CLong -> CLong -> IO ()++foreign import ccall "arb.h arb_zeta_ui_vec_even"+ arb_zeta_ui_vec_even :: Ptr CArb -> CULong -> CLong -> CLong -> IO ()++-- | /arb_zeta_ui_vec_odd/ /x/ /start/ /num/ /prec/ +-- +-- Computes \(\zeta(s)\) at /num/ consecutive integers (respectively /num/+-- even or /num/ odd integers) beginning with \(s = \mathrm{start} \ge 2\),+-- automatically choosing an appropriate algorithm.+foreign import ccall "arb.h arb_zeta_ui_vec_odd"+ arb_zeta_ui_vec_odd :: Ptr CArb -> CULong -> CLong -> CLong -> IO ()++-- | /arb_zeta_ui/ /x/ /s/ /prec/ +-- +-- Computes \(\zeta(s)\) for nonnegative integer \(s \ne 1\), automatically+-- choosing an appropriate algorithm. This function is intended for+-- numerical evaluation of isolated zeta values; for multi-evaluation, the+-- vector versions are more efficient.+foreign import ccall "arb.h arb_zeta_ui"+ arb_zeta_ui :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_zeta/ /z/ /s/ /prec/ +-- +-- Sets /z/ to the value of the Riemann zeta function \(\zeta(s)\).+-- +-- For computing derivatives with respect to \(s\), use+-- @arb_poly_zeta_series@.+foreign import ccall "arb.h arb_zeta"+ arb_zeta :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hurwitz_zeta/ /z/ /s/ /a/ /prec/ +-- +-- Sets /z/ to the value of the Hurwitz zeta function \(\zeta(s,a)\).+-- +-- For computing derivatives with respect to \(s\), use+-- @arb_poly_zeta_series@.+foreign import ccall "arb.h arb_hurwitz_zeta"+ arb_hurwitz_zeta :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- Bernoulli numbers and polynomials -------------------------------------------++foreign import ccall "arb.h arb_bernoulli_ui"+ arb_bernoulli_ui :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_bernoulli_fmpz/ /b/ /n/ /prec/ +-- +-- Sets \(b\) to the numerical value of the Bernoulli number \(B_n\)+-- approximated to /prec/ bits.+-- +-- The internal precision is increased automatically to give an accurate+-- result. Note that, with huge /fmpz/ input, the output will have a huge+-- exponent and evaluation will accordingly be slower.+-- +-- A single division from the exact fraction of \(B_n\) is used if this+-- value is in the global cache or the exact numerator roughly is larger+-- than /prec/ bits. Otherwise, the Riemann zeta function is used (see+-- @arb_bernoulli_ui_zeta@).+-- +-- This function reads \(B_n\) from the global cache if the number is+-- already cached, but does not automatically extend the cache by itself.+foreign import ccall "arb.h arb_bernoulli_fmpz"+ arb_bernoulli_fmpz :: Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_bernoulli_ui_zeta/ /b/ /n/ /prec/ +-- +-- Sets \(b\) to the numerical value of \(B_n\) accurate to /prec/ bits,+-- computed using the formula+-- \(B_{2n} = (-1)^{n+1} 2 (2n)! \zeta(2n) / (2 \pi)^n\).+-- +-- To avoid potential infinite recursion, we explicitly call the Euler+-- product implementation of the zeta function. This method will only give+-- high accuracy if the precision is small enough compared to \(n\) for the+-- Euler product to converge rapidly.+foreign import ccall "arb.h arb_bernoulli_ui_zeta"+ arb_bernoulli_ui_zeta :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_bernoulli_poly_ui/ /res/ /n/ /x/ /prec/ +-- +-- Sets /res/ to the value of the Bernoulli polynomial \(B_n(x)\).+-- +-- Warning: this function is only fast if either /n/ or /x/ is a small+-- integer.+-- +-- This function reads Bernoulli numbers from the global cache if they are+-- already cached, but does not automatically extend the cache by itself.+foreign import ccall "arb.h arb_bernoulli_poly_ui"+ arb_bernoulli_poly_ui :: Ptr CArb -> CULong -> Ptr CArb -> CLong -> IO ()++-- | /arb_power_sum_vec/ /res/ /a/ /b/ /len/ /prec/ +-- +-- For /n/ from 0 to /len/ - 1, sets entry /n/ in the output vector /res/+-- to+-- +-- \[`\]+-- \[S_n(a,b) = \frac{1}{n+1}\left(B_{n+1}(b) - B_{n+1}(a)\right)\]+-- +-- where \(B_n(x)\) is a Bernoulli polynomial. If /a/ and /b/ are integers+-- and \(b \ge a\), this is equivalent to+-- +-- \[`\]+-- \[S_n(a,b) = \sum_{k=a}^{b-1} k^n.\]+-- +-- The computation uses the generating function for Bernoulli polynomials.+foreign import ccall "arb.h arb_power_sum_vec"+ arb_power_sum_vec :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- Polylogarithms --------------------------------------------------------------++foreign import ccall "arb.h arb_polylog"+ arb_polylog :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_polylog_si/ /w/ /s/ /z/ /prec/ +-- +-- Sets /w/ to the polylogarithm \(\operatorname{Li}_s(z)\).+foreign import ccall "arb.h arb_polylog_si"+ arb_polylog_si :: Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++-- Other special functions -----------------------------------------------------++-- | /arb_fib_fmpz/ /z/ /n/ /prec/ +-- +-- Computes the Fibonacci number \(F_n\) using binary squaring.+foreign import ccall "arb.h arb_fib_fmpz"+ arb_fib_fmpz :: Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_agm/ /z/ /x/ /y/ /prec/ +-- +-- Sets /z/ to the arithmetic-geometric mean of /x/ and /y/.+foreign import ccall "arb.h arb_agm"+ arb_agm :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_chebyshev_t_ui"+ arb_chebyshev_t_ui :: Ptr CArb -> CULong -> Ptr CArb -> CLong -> IO ()++-- | /arb_chebyshev_u_ui/ /a/ /n/ /x/ /prec/ +-- +-- Evaluates the Chebyshev polynomial of the first kind \(a = T_n(x)\) or+-- the Chebyshev polynomial of the second kind \(a = U_n(x)\).+foreign import ccall "arb.h arb_chebyshev_u_ui"+ arb_chebyshev_u_ui :: Ptr CArb -> CULong -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_chebyshev_t2_ui"+ arb_chebyshev_t2_ui :: Ptr CArb -> Ptr CArb -> CULong -> Ptr CArb -> CLong -> IO ()++-- | /arb_chebyshev_u2_ui/ /a/ /b/ /n/ /x/ /prec/ +-- +-- Simultaneously evaluates \(a = T_n(x), b = T_{n-1}(x)\) or+-- \(a = U_n(x), b = U_{n-1}(x)\). Aliasing between /a/, /b/ and /x/ is not+-- permitted.+foreign import ccall "arb.h arb_chebyshev_u2_ui"+ arb_chebyshev_u2_ui :: Ptr CArb -> Ptr CArb -> CULong -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h arb_bell_sum_bsplit"+ arb_bell_sum_bsplit :: Ptr CArb -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_bell_sum_taylor/ /res/ /n/ /a/ /b/ /mmag/ /prec/ +-- +-- Helper functions for Bell numbers, evaluating the sum+-- \(\sum_{k=a}^{b-1} k^n / k!\). If /mmag/ is non-NULL, it may be used to+-- indicate that the target error tolerance should be \(2^{mmag - prec}\).+foreign import ccall "arb.h arb_bell_sum_taylor"+ arb_bell_sum_taylor :: Ptr CArb -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "arb.h arb_bell_fmpz"+ arb_bell_fmpz :: Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_bell_ui/ /res/ /n/ /prec/ +-- +-- Sets /res/ to the Bell number \(B_n\). If the number is too large to fit+-- exactly in /prec/ bits, a numerical approximation is computed+-- efficiently.+-- +-- The algorithm to compute Bell numbers, including error analysis, is+-- described in detail in < [Joh2015]>.+foreign import ccall "arb.h arb_bell_ui"+ arb_bell_ui :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_euler_number_fmpz/ /res/ /n/ /prec/ +-- +-- Sets /res/ to the Euler number \(E_n\), which is defined by the+-- exponential generating function \(1 / \cosh(x)\). The result will be+-- exact if \(E_n\) is exactly representable at the requested precision.+foreign import ccall "arb.h arb_euler_number_fmpz"+ arb_euler_number_fmpz :: Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_fmpz_euler_number_ui_multi_mod/ /res/ /n/ /alpha/ +-- +-- Computes the Euler number \(E_n\) as an exact integer. The default+-- algorithm uses a table lookup, the Dirichlet beta function or a hybrid+-- modular algorithm depending on the size of /n/. The /multi_mod/+-- algorithm accepts a tuning parameter /alpha/ which can be set to a+-- negative value to use defaults.+foreign import ccall "arb.h arb_fmpz_euler_number_ui_multi_mod"+ arb_fmpz_euler_number_ui_multi_mod :: Ptr CFmpz -> CULong -> CDouble -> IO ()++foreign import ccall "arb.h arb_partitions_fmpz"+ arb_partitions_fmpz :: Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_partitions_ui/ /res/ /n/ /prec/ +-- +-- Sets /res/ to the partition function \(p(n)\). When /n/ is large and+-- \(\log_2 p(n)\) is more than twice /prec/, the leading term in the+-- Hardy-Ramanujan asymptotic series is used together with an error bound.+-- Otherwise, the exact value is computed and rounded.+foreign import ccall "arb.h arb_partitions_ui"+ arb_partitions_ui :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_primorial_nth_ui/ /res/ /n/ /prec/ +-- +-- Sets /res/ to the /nth/ primorial, defined as the product of the first+-- /n/ prime numbers. The running time is quasilinear in /n/.+foreign import ccall "arb.h arb_primorial_nth_ui"+ arb_primorial_nth_ui :: Ptr CArb -> CULong -> CLong -> IO ()++-- | /arb_primorial_ui/ /res/ /n/ /prec/ +-- +-- Sets /res/ to the primorial defined as the product of the positive+-- integers up to and including /n/. The running time is quasilinear in+-- /n/.+foreign import ccall "arb.h arb_primorial_ui"+ arb_primorial_ui :: Ptr CArb -> CULong -> CLong -> IO ()++-- Internals for computing elementary functions --------------------------------++foreign import ccall "arb.h _arb_atan_taylor_naive"+ _arb_atan_taylor_naive :: Ptr CMp -> Ptr CMpLimb -> Ptr CMp -> CMpSize -> CULong -> CInt -> IO ()++-- | /_arb_atan_taylor_rs/ /y/ /error/ /x/ /xn/ /N/ /alternating/ +-- +-- Computes an approximation of \(y = \sum_{k=0}^{N-1} x^{2k+1} / (2k+1)\)+-- (if /alternating/ is 0) or+-- \(y = \sum_{k=0}^{N-1} (-1)^k x^{2k+1} / (2k+1)\) (if /alternating/ is+-- 1). Used internally for computing arctangents and logarithms. The+-- /naive/ version uses the forward recurrence, and the /rs/ version uses a+-- division-avoiding rectangular splitting scheme.+-- +-- Requires \(N \le 255\), \(0 \le x \le 1/16\), and /xn/ positive. The+-- input /x/ and output /y/ are fixed-point numbers with /xn/ fractional+-- limbs. A bound for the ulp error is written to /error/.+foreign import ccall "arb.h _arb_atan_taylor_rs"+ _arb_atan_taylor_rs :: Ptr CMp -> Ptr CMpLimb -> Ptr CMp -> CMpSize -> CULong -> CInt -> IO ()++foreign import ccall "arb.h _arb_exp_taylor_naive"+ _arb_exp_taylor_naive :: Ptr CMp -> Ptr CMpLimb -> Ptr CMp -> CMpSize -> CULong -> IO ()++-- | /_arb_exp_taylor_rs/ /y/ /error/ /x/ /xn/ /N/ +-- +-- Computes an approximation of \(y = \sum_{k=0}^{N-1} x^k / k!\). Used+-- internally for computing exponentials. The /naive/ version uses the+-- forward recurrence, and the /rs/ version uses a division-avoiding+-- rectangular splitting scheme.+-- +-- Requires \(N \le 287\), \(0 \le x \le 1/16\), and /xn/ positive. The+-- input /x/ is a fixed-point number with /xn/ fractional limbs, and the+-- output /y/ is a fixed-point number with /xn/ fractional limbs plus one+-- extra limb for the integer part of the result.+-- +-- A bound for the ulp error is written to /error/.+foreign import ccall "arb.h _arb_exp_taylor_rs"+ _arb_exp_taylor_rs :: Ptr CMp -> Ptr CMpLimb -> Ptr CMp -> CMpSize -> CULong -> IO ()++foreign import ccall "arb.h _arb_sin_cos_taylor_naive"+ _arb_sin_cos_taylor_naive :: Ptr CMp -> Ptr CMp -> Ptr CMpLimb -> Ptr CMp -> CMpSize -> CULong -> IO ()++-- | /_arb_sin_cos_taylor_rs/ /ysin/ /ycos/ /error/ /x/ /xn/ /N/ /sinonly/ /alternating/ +-- +-- Computes approximations of+-- \(y_s = \sum_{k=0}^{N-1} (-1)^k x^{2k+1} / (2k+1)!\) and+-- \(y_c = \sum_{k=0}^{N-1} (-1)^k x^{2k} / (2k)!\). Used internally for+-- computing sines and cosines. The /naive/ version uses the forward+-- recurrence, and the /rs/ version uses a division-avoiding rectangular+-- splitting scheme.+-- +-- Requires \(N \le 143\), \(0 \le x \le 1/16\), and /xn/ positive. The+-- input /x/ and outputs /ysin/, /ycos/ are fixed-point numbers with /xn/+-- fractional limbs. A bound for the ulp error is written to /error/.+-- +-- If /sinonly/ is 1, only the sine is computed; if /sinonly/ is 0 both the+-- sine and cosine are computed. To compute sin and cos, /alternating/+-- should be 1. If /alternating/ is 0, the hyperbolic sine is computed+-- (this is currently only intended to be used together with /sinonly/).+foreign import ccall "arb.h _arb_sin_cos_taylor_rs"+ _arb_sin_cos_taylor_rs :: Ptr CMp -> Ptr CMp -> Ptr CMpLimb -> Ptr CMp -> CMpSize -> CULong -> CInt -> CInt -> IO ()++-- | /_arb_get_mpn_fixed_mod_log2/ /w/ /q/ /error/ /x/ /wn/ +-- +-- Attempts to write \(w = x - q \log(2)\) with \(0 \le w < \log(2)\),+-- where /w/ is a fixed-point number with /wn/ limbs and ulp error /error/.+-- Returns success.+foreign import ccall "arb.h _arb_get_mpn_fixed_mod_log2"+ _arb_get_mpn_fixed_mod_log2 :: Ptr CMp -> Ptr CFmpz -> Ptr CMpLimb -> Ptr CArf -> CMpSize -> IO CInt++-- | /_arb_get_mpn_fixed_mod_pi4/ /w/ /q/ /octant/ /error/ /x/ /wn/ +-- +-- Attempts to write \(w = |x| - q \pi/4\) with \(0 \le w < \pi/4\), where+-- /w/ is a fixed-point number with /wn/ limbs and ulp error /error/.+-- Returns success.+-- +-- The value of /q/ mod 8 is written to /octant/. The output variable /q/+-- can be NULL, in which case the full value of /q/ is not stored.+foreign import ccall "arb.h _arb_get_mpn_fixed_mod_pi4"+ _arb_get_mpn_fixed_mod_pi4 :: Ptr CMp -> Ptr CFmpz -> Ptr CInt -> Ptr CMpLimb -> Ptr CArf -> CMpSize -> IO CInt++-- | /_arb_exp_taylor_bound/ /mag/ /prec/ +-- +-- Returns /n/ such that+-- \(\left|\sum_{k=n}^{\infty} x^k / k!\right| \le 2^{-\mathrm{prec}}\),+-- assuming \(|x| \le 2^{\mathrm{mag}} \le 1/4\).+foreign import ccall "arb.h _arb_exp_taylor_bound"+ _arb_exp_taylor_bound :: CLong -> CLong -> IO CLong++-- | /arb_exp_arf_bb/ /z/ /x/ /prec/ /m1/ +-- +-- Computes the exponential function using the bit-burst algorithm. If /m1/+-- is nonzero, the exponential function minus one is computed accurately.+-- +-- Aborts if /x/ is extremely small or large (where another algorithm+-- should be used).+-- +-- For large /x/, repeated halving is used. In fact, we always do argument+-- reduction until \(|x|\) is smaller than about \(2^{-d}\) where+-- \(d \approx 16\) to speed up convergence. If \(|x| \approx 2^m\), we+-- thus need about \(m+d\) squarings.+-- +-- Computing \(\log(2)\) costs roughly 100-200 multiplications, so is not+-- usually worth the effort at very high precision. However, this function+-- could be improved by using \(\log(2)\) based reduction at precision low+-- enough that the value can be assumed to be cached.+foreign import ccall "arb.h arb_exp_arf_bb"+ arb_exp_arf_bb :: Ptr CArb -> Ptr CArf -> CLong -> CInt -> IO ()++foreign import ccall "arb.h _arb_exp_sum_bs_simple"+ _arb_exp_sum_bs_simple :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFBitCnt -> Ptr CFmpz -> CFBitCnt -> CLong -> IO ()++-- | /_arb_exp_sum_bs_powtab/ /T/ /Q/ /Qexp/ /x/ /r/ /N/ +-- +-- Computes /T/, /Q/ and /Qexp/ such that+-- \(T / (Q 2^{\text{Qexp}}) = \sum_{k=1}^N (x/2^r)^k/k!\) using binary+-- splitting. Note that the sum is taken to /N/ inclusive and omits the+-- constant term.+-- +-- The /powtab/ version precomputes a table of powers of /x/, resulting in+-- slightly higher memory usage but better speed. For best efficiency, /N/+-- should have many trailing zero bits.+foreign import ccall "arb.h _arb_exp_sum_bs_powtab"+ _arb_exp_sum_bs_powtab :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFBitCnt -> Ptr CFmpz -> CFBitCnt -> CLong -> IO ()++-- | /arb_exp_arf_rs_generic/ /res/ /x/ /prec/ /minus_one/ +-- +-- Computes the exponential function using a generic version of the+-- rectangular splitting strategy, intended for intermediate precision.+foreign import ccall "arb.h arb_exp_arf_rs_generic"+ arb_exp_arf_rs_generic :: Ptr CArb -> Ptr CArf -> CLong -> CInt -> IO ()++foreign import ccall "arb.h _arb_atan_sum_bs_simple"+ _arb_atan_sum_bs_simple :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFBitCnt -> Ptr CFmpz -> CFBitCnt -> CLong -> IO ()++-- | /_arb_atan_sum_bs_powtab/ /T/ /Q/ /Qexp/ /x/ /r/ /N/ +-- +-- Computes /T/, /Q/ and /Qexp/ such that+-- \(T / (Q 2^{\text{Qexp}}) = \sum_{k=1}^N (-1)^k (x/2^r)^{2k} / (2k+1)\)+-- using binary splitting. Note that the sum is taken to /N/ inclusive,+-- omits the linear term, and requires a final multiplication by+-- \((x/2^r)\) to give the true series for atan.+-- +-- The /powtab/ version precomputes a table of powers of /x/, resulting in+-- slightly higher memory usage but better speed. For best efficiency, /N/+-- should have many trailing zero bits.+foreign import ccall "arb.h _arb_atan_sum_bs_powtab"+ _arb_atan_sum_bs_powtab :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFBitCnt -> Ptr CFmpz -> CFBitCnt -> CLong -> IO ()++-- | /arb_atan_arf_bb/ /z/ /x/ /prec/ +-- +-- Computes the arctangent of /x/. Initially, the argument-halving formula+-- +-- \[`\]+-- \[\operatorname{atan}(x) = 2 \operatorname{atan}\left(\frac{x}{1+\sqrt{1+x^2}}\right)\]+-- +-- is applied up to 8 times to get a small argument. Then a version of the+-- bit-burst algorithm is used. The functional equation+-- +-- \[`\]+-- \[\operatorname{atan}(x) = \operatorname{atan}(p/q) ++-- \operatorname{atan}(w),+-- \quad w = \frac{qx-p}{px+q},+-- \quad p = \lfloor qx \rfloor\]+-- +-- is applied repeatedly instead of integrating a differential equation for+-- the arctangent, as this appears to be more efficient.+foreign import ccall "arb.h arb_atan_arf_bb"+ arb_atan_arf_bb :: Ptr CArb -> Ptr CArf -> CLong -> IO ()++-- | /arb_atan_frac_bsplit/ /s/ /p/ /q/ /hyperbolic/ /prec/ +-- +-- Computes the arctangent of \(p/q\), optionally the hyperbolic+-- arctangent, using direct series summation with binary splitting.+foreign import ccall "arb.h arb_atan_frac_bsplit"+ arb_atan_frac_bsplit :: Ptr CArb -> Ptr CFmpz -> Ptr CFmpz -> CInt -> CLong -> IO ()++-- | /arb_sin_cos_arf_generic/ /s/ /c/ /x/ /prec/ +-- +-- Computes the sine and cosine of /x/ using a generic strategy. This+-- function gets called internally by the main sin and cos functions when+-- the precision for argument reduction or series evaluation based on+-- lookup tables is exhausted.+-- +-- This function first performs a cheap test to see if+-- \(|x| < \pi / 2 - \varepsilon\). If the test fails, it uses \(\pi\) to+-- reduce the argument to the first octant, and then evaluates the sin and+-- cos functions recursively (this call cannot result in infinite+-- recursion).+-- +-- If no argument reduction is needed, this function uses a generic version+-- of the rectangular splitting algorithm if the precision is not too high,+-- and otherwise invokes the asymptotically fast bit-burst algorithm.+foreign import ccall "arb.h arb_sin_cos_arf_generic"+ arb_sin_cos_arf_generic :: Ptr CArb -> Ptr CArb -> Ptr CArf -> CLong -> IO ()++-- | /arb_sin_cos_arf_bb/ /s/ /c/ /x/ /prec/ +-- +-- Computes the sine and cosine of /x/ using the bit-burst algorithm. It is+-- required that \(|x| < \pi / 2\) (this is not checked).+foreign import ccall "arb.h arb_sin_cos_arf_bb"+ arb_sin_cos_arf_bb :: Ptr CArb -> Ptr CArb -> Ptr CArf -> CLong -> IO ()++-- | /arb_sin_cos_wide/ /s/ /c/ /x/ /prec/ +-- +-- Computes an accurate enclosure (with both endpoints optimal to within+-- about \(2^{-30}\) as afforded by the radius format) of the range of sine+-- and cosine on a given wide interval. The computation is done by+-- evaluating the sine and cosine at the interval endpoints and determining+-- whether peaks of -1 or 1 occur between the endpoints. The interval is+-- then converted back to a ball.+-- +-- The internal computations are done with doubles, using a simple+-- floating-point algorithm to approximate the sine and cosine. It is easy+-- to see that the cumulative errors in this algorithm add up to less than+-- \(2^{-30}\), with the dominant source of error being a single+-- approximate reduction by \(\pi/2\). This reduction is done safely using+-- doubles up to a magnitude of about \(2^{20}\). For larger arguments, a+-- slower reduction using @arb_t@ arithmetic is done as a preprocessing+-- step.+foreign import ccall "arb.h arb_sin_cos_wide"+ arb_sin_cos_wide :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_sin_cos_generic/ /s/ /c/ /x/ /prec/ +-- +-- Computes the sine and cosine of /x/ by taking care of various special+-- cases and computing the propagated error before calling+-- @arb_sin_cos_arf_generic@. This is used as a fallback inside+-- @arb_sin_cos@ to take care of all cases without a fast path in that+-- function.+foreign import ccall "arb.h arb_sin_cos_generic"+ arb_sin_cos_generic :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_log_primes_vec_bsplit/ /res/ /n/ /prec/ +-- +-- Sets /res/ to a vector containing the natural logarithms of the first+-- /n/ prime numbers, computed using binary splitting applied to+-- simultaneous Machine-type formulas. This function is not optimized for+-- large /n/ or small /prec/.+foreign import ccall "arb.h arb_log_primes_vec_bsplit"+ arb_log_primes_vec_bsplit :: Ptr CArb -> CLong -> CLong -> IO ()++++++++-- | /_arb_log_p_ensure_cached/ /prec/ +-- +-- Ensure that the internal cache of logarithms of small prime numbers has+-- entries to at least /prec/ bits.+foreign import ccall "arb.h _arb_log_p_ensure_cached"+ _arb_log_p_ensure_cached :: CLong -> IO ()++-- | /arb_exp_arf_log_reduction/ /res/ /x/ /prec/ /minus_one/ +-- +-- Computes the exponential function using log reduction.+foreign import ccall "arb.h arb_exp_arf_log_reduction"+ arb_exp_arf_log_reduction :: Ptr CArb -> Ptr CArf -> CLong -> CInt -> IO ()++-- | /arb_exp_arf_generic/ /z/ /x/ /prec/ /minus_one/ +-- +-- Computes the exponential function using an automatic choice between+-- rectangular splitting and the bit-burst algorithm, without+-- precomputation.+foreign import ccall "arb.h arb_exp_arf_generic"+ arb_exp_arf_generic :: Ptr CArb -> Ptr CArf -> CLong -> CInt -> IO ()++-- | /arb_exp_arf/ /z/ /x/ /prec/ /minus_one/ /maglim/ +-- +-- Computes the exponential function using an automatic choice between all+-- implemented algorithms.+foreign import ccall "arb.h arb_exp_arf"+ arb_exp_arf :: Ptr CArb -> Ptr CArf -> CLong -> CInt -> CLong -> IO ()++-- | /arb_log_newton/ /res/ /x/ /prec/ +-- +-- Computes the logarithm using Newton iteration.+foreign import ccall "arb.h arb_log_newton"+ arb_log_newton :: Ptr CArb -> Ptr CArb -> CLong -> IO ()+++++-- | /arb_atan_gauss_primes_vec_bsplit/ /res/ /n/ /prec/ +-- +-- Sets /res/ to the primitive angles corresponding to the first /n/+-- nonreal Gaussian primes (ignoring symmetries), computed using binary+-- splitting applied to simultaneous Machine-type formulas. This function+-- is not optimized for large /n/ or small /prec/.+foreign import ccall "arb.h arb_atan_gauss_primes_vec_bsplit"+ arb_atan_gauss_primes_vec_bsplit :: Ptr CArb -> CLong -> CLong -> IO ()++foreign import ccall "arb.h _arb_atan_gauss_p_ensure_cached"+ _arb_atan_gauss_p_ensure_cached :: CLong -> IO ()++-- | /arb_sin_cos_arf_atan_reduction/ /res1/ /res2/ /x/ /prec/ +-- +-- Computes sin and\/or cos using reduction by primitive angles.+foreign import ccall "arb.h arb_sin_cos_arf_atan_reduction"+ arb_sin_cos_arf_atan_reduction :: Ptr CArb -> Ptr CArb -> Ptr CArf -> CLong -> IO ()++-- | /arb_atan_newton/ /res/ /x/ /prec/ +-- +-- Computes the arctangent using Newton iteration.+foreign import ccall "arb.h arb_atan_newton"+ arb_atan_newton :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- Vector functions ------------------------------------------------------------++-- | /_arb_vec_zero/ /vec/ /n/ +-- +-- Sets all entries in /vec/ to zero.+foreign import ccall "arb.h _arb_vec_zero"+ _arb_vec_zero :: Ptr CArb -> CLong -> IO ()++-- | /_arb_vec_is_zero/ /vec/ /len/ +-- +-- Returns nonzero iff all entries in /x/ are zero.+foreign import ccall "arb.h _arb_vec_is_zero"+ _arb_vec_is_zero :: Ptr CArb -> CLong -> IO CInt++-- | /_arb_vec_is_finite/ /x/ /len/ +-- +-- Returns nonzero iff all entries in /x/ certainly are finite.+foreign import ccall "arb.h _arb_vec_is_finite"+ _arb_vec_is_finite :: Ptr CArb -> CLong -> IO CInt++-- | /_arb_vec_set/ /res/ /vec/ /len/ +-- +-- Sets /res/ to a copy of /vec/.+foreign import ccall "arb.h _arb_vec_set"+ _arb_vec_set :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /_arb_vec_set_round/ /res/ /vec/ /len/ /prec/ +-- +-- Sets /res/ to a copy of /vec/, rounding each entry to /prec/ bits.+foreign import ccall "arb.h _arb_vec_set_round"+ _arb_vec_set_round :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_vec_swap/ /vec1/ /vec2/ /len/ +-- +-- Swaps the entries of /vec1/ and /vec2/.+foreign import ccall "arb.h _arb_vec_swap"+ _arb_vec_swap :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h _arb_vec_neg"+ _arb_vec_neg :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h _arb_vec_sub"+ _arb_vec_sub :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++foreign import ccall "arb.h _arb_vec_add"+ _arb_vec_add :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++foreign import ccall "arb.h _arb_vec_scalar_mul"+ _arb_vec_scalar_mul :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h _arb_vec_scalar_div"+ _arb_vec_scalar_div :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb.h _arb_vec_scalar_mul_fmpz"+ _arb_vec_scalar_mul_fmpz :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "arb.h _arb_vec_scalar_mul_2exp_si"+ _arb_vec_scalar_mul_2exp_si :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_vec_scalar_addmul/ /res/ /vec/ /len/ /c/ /prec/ +-- +-- Performs the respective scalar operation elementwise.+foreign import ccall "arb.h _arb_vec_scalar_addmul"+ _arb_vec_scalar_addmul :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++-- | /_arb_vec_get_mag/ /bound/ /vec/ /len/ /prec/ +-- +-- Sets /bound/ to an upper bound for the entries in /vec/.+foreign import ccall "arb.h _arb_vec_get_mag"+ _arb_vec_get_mag :: Ptr CMag -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_vec_bits/ /x/ /len/ +-- +-- Returns the maximum of @arb_bits@ for all entries in /vec/.+foreign import ccall "arb.h _arb_vec_bits"+ _arb_vec_bits :: Ptr CArb -> CLong -> IO CLong++-- | /_arb_vec_set_powers/ /xs/ /x/ /len/ /prec/ +-- +-- Sets /xs/ to the powers \(1, x, x^2, \ldots, x^{len-1}\).+foreign import ccall "arb.h _arb_vec_set_powers"+ _arb_vec_set_powers :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++foreign import ccall "arb.h _arb_vec_add_error_arf_vec"+ _arb_vec_add_error_arf_vec :: Ptr CArb -> Ptr CArf -> CLong -> IO ()++-- | /_arb_vec_add_error_mag_vec/ /res/ /err/ /len/ +-- +-- Adds the magnitude of each entry in /err/ to the radius of the+-- corresponding entry in /res/.+foreign import ccall "arb.h _arb_vec_add_error_mag_vec"+ _arb_vec_add_error_mag_vec :: Ptr CArb -> Ptr CMag -> CLong -> IO ()++-- | /_arb_vec_indeterminate/ /vec/ /len/ +-- +-- Applies @arb_indeterminate@ elementwise.+foreign import ccall "arb.h _arb_vec_indeterminate"+ _arb_vec_indeterminate :: Ptr CArb -> CLong -> IO ()++-- | /_arb_vec_trim/ /res/ /vec/ /len/ +-- +-- Applies @arb_trim@ elementwise.+foreign import ccall "arb.h _arb_vec_trim"+ _arb_vec_trim :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /_arb_vec_get_unique_fmpz_vec/ /res/ /vec/ /len/ +-- +-- Calls @arb_get_unique_fmpz@ elementwise and returns nonzero if all+-- entries can be rounded uniquely to integers. If any entry in /vec/+-- cannot be rounded uniquely to an integer, returns zero.+foreign import ccall "arb.h _arb_vec_get_unique_fmpz_vec"+ _arb_vec_get_unique_fmpz_vec :: Ptr CFmpz -> Ptr CArb -> CLong -> IO CInt+
+ src/Data/Number/Flint/Arb/Fmpz/Poly.hs view
@@ -0,0 +1,20 @@+{- |+This module provides methods for FLINT polynomials with integer and+rational coefficients (@FmpzPoly@) and (@FmpqPoly@) requiring use+of Arb real or complex numbers.++Some methods output real or complex numbers while others use real and+complex numbers internally to produce an exact result. This module also+contains some useful helper functions not specifically related to real+and complex numbers.++Note that methods that combine Arb /polynomials/ and FLINT polynomials+are found in the respective Arb polynomial modules, such as+@arb_poly_set_fmpz_poly@ and @arb_poly_get_unique_fmpz_poly@.++-}+module Data.Number.Flint.Arb.Fmpz.Poly (+ module Data.Number.Flint.Arb.Fmpz.Poly.FFI+ ) where++import Data.Number.Flint.Arb.Fmpz.Poly.FFI
+ src/Data/Number/Flint/Arb/Fmpz/Poly/FFI.hsc view
@@ -0,0 +1,214 @@+{-|+module : Data.Number.Flint.Arb.Fmpz.Poly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Arb.Fmpz.Poly.FFI (+ -- * Extra methods for integer polynomials+ -- * Evaluation+ _arb_fmpz_poly_evaluate_arb_horner+ , arb_fmpz_poly_evaluate_arb_horner+ , _arb_fmpz_poly_evaluate_arb_rectangular+ , arb_fmpz_poly_evaluate_arb_rectangular+ , _arb_fmpz_poly_evaluate_arb+ , arb_fmpz_poly_evaluate_arb+ , _arb_fmpz_poly_evaluate_acb_horner+ , arb_fmpz_poly_evaluate_acb_horner+ , _arb_fmpz_poly_evaluate_acb_rectangular+ , arb_fmpz_poly_evaluate_acb_rectangular+ , _arb_fmpz_poly_evaluate_acb+ , arb_fmpz_poly_evaluate_acb+ -- * Utility methods+ , arb_fmpz_poly_deflation+ , arb_fmpz_poly_deflate+ -- * Polynomial roots+ , arb_fmpz_poly_complex_roots+ -- * Special polynomials+ , arb_fmpz_poly_cos_minpoly+ , arb_fmpz_poly_gauss_period_minpoly+) where++-- Extra methods for integer polynomials ---------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr )+import Foreign.Marshal ( free )++import Foreign.Storable++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpq.Poly++import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Arb.Poly++import Data.Number.Flint.Acb+import Data.Number.Flint.Acb.Types+import Data.Number.Flint.Acb.Poly++-- Evaluation ------------------------------------------------------------------++-- | /_arb_fmpz_poly_evaluate_arb_horner/ /res/ /poly/ /len/ /x/ /prec/ +--+foreign import ccall "arb_fmpz_poly.h _arb_fmpz_poly_evaluate_arb_horner"+ _arb_fmpz_poly_evaluate_arb_horner :: Ptr CArb -> Ptr CFmpz -> CLong -> Ptr CArb -> CLong -> IO ()++-- | /arb_fmpz_poly_evaluate_arb_horner/ /res/ /poly/ /x/ /prec/ +--+foreign import ccall "arb_fmpz_poly.h arb_fmpz_poly_evaluate_arb_horner"+ arb_fmpz_poly_evaluate_arb_horner :: Ptr CArb -> Ptr CFmpzPoly -> Ptr CArb -> CLong -> IO ()++-- | /_arb_fmpz_poly_evaluate_arb_rectangular/ /res/ /poly/ /len/ /x/ /prec/ +--+foreign import ccall "arb_fmpz_poly.h _arb_fmpz_poly_evaluate_arb_rectangular"+ _arb_fmpz_poly_evaluate_arb_rectangular :: Ptr CArb -> Ptr CFmpz -> CLong -> Ptr CArb -> CLong -> IO ()++-- | /arb_fmpz_poly_evaluate_arb_rectangular/ /res/ /poly/ /x/ /prec/ +--+foreign import ccall "arb_fmpz_poly.h arb_fmpz_poly_evaluate_arb_rectangular"+ arb_fmpz_poly_evaluate_arb_rectangular :: Ptr CArb -> Ptr CFmpzPoly -> Ptr CArb -> CLong -> IO ()++-- | /_arb_fmpz_poly_evaluate_arb/ /res/ /poly/ /len/ /x/ /prec/ +--+foreign import ccall "arb_fmpz_poly.h _arb_fmpz_poly_evaluate_arb"+ _arb_fmpz_poly_evaluate_arb :: Ptr CArb -> Ptr CFmpz -> CLong -> Ptr CArb -> CLong -> IO ()++-- | /arb_fmpz_poly_evaluate_arb/ /res/ /poly/ /x/ /prec/ +--+foreign import ccall "arb_fmpz_poly.h arb_fmpz_poly_evaluate_arb"+ arb_fmpz_poly_evaluate_arb :: Ptr CArb -> Ptr CFmpzPoly -> Ptr CArb -> CLong -> IO ()++-- | /_arb_fmpz_poly_evaluate_acb_horner/ /res/ /poly/ /len/ /x/ /prec/ +--+foreign import ccall "arb_fmpz_poly.h _arb_fmpz_poly_evaluate_acb_horner"+ _arb_fmpz_poly_evaluate_acb_horner :: Ptr CAcb -> Ptr CFmpz -> CLong -> Ptr CAcb -> CLong -> IO ()++-- | /arb_fmpz_poly_evaluate_acb_horner/ /res/ /poly/ /x/ /prec/ +--+foreign import ccall "arb_fmpz_poly.h arb_fmpz_poly_evaluate_acb_horner"+ arb_fmpz_poly_evaluate_acb_horner :: Ptr CAcb -> Ptr CFmpzPoly -> Ptr CAcb -> CLong -> IO ()++-- | /_arb_fmpz_poly_evaluate_acb_rectangular/ /res/ /poly/ /len/ /x/ /prec/ +--+foreign import ccall "arb_fmpz_poly.h _arb_fmpz_poly_evaluate_acb_rectangular"+ _arb_fmpz_poly_evaluate_acb_rectangular :: Ptr CAcb -> Ptr CFmpz -> CLong -> Ptr CAcb -> CLong -> IO ()++-- | /arb_fmpz_poly_evaluate_acb_rectangular/ /res/ /poly/ /x/ /prec/ +--+foreign import ccall "arb_fmpz_poly.h arb_fmpz_poly_evaluate_acb_rectangular"+ arb_fmpz_poly_evaluate_acb_rectangular :: Ptr CAcb -> Ptr CFmpzPoly -> Ptr CAcb -> CLong -> IO ()++-- | /_arb_fmpz_poly_evaluate_acb/ /res/ /poly/ /len/ /x/ /prec/ +--+foreign import ccall "arb_fmpz_poly.h _arb_fmpz_poly_evaluate_acb"+ _arb_fmpz_poly_evaluate_acb :: Ptr CAcb -> Ptr CFmpz -> CLong -> Ptr CAcb -> CLong -> IO ()++-- | /arb_fmpz_poly_evaluate_acb/ /res/ /poly/ /x/ /prec/ +--+-- Evaluates /poly/ (given by a polynomial object or an array with /len/+-- coefficients) at the given real or complex number, respectively using+-- Horner\'s rule, rectangular splitting, or a default algorithm choice.+foreign import ccall "arb_fmpz_poly.h arb_fmpz_poly_evaluate_acb"+ arb_fmpz_poly_evaluate_acb :: Ptr CAcb -> Ptr CFmpzPoly -> Ptr CAcb -> CLong -> IO ()++-- Utility methods -------------------------------------------------------------++-- | /arb_fmpz_poly_deflation/ /poly/ +--+-- Finds the maximal exponent by which /poly/ can be deflated.+foreign import ccall "arb_fmpz_poly.h arb_fmpz_poly_deflation"+ arb_fmpz_poly_deflation :: Ptr CFmpzPoly -> IO CULong++-- | /arb_fmpz_poly_deflate/ /res/ /poly/ /deflation/ +--+-- Sets /res/ to a copy of /poly/ deflated by the exponent /deflation/.+foreign import ccall "arb_fmpz_poly.h arb_fmpz_poly_deflate"+ arb_fmpz_poly_deflate :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- Polynomial roots ------------------------------------------------------------++-- | /arb_fmpz_poly_complex_roots/ /roots/ /poly/ /flags/ /prec/ +--+-- Writes to /roots/ all the real and complex roots of the polynomial+-- /poly/, computed to at least /prec/ accurate bits. The root enclosures+-- are guaranteed to be disjoint, so that all roots are isolated.+-- +-- The real roots are written first in ascending order (with the imaginary+-- parts set exactly to zero). The following nonreal roots are written in+-- arbitrary order, but with conjugate pairs grouped together (the root in+-- the upper plane leading the root in the lower plane).+-- +-- The input polynomial /must/ be squarefree. For a general polynomial,+-- compute the squarefree part \(f / \gcd(f,f')\) or do a full squarefree+-- factorization to obtain the multiplicities of the roots:+-- +-- > fmpz_poly_factor_t fac;+-- > fmpz_poly_factor_init(fac);+-- > fmpz_poly_factor_squarefree(fac, poly);+-- >+-- > for (i = 0; i < fac->num; i++)+-- > {+-- > deg = fmpz_poly_degree(fac->p + i);+-- > flint_printf("%wd roots of multiplicity %wd\n", deg, fac->exp[i]);+-- > roots = _acb_vec_init(deg);+-- > arb_fmpz_poly_complex_roots(roots, fac->p + i, 0, prec);+-- > _acb_vec_clear(roots, deg);+-- > }+-- >+-- > fmpz_poly_factor_clear(fac);+-- +-- All roots are refined to a relative accuracy of at least /prec/ bits.+-- The output values will generally have higher actual precision, depending+-- on the precision needed for isolation and the precision used internally+-- by the algorithm.+-- +-- This implementation should be adequate for general use, but it is not+-- currently competitive with state-of-the-art isolation methods for+-- finding real roots alone.+-- +-- The following /flags/ are supported:+-- +-- - /ARB_FMPZ_POLY_ROOTS_VERBOSE/+foreign import ccall "arb_fmpz_poly.h arb_fmpz_poly_complex_roots"+ arb_fmpz_poly_complex_roots :: Ptr CAcb -> Ptr CFmpzPoly -> CInt -> CLong -> IO ()++-- Special polynomials ---------------------------------------------------------++-- Note: see also the methods available in FLINT (e.g. for cyclotomic+-- polynomials).+--+-- | /arb_fmpz_poly_cos_minpoly/ /res/ /n/ +--+-- Sets /res/ to the monic minimal polynomial of \(2 \cos(2 \pi / n)\).+-- This is a wrapper of FLINT\'s /fmpz_poly_cos_minpoly/, provided here for+-- backward compatibility.+foreign import ccall "arb_fmpz_poly.h arb_fmpz_poly_cos_minpoly"+ arb_fmpz_poly_cos_minpoly :: Ptr CFmpzPoly -> CULong -> IO ()++-- | /arb_fmpz_poly_gauss_period_minpoly/ /res/ /q/ /n/ +--+-- Sets /res/ to the minimal polynomial of the Gaussian periods+-- \(\sum_{a \in H} \zeta^a\) where \(\zeta = \exp(2 \pi i / q)\) and /H/+-- are the cosets of the subgroups of order \(d = (q - 1) / n\) of+-- \((\mathbb{Z}/q\mathbb{Z})^{\times}\). The resulting polynomial has+-- degree /n/. When \(d = 1\), the result is the cyclotomic polynomial+-- \(\Phi_q\).+-- +-- The implementation assumes that /q/ is prime, and that /n/ is a divisor+-- of \(q - 1\) such that /n/ is coprime with /d/. If any condition is not+-- met, /res/ is set to the zero polynomial.+-- +-- This method provides a fast (in practice) way to construct finite field+-- extensions of prescribed degree. If /q/ satisfies the conditions stated+-- above and \((q-1)/f\) additionally is coprime with /n/, where /f/ is the+-- multiplicative order of /p/ mod /q/, then the Gaussian period minimal+-- polynomial is irreducible over \(\operatorname{GF}(p)\) < [CP2005]>.+foreign import ccall "arb_fmpz_poly.h arb_fmpz_poly_gauss_period_minpoly"+ arb_fmpz_poly_gauss_period_minpoly :: Ptr CFmpzPoly -> CULong -> CULong -> IO ()+
+ src/Data/Number/Flint/Arb/FpWrap.hs view
@@ -0,0 +1,59 @@+{- |+__Warning:__ This module is experimental (as of Arb 2.21). It has not+been extensively tested, and interfaces may change in the future.++This module provides wrappers of Arb functions intended users who want+accurate floating-point mathematical functions without necessarily+caring about ball arithmetic. The wrappers take floating-point input,+give floating-point output, and automatically increase the internal+working precision to ensure that the output is accurate (in the rare+case of failure, they output NaN along with an error code).++Outputs are passed by reference so that we can return status flags and+so that the interface is uniform for functions with multiple outputs.++The Haskell version of the c-functions require Ptr for the complex values.+The functions can be wrapped to a regular Haskell function ++= Example++@+import System.IO.Unsafe+import Foreign.Ptr+import Foreign.C.Types++import Data.Number.Flint.Arb.FpWrap++main = do+ print $ airy_ai 1+ print $ airy_ai' 1++airy_ai = liftD arb_fpwrap_double_airy_ai+airy_ai' = liftD arb_fpwrap_double_airy_ai_prime++liftD :: (Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn)+ -> (Double -> Double)+liftD f x = unsafePerformIO $ do+ r <- malloc :: IO (Ptr CDouble)+ flag <- f r (realToFrac x) 0+ res <- peek r+ free r+ return $ realToFrac res+@++Running main yields:++>>> main++produces the output++@+0.13529241631288141+-0.1591474412967932+@+-}+module Data.Number.Flint.Arb.FpWrap (+ module Data.Number.Flint.Arb.FpWrap.FFI+ ) where++import Data.Number.Flint.Arb.FpWrap.FFI
+ src/Data/Number/Flint/Arb/FpWrap/FFI.hsc view
@@ -0,0 +1,1146 @@+{-|+module : Data.Number.Flint.Arb.FpWrap.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Arb.FpWrap.FFI (+ -- * Floating-point wrappers of Arb mathematical functions+ -- * Option and return flags+ FpWrapReturn (..)+ , fpwrap_success+ , fpwrap_unable+ , fpwrap_accurate_parts+ , fpwrap_correct_rounding+ , fpwrap_work_limit+ -- * Elementary functions+ , arb_fpwrap_double_exp+ , arb_fpwrap_cdouble_exp+ , arb_fpwrap_double_expm1+ , arb_fpwrap_cdouble_expm1+ , arb_fpwrap_double_log+ , arb_fpwrap_cdouble_log+ , arb_fpwrap_double_log1p+ , arb_fpwrap_cdouble_log1p+ , arb_fpwrap_double_pow+ , arb_fpwrap_cdouble_pow+ , arb_fpwrap_double_sqrt+ , arb_fpwrap_cdouble_sqrt+ , arb_fpwrap_double_rsqrt+ , arb_fpwrap_cdouble_rsqrt+ , arb_fpwrap_double_cbrt+ , arb_fpwrap_cdouble_cbrt+ , arb_fpwrap_double_sin+ , arb_fpwrap_cdouble_sin+ , arb_fpwrap_double_cos+ , arb_fpwrap_cdouble_cos+ , arb_fpwrap_double_tan+ , arb_fpwrap_cdouble_tan+ , arb_fpwrap_double_cot+ , arb_fpwrap_cdouble_cot+ , arb_fpwrap_double_sec+ , arb_fpwrap_cdouble_sec+ , arb_fpwrap_double_csc+ , arb_fpwrap_cdouble_csc+ , arb_fpwrap_double_sinc+ , arb_fpwrap_cdouble_sinc+ , arb_fpwrap_double_sin_pi+ , arb_fpwrap_cdouble_sin_pi+ , arb_fpwrap_double_cos_pi+ , arb_fpwrap_cdouble_cos_pi+ , arb_fpwrap_double_tan_pi+ , arb_fpwrap_cdouble_tan_pi+ , arb_fpwrap_double_cot_pi+ , arb_fpwrap_cdouble_cot_pi+ , arb_fpwrap_double_sinc_pi+ , arb_fpwrap_cdouble_sinc_pi+ , arb_fpwrap_double_asin+ , arb_fpwrap_cdouble_asin+ , arb_fpwrap_double_acos+ , arb_fpwrap_cdouble_acos+ , arb_fpwrap_double_atan+ , arb_fpwrap_cdouble_atan+ , arb_fpwrap_double_atan2+ , arb_fpwrap_double_asinh+ , arb_fpwrap_cdouble_asinh+ , arb_fpwrap_double_acosh+ , arb_fpwrap_cdouble_acosh+ , arb_fpwrap_double_atanh+ , arb_fpwrap_cdouble_atanh+ , arb_fpwrap_double_lambertw+ , arb_fpwrap_cdouble_lambertw+ -- * Gamma, zeta and related functions+ , arb_fpwrap_double_rising+ , arb_fpwrap_cdouble_rising+ , arb_fpwrap_double_gamma+ , arb_fpwrap_cdouble_gamma+ , arb_fpwrap_double_rgamma+ , arb_fpwrap_cdouble_rgamma+ , arb_fpwrap_double_lgamma+ , arb_fpwrap_cdouble_lgamma+ , arb_fpwrap_double_digamma+ , arb_fpwrap_cdouble_digamma+ , arb_fpwrap_double_zeta+ , arb_fpwrap_cdouble_zeta+ , arb_fpwrap_double_hurwitz_zeta+ , arb_fpwrap_cdouble_hurwitz_zeta+ , arb_fpwrap_double_lerch_phi+ , arb_fpwrap_cdouble_lerch_phi+ , arb_fpwrap_double_barnes_g+ , arb_fpwrap_cdouble_barnes_g+ , arb_fpwrap_double_log_barnes_g+ , arb_fpwrap_cdouble_log_barnes_g+ , arb_fpwrap_double_polygamma+ , arb_fpwrap_cdouble_polygamma+ , arb_fpwrap_double_polylog+ , arb_fpwrap_cdouble_polylog+ , arb_fpwrap_cdouble_dirichlet_eta+ , arb_fpwrap_cdouble_riemann_xi+ , arb_fpwrap_cdouble_hardy_theta+ , arb_fpwrap_cdouble_hardy_z+ , arb_fpwrap_cdouble_zeta_zero+ -- * Error functions and exponential integrals+ , arb_fpwrap_double_erf+ , arb_fpwrap_cdouble_erf+ , arb_fpwrap_double_erfc+ , arb_fpwrap_cdouble_erfc+ , arb_fpwrap_double_erfi+ , arb_fpwrap_cdouble_erfi+ , arb_fpwrap_double_erfinv+ , arb_fpwrap_double_erfcinv+ , arb_fpwrap_double_fresnel_s+ , arb_fpwrap_cdouble_fresnel_s+ , arb_fpwrap_double_fresnel_c+ , arb_fpwrap_cdouble_fresnel_c+ , arb_fpwrap_double_gamma_upper+ , arb_fpwrap_cdouble_gamma_upper+ , arb_fpwrap_double_gamma_lower+ , arb_fpwrap_cdouble_gamma_lower+ , arb_fpwrap_double_beta_lower+ , arb_fpwrap_cdouble_beta_lower+ , arb_fpwrap_double_exp_integral_e+ , arb_fpwrap_cdouble_exp_integral_e+ , arb_fpwrap_double_exp_integral_ei+ , arb_fpwrap_cdouble_exp_integral_ei+ , arb_fpwrap_double_sin_integral+ , arb_fpwrap_cdouble_sin_integral+ , arb_fpwrap_double_cos_integral+ , arb_fpwrap_cdouble_cos_integral+ , arb_fpwrap_double_sinh_integral+ , arb_fpwrap_cdouble_sinh_integral+ , arb_fpwrap_double_cosh_integral+ , arb_fpwrap_cdouble_cosh_integral+ , arb_fpwrap_double_log_integral+ , arb_fpwrap_cdouble_log_integral+ , arb_fpwrap_double_dilog+ , arb_fpwrap_cdouble_dilog+ -- * Bessel, Airy and Coulomb functions+ , arb_fpwrap_double_bessel_j+ , arb_fpwrap_cdouble_bessel_j+ , arb_fpwrap_double_bessel_y+ , arb_fpwrap_cdouble_bessel_y+ , arb_fpwrap_double_bessel_i+ , arb_fpwrap_cdouble_bessel_i+ , arb_fpwrap_double_bessel_k+ , arb_fpwrap_cdouble_bessel_k+ , arb_fpwrap_double_bessel_k_scaled+ , arb_fpwrap_cdouble_bessel_k_scaled+ , arb_fpwrap_double_airy_ai+ , arb_fpwrap_cdouble_airy_ai+ , arb_fpwrap_double_airy_ai_prime+ , arb_fpwrap_cdouble_airy_ai_prime+ , arb_fpwrap_double_airy_bi+ , arb_fpwrap_cdouble_airy_bi+ , arb_fpwrap_double_airy_bi_prime+ , arb_fpwrap_cdouble_airy_bi_prime+ , arb_fpwrap_double_airy_ai_zero+ , arb_fpwrap_double_airy_ai_prime_zero+ , arb_fpwrap_double_airy_bi_zero+ , arb_fpwrap_double_airy_bi_prime_zero+ , arb_fpwrap_double_coulomb_f+ , arb_fpwrap_cdouble_coulomb_f+ , arb_fpwrap_double_coulomb_g+ , arb_fpwrap_cdouble_coulomb_g+ , arb_fpwrap_cdouble_coulomb_hpos+ , arb_fpwrap_cdouble_coulomb_hneg+ -- * Orthogonal polynomials+ , arb_fpwrap_double_chebyshev_t+ , arb_fpwrap_cdouble_chebyshev_t+ , arb_fpwrap_double_chebyshev_u+ , arb_fpwrap_cdouble_chebyshev_u+ , arb_fpwrap_double_jacobi_p+ , arb_fpwrap_cdouble_jacobi_p+ , arb_fpwrap_double_gegenbauer_c+ , arb_fpwrap_cdouble_gegenbauer_c+ , arb_fpwrap_double_laguerre_l+ , arb_fpwrap_cdouble_laguerre_l+ , arb_fpwrap_double_hermite_h+ , arb_fpwrap_cdouble_hermite_h+ , arb_fpwrap_double_legendre_p+ , arb_fpwrap_cdouble_legendre_p+ , arb_fpwrap_double_legendre_q+ , arb_fpwrap_cdouble_legendre_q+ , arb_fpwrap_double_legendre_root+ , arb_fpwrap_cdouble_spherical_y+ -- * Hypergeometric functions+ , arb_fpwrap_double_hypgeom_0f1+ , arb_fpwrap_cdouble_hypgeom_0f1+ , arb_fpwrap_double_hypgeom_1f1+ , arb_fpwrap_cdouble_hypgeom_1f1+ , arb_fpwrap_double_hypgeom_u+ , arb_fpwrap_cdouble_hypgeom_u+ , arb_fpwrap_double_hypgeom_2f1+ , arb_fpwrap_cdouble_hypgeom_2f1+ , arb_fpwrap_double_hypgeom_pfq+ , arb_fpwrap_cdouble_hypgeom_pfq+ -- * Elliptic integrals, elliptic functions and modular forms+ , arb_fpwrap_double_agm+ , arb_fpwrap_cdouble_agm+ , arb_fpwrap_cdouble_elliptic_k+ , arb_fpwrap_cdouble_elliptic_e+ , arb_fpwrap_cdouble_elliptic_pi+ , arb_fpwrap_cdouble_elliptic_f+ , arb_fpwrap_cdouble_elliptic_e_inc+ , arb_fpwrap_cdouble_elliptic_pi_inc+ , arb_fpwrap_cdouble_elliptic_rf+ , arb_fpwrap_cdouble_elliptic_rg+ , arb_fpwrap_cdouble_elliptic_rj+ , arb_fpwrap_cdouble_elliptic_p+ , arb_fpwrap_cdouble_elliptic_p_prime+ , arb_fpwrap_cdouble_elliptic_inv_p+ , arb_fpwrap_cdouble_elliptic_zeta+ , arb_fpwrap_cdouble_elliptic_sigma+ , arb_fpwrap_cdouble_jacobi_theta_1+ , arb_fpwrap_cdouble_jacobi_theta_2+ , arb_fpwrap_cdouble_jacobi_theta_3+ , arb_fpwrap_cdouble_jacobi_theta_4+ , arb_fpwrap_cdouble_dedekind_eta+ , arb_fpwrap_cdouble_modular_j+ , arb_fpwrap_cdouble_modular_lambda+ , arb_fpwrap_cdouble_modular_delta+) where ++-- Floating-point wrappers of Arb mathematical functions -----------------------++import Foreign.Ptr+import Foreign.C.Types+import Foreign.Storable++import Data.Complex++#include <flint/arb_fpwrap.h>++--------------------------------------------------------------------------------++-- | Return type for fpwrap functions+newtype FpWrapReturn = FpWrapReturn { _FpWrapReturn :: CInt }+ deriving (Show, Eq)++-- | Indicates an accurate result. (Up to inevitable underflow or+-- overflow in the final conversion to a floating-point result; see+-- above.)+-- +-- This flag has the numerical value 0.+fpwrap_success = FpWrapReturn #const FPWRAP_SUCCESS+-- | Indicates failure (unable to achieve to target accuracy, possibly+-- because of a singularity). The output is set to NaN.+--+-- This flag has the numerical value 1.+-- Functions take a flags parameter specifying optional rounding and termination behavior. This can be set to 0 to use defaults.+fpwrap_unable = FpWrapReturn #const FPWRAP_UNABLE+-- | For complex output, compute both real and imaginary parts to full+-- relative accuracy. By default (if this flag is not set), complex+-- results are computed to at least 53-bit accuracy as a whole, but if+-- either the real or imaginary part is much smaller than the other,+-- that part can have a large relative error. Setting this flag can+-- result in slower evaluation or failure to converge in some cases.+--+-- This flag has the numerical value 1.+fpwrap_accurate_parts = FpWrapReturn #const FPWRAP_ACCURATE_PARTS+-- | Guarantees correct rounding. By default (if this flag is not+-- set), real results are accurate up to the rounding of the last bit,+-- but the last bit is not guaranteed to be rounded optimally. Setting+-- this flag can result in slower evaluation or failure to converge in+-- some cases. Correct rounding automatically applies to both real and+-- imaginary parts of complex numbers, so it is unnecessary to set+-- both this flag and FPWRAP_ACCURATE_PARTS.+--+-- This flag has the numerical value 2.+fpwrap_correct_rounding = FpWrapReturn #const FPWRAP_CORRECT_ROUNDING+-- | Multiplied by an integer, specifies the maximum working precision+-- to use before giving up. With n * FPWRAP_WORK_LIMIT added to flags,+-- levels of precision will be used. The default is equivalent to ,+-- which for double means trying with a working precision of 64, 128,+-- 256, 512, 1024, 2048, 4096, 8192 bits. With flags = 2 *+-- FPWRAP_WORK_LIMIT, we only try 64 and 128 bits, and with flags = 16+-- * FPWRAP_WORK_LIMIT we go up to 2097152 bits.+--+-- This flag has the numerical value 65536.+fpwrap_work_limit = FpWrapReturn #const FPWRAP_WORK_LIMIT++-- Functions -------------------------------------------------------------------++-- Elementary functions --------------------------------------------------------++-- | /arb_fpwrap_double_exp/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_exp_"+ arb_fpwrap_double_exp :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_exp/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_exp_"+ arb_fpwrap_cdouble_exp :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_expm1/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_expm1_"+ arb_fpwrap_double_expm1 :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_expm1/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_expm1_"+ arb_fpwrap_cdouble_expm1 :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_log/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_log_"+ arb_fpwrap_double_log :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_log/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_log_"+ arb_fpwrap_cdouble_log :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_log1p/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_log1p_"+ arb_fpwrap_double_log1p :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_log1p/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_log1p_"+ arb_fpwrap_cdouble_log1p :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_pow/ /res/ /x/ /y/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_pow_"+ arb_fpwrap_double_pow :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_pow/ /res/ /x/ /y/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_pow_"+ arb_fpwrap_cdouble_pow :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_sqrt/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_sqrt_"+ arb_fpwrap_double_sqrt :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_sqrt/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_sqrt_"+ arb_fpwrap_cdouble_sqrt :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_rsqrt/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_rsqrt_"+ arb_fpwrap_double_rsqrt :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_rsqrt/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_rsqrt_"+ arb_fpwrap_cdouble_rsqrt :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_cbrt/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_cbrt_"+ arb_fpwrap_double_cbrt :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_cbrt/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_cbrt_"+ arb_fpwrap_cdouble_cbrt :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_sin/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_sin_"+ arb_fpwrap_double_sin :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_sin/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_sin_"+ arb_fpwrap_cdouble_sin :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_cos/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_cos_"+ arb_fpwrap_double_cos :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_cos/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_cos_"+ arb_fpwrap_cdouble_cos :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_tan/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_tan_"+ arb_fpwrap_double_tan :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_tan/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_tan_"+ arb_fpwrap_cdouble_tan :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_cot/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_cot_"+ arb_fpwrap_double_cot :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_cot/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_cot_"+ arb_fpwrap_cdouble_cot :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_sec/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_sec_"+ arb_fpwrap_double_sec :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_sec/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_sec_"+ arb_fpwrap_cdouble_sec :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_csc/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_csc_"+ arb_fpwrap_double_csc :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_csc/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_csc_"+ arb_fpwrap_cdouble_csc :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_sinc/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_sinc_"+ arb_fpwrap_double_sinc :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_sinc/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_sinc_"+ arb_fpwrap_cdouble_sinc :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_sin_pi/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_sin_pi_"+ arb_fpwrap_double_sin_pi :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_sin_pi/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_sin_pi_"+ arb_fpwrap_cdouble_sin_pi :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_cos_pi/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_cos_pi_"+ arb_fpwrap_double_cos_pi :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_cos_pi/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_cos_pi_"+ arb_fpwrap_cdouble_cos_pi :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_tan_pi/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_tan_pi_"+ arb_fpwrap_double_tan_pi :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_tan_pi/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_tan_pi_"+ arb_fpwrap_cdouble_tan_pi :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_cot_pi/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_cot_pi_"+ arb_fpwrap_double_cot_pi :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_cot_pi/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_cot_pi_"+ arb_fpwrap_cdouble_cot_pi :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_sinc_pi/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_sinc_pi_"+ arb_fpwrap_double_sinc_pi :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_sinc_pi/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_sinc_pi_"+ arb_fpwrap_cdouble_sinc_pi :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_asin/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_asin_"+ arb_fpwrap_double_asin :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_asin/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_asin_"+ arb_fpwrap_cdouble_asin :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_acos/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_acos_"+ arb_fpwrap_double_acos :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_acos/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_acos_"+ arb_fpwrap_cdouble_acos :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_atan/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_atan_"+ arb_fpwrap_double_atan :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_atan/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_atan_"+ arb_fpwrap_cdouble_atan :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_atan2/ /res/ /x1/ /x2/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_double_atan2_"+ arb_fpwrap_double_atan2 :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_asinh/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_asinh_"+ arb_fpwrap_double_asinh :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_asinh/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_asinh_"+ arb_fpwrap_cdouble_asinh :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_acosh/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_acosh_"+ arb_fpwrap_double_acosh :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_acosh/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_acosh_"+ arb_fpwrap_cdouble_acosh :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_atanh/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_atanh_"+ arb_fpwrap_double_atanh :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_atanh/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_atanh_"+ arb_fpwrap_cdouble_atanh :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_lambertw/ /res/ /x/ /branch/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_lambertw_"+ arb_fpwrap_double_lambertw :: Ptr CDouble -> CDouble -> CLong -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_lambertw/ /res/ /x/ /branch/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_lambertw_"+ arb_fpwrap_cdouble_lambertw :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CLong -> CInt -> IO FpWrapReturn++-- Gamma, zeta and related functions -------------------------------------------++-- | /arb_fpwrap_double_rising/ /res/ /x/ /n/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_rising_"+ arb_fpwrap_double_rising :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_rising/ /res/ /x/ /n/ /flags/ +--+-- Rising factorial.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_rising_"+ arb_fpwrap_cdouble_rising :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_gamma/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_gamma_"+ arb_fpwrap_double_gamma :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_gamma/ /res/ /x/ /flags/ +--+-- Gamma function.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_gamma_"+ arb_fpwrap_cdouble_gamma :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_rgamma/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_rgamma_"+ arb_fpwrap_double_rgamma :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_rgamma/ /res/ /x/ /flags/ +--+-- Reciprocal gamma function.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_rgamma_"+ arb_fpwrap_cdouble_rgamma :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_lgamma/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_lgamma_"+ arb_fpwrap_double_lgamma :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_lgamma/ /res/ /x/ /flags/ +--+-- Log-gamma function.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_lgamma_"+ arb_fpwrap_cdouble_lgamma :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_digamma/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_digamma_"+ arb_fpwrap_double_digamma :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_digamma/ /res/ /x/ /flags/ +--+-- Digamma function.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_digamma_"+ arb_fpwrap_cdouble_digamma :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_zeta/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_zeta_"+ arb_fpwrap_double_zeta :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_zeta/ /res/ /x/ /flags/ +--+-- Riemann zeta function.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_zeta_"+ arb_fpwrap_cdouble_zeta :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_hurwitz_zeta/ /res/ /s/ /z/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_hurwitz_zeta_"+ arb_fpwrap_double_hurwitz_zeta :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_hurwitz_zeta/ /res/ /s/ /z/ /flags/ +--+-- Hurwitz zeta function.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_hurwitz_zeta_"+ arb_fpwrap_cdouble_hurwitz_zeta :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_lerch_phi/ /res/ /z/ /s/ /a/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_lerch_phi_"+ arb_fpwrap_double_lerch_phi :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_lerch_phi/ /res/ /z/ /s/ /a/ /flags/ +--+-- Lerch transcendent.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_lerch_phi_"+ arb_fpwrap_cdouble_lerch_phi :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_barnes_g/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_barnes_g_"+ arb_fpwrap_double_barnes_g :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_barnes_g/ /res/ /x/ /flags/ +--+-- Barnes G-function.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_barnes_g_"+ arb_fpwrap_cdouble_barnes_g :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_log_barnes_g/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_log_barnes_g_"+ arb_fpwrap_double_log_barnes_g :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_log_barnes_g/ /res/ /x/ /flags/ +--+-- Logarithmic Barnes G-function.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_log_barnes_g_"+ arb_fpwrap_cdouble_log_barnes_g :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_polygamma/ /res/ /s/ /z/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_polygamma_"+ arb_fpwrap_double_polygamma :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_polygamma/ /res/ /s/ /z/ /flags/ +--+-- Polygamma function.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_polygamma_"+ arb_fpwrap_cdouble_polygamma :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_polylog/ /res/ /s/ /z/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_polylog_"+ arb_fpwrap_double_polylog :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_polylog/ /res/ /s/ /z/ /flags/ +--+-- Polylogarithm.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_polylog_"+ arb_fpwrap_cdouble_polylog :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_dirichlet_eta/ /res/ /s/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_dirichlet_eta_"+ arb_fpwrap_cdouble_dirichlet_eta :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_riemann_xi/ /res/ /s/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_riemann_xi_"+ arb_fpwrap_cdouble_riemann_xi :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_hardy_theta/ /res/ /z/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_hardy_theta_"+ arb_fpwrap_cdouble_hardy_theta :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_hardy_z/ /res/ /z/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_hardy_z_"+ arb_fpwrap_cdouble_hardy_z :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_zeta_zero/ /res/ /n/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_zeta_zero_"+ arb_fpwrap_cdouble_zeta_zero :: Ptr (Complex CDouble) -> CULong -> CInt -> IO FpWrapReturn++-- Error functions and exponential integrals -----------------------------------++-- | /arb_fpwrap_double_erf/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_erf_"+ arb_fpwrap_double_erf :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_erf/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_erf_"+ arb_fpwrap_cdouble_erf :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_erfc/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_erfc_"+ arb_fpwrap_double_erfc :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_erfc/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_erfc_"+ arb_fpwrap_cdouble_erfc :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_erfi/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_erfi_"+ arb_fpwrap_double_erfi :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_erfi/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_erfi_"+ arb_fpwrap_cdouble_erfi :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_erfinv/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_double_erfinv_"+ arb_fpwrap_double_erfinv :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_erfcinv/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_double_erfcinv_"+ arb_fpwrap_double_erfcinv :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_fresnel_s/ /res/ /x/ /normalized/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_fresnel_s_"+ arb_fpwrap_double_fresnel_s :: Ptr CDouble -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_fresnel_s/ /res/ /x/ /normalized/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_fresnel_s_"+ arb_fpwrap_cdouble_fresnel_s :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_fresnel_c/ /res/ /x/ /normalized/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_fresnel_c_"+ arb_fpwrap_double_fresnel_c :: Ptr CDouble -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_fresnel_c/ /res/ /x/ /normalized/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_fresnel_c_"+ arb_fpwrap_cdouble_fresnel_c :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_gamma_upper/ /res/ /s/ /z/ /regularized/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_gamma_upper_"+ arb_fpwrap_double_gamma_upper :: Ptr CDouble -> CDouble -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_gamma_upper/ /res/ /s/ /z/ /regularized/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_gamma_upper_"+ arb_fpwrap_cdouble_gamma_upper :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_gamma_lower/ /res/ /s/ /z/ /regularized/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_gamma_lower_"+ arb_fpwrap_double_gamma_lower :: Ptr CDouble -> CDouble -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_gamma_lower/ /res/ /s/ /z/ /regularized/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_gamma_lower_"+ arb_fpwrap_cdouble_gamma_lower :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_beta_lower/ /res/ /a/ /b/ /z/ /regularized/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_beta_lower_"+ arb_fpwrap_double_beta_lower :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_beta_lower/ /res/ /a/ /b/ /z/ /regularized/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_beta_lower_"+ arb_fpwrap_cdouble_beta_lower :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_exp_integral_e/ /res/ /s/ /z/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_exp_integral_e_"+ arb_fpwrap_double_exp_integral_e :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_exp_integral_e/ /res/ /s/ /z/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_exp_integral_e_"+ arb_fpwrap_cdouble_exp_integral_e :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_exp_integral_ei/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_exp_integral_ei_"+ arb_fpwrap_double_exp_integral_ei :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_exp_integral_ei/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_exp_integral_ei_"+ arb_fpwrap_cdouble_exp_integral_ei :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_sin_integral/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_sin_integral_"+ arb_fpwrap_double_sin_integral :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_sin_integral/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_sin_integral_"+ arb_fpwrap_cdouble_sin_integral :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_cos_integral/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_cos_integral_"+ arb_fpwrap_double_cos_integral :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_cos_integral/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_cos_integral_"+ arb_fpwrap_cdouble_cos_integral :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_sinh_integral/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_sinh_integral_"+ arb_fpwrap_double_sinh_integral :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_sinh_integral/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_sinh_integral_"+ arb_fpwrap_cdouble_sinh_integral :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_cosh_integral/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_cosh_integral_"+ arb_fpwrap_double_cosh_integral :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_cosh_integral/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_cosh_integral_"+ arb_fpwrap_cdouble_cosh_integral :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_log_integral/ /res/ /x/ /offset/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_log_integral_"+ arb_fpwrap_double_log_integral :: Ptr CDouble -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_log_integral/ /res/ /x/ /offset/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_log_integral_"+ arb_fpwrap_cdouble_log_integral :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_dilog/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_dilog_"+ arb_fpwrap_double_dilog :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_dilog/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_dilog_"+ arb_fpwrap_cdouble_dilog :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- Bessel, Airy and Coulomb functions ------------------------------------------++-- | /arb_fpwrap_double_bessel_j/ /res/ /nu/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_bessel_j_"+ arb_fpwrap_double_bessel_j :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_bessel_j/ /res/ /nu/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_bessel_j_"+ arb_fpwrap_cdouble_bessel_j :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_bessel_y/ /res/ /nu/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_bessel_y_"+ arb_fpwrap_double_bessel_y :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_bessel_y/ /res/ /nu/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_bessel_y_"+ arb_fpwrap_cdouble_bessel_y :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_bessel_i/ /res/ /nu/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_bessel_i_"+ arb_fpwrap_double_bessel_i :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_bessel_i/ /res/ /nu/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_bessel_i_"+ arb_fpwrap_cdouble_bessel_i :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_bessel_k/ /res/ /nu/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_bessel_k_"+ arb_fpwrap_double_bessel_k :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_bessel_k/ /res/ /nu/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_bessel_k_"+ arb_fpwrap_cdouble_bessel_k :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_bessel_k_scaled/ /res/ /nu/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_bessel_k_scaled_"+ arb_fpwrap_double_bessel_k_scaled :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_bessel_k_scaled/ /res/ /nu/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_bessel_k_scaled_"+ arb_fpwrap_cdouble_bessel_k_scaled :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_airy_ai/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_airy_ai_"+ arb_fpwrap_double_airy_ai :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_airy_ai/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_airy_ai_"+ arb_fpwrap_cdouble_airy_ai :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_airy_ai_prime/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_airy_ai_prime_"+ arb_fpwrap_double_airy_ai_prime :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_airy_ai_prime/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_airy_ai_prime_"+ arb_fpwrap_cdouble_airy_ai_prime :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_airy_bi/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_airy_bi_"+ arb_fpwrap_double_airy_bi :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_airy_bi/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_airy_bi_"+ arb_fpwrap_cdouble_airy_bi :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_airy_bi_prime/ /res/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_airy_bi_prime_"+ arb_fpwrap_double_airy_bi_prime :: Ptr CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_airy_bi_prime/ /res/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_airy_bi_prime_"+ arb_fpwrap_cdouble_airy_bi_prime :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_airy_ai_zero/ /res/ /n/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_double_airy_ai_zero_"+ arb_fpwrap_double_airy_ai_zero :: Ptr CDouble -> CULong -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_airy_ai_prime_zero/ /res/ /n/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_double_airy_ai_prime_zero_"+ arb_fpwrap_double_airy_ai_prime_zero :: Ptr CDouble -> CULong -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_airy_bi_zero/ /res/ /n/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_double_airy_bi_zero_"+ arb_fpwrap_double_airy_bi_zero :: Ptr CDouble -> CULong -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_airy_bi_prime_zero/ /res/ /n/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_double_airy_bi_prime_zero_"+ arb_fpwrap_double_airy_bi_prime_zero :: Ptr CDouble -> CULong -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_coulomb_f/ /res/ /l/ /eta/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_coulomb_f_"+ arb_fpwrap_double_coulomb_f :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_coulomb_f/ /res/ /l/ /eta/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_coulomb_f_"+ arb_fpwrap_cdouble_coulomb_f :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_coulomb_g/ /res/ /l/ /eta/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_coulomb_g_"+ arb_fpwrap_double_coulomb_g :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_coulomb_g/ /res/ /l/ /eta/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_coulomb_g_"+ arb_fpwrap_cdouble_coulomb_g :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_coulomb_hpos/ /res/ /l/ /eta/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_coulomb_hpos_"+ arb_fpwrap_cdouble_coulomb_hpos :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_coulomb_hneg/ /res/ /l/ /eta/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_coulomb_hneg_"+ arb_fpwrap_cdouble_coulomb_hneg :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- Orthogonal polynomials ------------------------------------------------------++-- | /arb_fpwrap_double_chebyshev_t/ /res/ /n/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_chebyshev_t_"+ arb_fpwrap_double_chebyshev_t :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_chebyshev_t/ /res/ /n/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_chebyshev_t_"+ arb_fpwrap_cdouble_chebyshev_t :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_chebyshev_u/ /res/ /n/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_chebyshev_u_"+ arb_fpwrap_double_chebyshev_u :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_chebyshev_u/ /res/ /n/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_chebyshev_u_"+ arb_fpwrap_cdouble_chebyshev_u :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_jacobi_p/ /res/ /n/ /a/ /b/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_jacobi_p_"+ arb_fpwrap_double_jacobi_p :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_jacobi_p/ /res/ /n/ /a/ /b/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_jacobi_p_"+ arb_fpwrap_cdouble_jacobi_p :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_gegenbauer_c/ /res/ /n/ /m/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_gegenbauer_c_"+ arb_fpwrap_double_gegenbauer_c :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_gegenbauer_c/ /res/ /n/ /m/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_gegenbauer_c_"+ arb_fpwrap_cdouble_gegenbauer_c :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_laguerre_l/ /res/ /n/ /m/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_laguerre_l_"+ arb_fpwrap_double_laguerre_l :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_laguerre_l/ /res/ /n/ /m/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_laguerre_l_"+ arb_fpwrap_cdouble_laguerre_l :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_hermite_h/ /res/ /n/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_hermite_h_"+ arb_fpwrap_double_hermite_h :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_hermite_h/ /res/ /n/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_hermite_h_"+ arb_fpwrap_cdouble_hermite_h :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_legendre_p/ /res/ /n/ /m/ /x/ /type/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_legendre_p_"+ arb_fpwrap_double_legendre_p :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_legendre_p/ /res/ /n/ /m/ /x/ /type/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_legendre_p_"+ arb_fpwrap_cdouble_legendre_p :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_legendre_q/ /res/ /n/ /m/ /x/ /type/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_legendre_q_"+ arb_fpwrap_double_legendre_q :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_legendre_q/ /res/ /n/ /m/ /x/ /type/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_legendre_q_"+ arb_fpwrap_cdouble_legendre_q :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_legendre_root/ /res1/ /res2/ /n/ /k/ /flags/ +--+-- Sets /res1/ to the index /k/ root of the Legendre polynomial \(P_n(x)\),+-- and simultaneously sets /res2/ to the corresponding weight for+-- Gauss-Legendre quadrature.+foreign import ccall "arb_fpwrap.h arb_fpwrap_double_legendre_root_"+ arb_fpwrap_double_legendre_root :: Ptr CDouble -> Ptr CDouble -> CULong -> CULong -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_spherical_y/ /res/ /n/ /m/ /x1/ /x2/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_spherical_y_"+ arb_fpwrap_cdouble_spherical_y :: Ptr (Complex CDouble) -> CLong -> CLong -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- Hypergeometric functions ----------------------------------------------------++-- | /arb_fpwrap_double_hypgeom_0f1/ /res/ /a/ /x/ /regularized/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_hypgeom_0f1_"+ arb_fpwrap_double_hypgeom_0f1 :: Ptr CDouble -> CDouble -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_hypgeom_0f1/ /res/ /a/ /x/ /regularized/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_hypgeom_0f1_"+ arb_fpwrap_cdouble_hypgeom_0f1 :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_hypgeom_1f1/ /res/ /a/ /b/ /x/ /regularized/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_hypgeom_1f1_"+ arb_fpwrap_double_hypgeom_1f1 :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_hypgeom_1f1/ /res/ /a/ /b/ /x/ /regularized/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_hypgeom_1f1_"+ arb_fpwrap_cdouble_hypgeom_1f1 :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_hypgeom_u/ /res/ /a/ /b/ /x/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_hypgeom_u_"+ arb_fpwrap_double_hypgeom_u :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_hypgeom_u/ /res/ /a/ /b/ /x/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_hypgeom_u_"+ arb_fpwrap_cdouble_hypgeom_u :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_hypgeom_2f1/ /res/ /a/ /b/ /c/ /x/ /regularized/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_hypgeom_2f1_"+ arb_fpwrap_double_hypgeom_2f1 :: Ptr CDouble -> CDouble -> CDouble -> CDouble -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_hypgeom_2f1/ /res/ /a/ /b/ /c/ /x/ /regularized/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_hypgeom_2f1_"+ arb_fpwrap_cdouble_hypgeom_2f1 :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_double_hypgeom_pfq/ /res/ /a/ /p/ /b/ /q/ /z/ /regularized/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_hypgeom_pfq_"+ arb_fpwrap_double_hypgeom_pfq :: Ptr CDouble -> Ptr CDouble -> CLong -> Ptr CDouble -> CLong -> CDouble -> CInt -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_hypgeom_pfq/ /res/ /a/ /p/ /b/ /q/ /z/ /regularized/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_hypgeom_pfq_"+ arb_fpwrap_cdouble_hypgeom_pfq :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CLong -> Ptr (Complex CDouble) -> CLong -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- Elliptic integrals, elliptic functions and modular forms --------------------++-- | /arb_fpwrap_double_agm/ /res/ /x/ /y/ /flags/ +foreign import ccall "arb_fpwrap.h arb_fpwrap_double_agm_"+ arb_fpwrap_double_agm :: Ptr CDouble -> CDouble -> CDouble -> CInt -> IO FpWrapReturn+-- | /arb_fpwrap_cdouble_agm/ /res/ /x/ /y/ /flags/ +--+-- Arithmetic-geometric mean.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_agm_"+ arb_fpwrap_cdouble_agm :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_k/ /res/ /m/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_k_"+ arb_fpwrap_cdouble_elliptic_k :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_e/ /res/ /m/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_e_"+ arb_fpwrap_cdouble_elliptic_e :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_pi/ /res/ /n/ /m/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_pi_"+ arb_fpwrap_cdouble_elliptic_pi :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_f/ /res/ /phi/ /m/ /pi/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_f_"+ arb_fpwrap_cdouble_elliptic_f :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_e_inc/ /res/ /phi/ /m/ /pi/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_e_inc_"+ arb_fpwrap_cdouble_elliptic_e_inc :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_pi_inc/ /res/ /n/ /phi/ /m/ /pi/ /flags/ +--+-- Complete and incomplete elliptic integrals.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_pi_inc_"+ arb_fpwrap_cdouble_elliptic_pi_inc :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_rf/ /res/ /x/ /y/ /z/ /option/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_rf_"+ arb_fpwrap_cdouble_elliptic_rf :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_rg/ /res/ /x/ /y/ /z/ /option/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_rg_"+ arb_fpwrap_cdouble_elliptic_rg :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_rj/ /res/ /x/ /y/ /z/ /w/ /option/ /flags/ +--+-- Carlson symmetric elliptic integrals.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_rj_"+ arb_fpwrap_cdouble_elliptic_rj :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_p/ /res/ /z/ /tau/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_p_"+ arb_fpwrap_cdouble_elliptic_p :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_p_prime/ /res/ /z/ /tau/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_p_prime_"+ arb_fpwrap_cdouble_elliptic_p_prime :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_inv_p/ /res/ /z/ /tau/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_inv_p_"+ arb_fpwrap_cdouble_elliptic_inv_p :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_zeta/ /res/ /z/ /tau/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_zeta_"+ arb_fpwrap_cdouble_elliptic_zeta :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_elliptic_sigma/ /res/ /z/ /tau/ /flags/ +--+-- Weierstrass elliptic functions.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_elliptic_sigma_"+ arb_fpwrap_cdouble_elliptic_sigma :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_jacobi_theta_1/ /res/ /z/ /tau/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_jacobi_theta_1_"+ arb_fpwrap_cdouble_jacobi_theta_1 :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_jacobi_theta_2/ /res/ /z/ /tau/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_jacobi_theta_2_"+ arb_fpwrap_cdouble_jacobi_theta_2 :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_jacobi_theta_3/ /res/ /z/ /tau/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_jacobi_theta_3_"+ arb_fpwrap_cdouble_jacobi_theta_3 :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_jacobi_theta_4/ /res/ /z/ /tau/ /flags/ +--+-- Jacobi theta functions.+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_jacobi_theta_4_"+ arb_fpwrap_cdouble_jacobi_theta_4 :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_dedekind_eta/ /res/ /tau/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_dedekind_eta_"+ arb_fpwrap_cdouble_dedekind_eta :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_modular_j/ /res/ /tau/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_modular_j_"+ arb_fpwrap_cdouble_modular_j :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_modular_lambda/ /res/ /tau/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_modular_lambda_"+ arb_fpwrap_cdouble_modular_lambda :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn++-- | /arb_fpwrap_cdouble_modular_delta/ /res/ /tau/ /flags/ +--+foreign import ccall "arb_fpwrap.h arb_fpwrap_cdouble_modular_delta_"+ arb_fpwrap_cdouble_modular_delta :: Ptr (Complex CDouble) -> Ptr (Complex CDouble) -> CInt -> IO FpWrapReturn+++
+ src/Data/Number/Flint/Arb/Hypgeom.hs view
@@ -0,0 +1,17 @@+{- | See [Data.Number.Flint.Acb.Hypgeom]("Data.Number.Flint.Acb.Hypgeom")+for the general implementation of hypergeometric functions.++For convenience, this module provides versions of the same functions for+real variables represented using @Arb@ and @ArbPoly@. Most methods+are simple wrappers around the complex versions, but some of the+functions in this module have been further optimized specifically for+real variables.++This module also provides certain functions exclusive to real variables,+such as functions for computing real roots of common special functions.+-}+module Data.Number.Flint.Arb.Hypgeom (+ module Data.Number.Flint.Arb.Hypgeom.FFI+ ) where++import Data.Number.Flint.Arb.Hypgeom.FFI
+ src/Data/Number/Flint/Arb/Hypgeom/FFI.hsc view
@@ -0,0 +1,1063 @@+{-|+module : Data.Number.Flint.Arb.Hypgeom.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Arb.Hypgeom.FFI (+ -- * Hypergeometric functions of real variables+ -- * Rising factorials+ _arb_hypgeom_rising_coeffs_1+ , _arb_hypgeom_rising_coeffs_2+ , _arb_hypgeom_rising_coeffs_fmpz+ , arb_hypgeom_rising_ui_forward+ , arb_hypgeom_rising_ui_bs+ , arb_hypgeom_rising_ui_rs+ , arb_hypgeom_rising_ui_rec+ , arb_hypgeom_rising_ui+ , arb_hypgeom_rising+ , arb_hypgeom_rising_ui_jet_powsum+ , arb_hypgeom_rising_ui_jet_bs+ , arb_hypgeom_rising_ui_jet_rs+ , arb_hypgeom_rising_ui_jet+ -- * Gamma function+ , _arb_hypgeom_gamma_stirling_term_bounds+ , arb_hypgeom_gamma_stirling_sum_horner+ , arb_hypgeom_gamma_stirling_sum_improved+ , arb_hypgeom_gamma_stirling+ , arb_hypgeom_gamma_taylor+ , arb_hypgeom_gamma+ , arb_hypgeom_gamma_fmpq+ , arb_hypgeom_gamma_fmpz+ , arb_hypgeom_rgamma+ , arb_hypgeom_lgamma+ -- * Binomial coefficients+ , arb_hypgeom_central_bin_ui+ -- * Generalized hypergeometric function+ , arb_hypgeom_pfq+ -- * Confluent hypergeometric functions+ , arb_hypgeom_0f1+ , arb_hypgeom_m+ , arb_hypgeom_1f1+ , arb_hypgeom_1f1_integration+ , arb_hypgeom_u+ , arb_hypgeom_u_integration+ -- * Gauss hypergeometric function+ , arb_hypgeom_2f1+ , arb_hypgeom_2f1_integration+ -- * Error functions and Fresnel integrals+ , arb_hypgeom_erf+ , _arb_hypgeom_erf_series+ , arb_hypgeom_erf_series+ , arb_hypgeom_erfc+ , _arb_hypgeom_erfc_series+ , arb_hypgeom_erfc_series+ , arb_hypgeom_erfi+ , _arb_hypgeom_erfi_series+ , arb_hypgeom_erfi_series+ , arb_hypgeom_erfinv+ , arb_hypgeom_erfcinv+ , arb_hypgeom_fresnel+ , _arb_hypgeom_fresnel_series+ , arb_hypgeom_fresnel_series+ -- * Incomplete gamma and beta functions+ , arb_hypgeom_gamma_upper+ , arb_hypgeom_gamma_upper_integration+ , _arb_hypgeom_gamma_upper_series+ , arb_hypgeom_gamma_upper_series+ , arb_hypgeom_gamma_lower+ , _arb_hypgeom_gamma_lower_series+ , arb_hypgeom_gamma_lower_series+ , arb_hypgeom_beta_lower+ , _arb_hypgeom_beta_lower_series+ , arb_hypgeom_beta_lower_series+ -- * Internal evaluation functions+ , _arb_hypgeom_gamma_lower_sum_rs_1+ , _arb_hypgeom_gamma_upper_sum_rs_1+ , _arb_hypgeom_gamma_upper_fmpq_inf_choose_N+ , _arb_hypgeom_gamma_upper_fmpq_inf_bsplit+ , _arb_hypgeom_gamma_lower_fmpq_0_choose_N+ , _arb_hypgeom_gamma_lower_fmpq_0_bsplit+ , _arb_hypgeom_gamma_upper_singular_si_choose_N+ , _arb_hypgeom_gamma_upper_singular_si_bsplit+ , _arb_gamma_upper_fmpq_step_bsplit+ -- * Exponential and trigonometric integrals+ , arb_hypgeom_expint+ , arb_hypgeom_ei+ , _arb_hypgeom_ei_series+ , arb_hypgeom_ei_series+ , _arb_hypgeom_si_asymp+ , _arb_hypgeom_si_1f2+ , arb_hypgeom_si+ , _arb_hypgeom_si_series+ , arb_hypgeom_si_series+ , _arb_hypgeom_ci_asymp+ , _arb_hypgeom_ci_2f3+ , arb_hypgeom_ci+ , _arb_hypgeom_ci_series+ , arb_hypgeom_ci_series+ , arb_hypgeom_shi+ , _arb_hypgeom_shi_series+ , arb_hypgeom_shi_series+ , arb_hypgeom_chi+ , _arb_hypgeom_chi_series+ , arb_hypgeom_chi_series+ , arb_hypgeom_li+ , _arb_hypgeom_li_series+ , arb_hypgeom_li_series+ -- * Bessel functions+ , arb_hypgeom_bessel_j+ , arb_hypgeom_bessel_y+ , arb_hypgeom_bessel_jy+ , arb_hypgeom_bessel_i+ , arb_hypgeom_bessel_i_scaled+ , arb_hypgeom_bessel_k+ , arb_hypgeom_bessel_k_scaled+ , arb_hypgeom_bessel_i_integration+ , arb_hypgeom_bessel_k_integration+ -- * Airy functions+ , arb_hypgeom_airy+ , arb_hypgeom_airy_jet+ , _arb_hypgeom_airy_series+ , arb_hypgeom_airy_series+ , arb_hypgeom_airy_zero+ -- * Coulomb wave functions+ , arb_hypgeom_coulomb+ , arb_hypgeom_coulomb_jet+ , _arb_hypgeom_coulomb_series+ , arb_hypgeom_coulomb_series+ -- * Orthogonal polynomials and functions+ , arb_hypgeom_chebyshev_t+ , arb_hypgeom_chebyshev_u+ , arb_hypgeom_jacobi_p+ , arb_hypgeom_gegenbauer_c+ , arb_hypgeom_laguerre_l+ , arb_hypgeom_hermite_h+ , arb_hypgeom_legendre_p+ , arb_hypgeom_legendre_q+ , arb_hypgeom_legendre_p_ui_deriv_bound+ , arb_hypgeom_legendre_p_ui_zero+ , arb_hypgeom_legendre_p_ui_one+ , arb_hypgeom_legendre_p_ui_asymp+ --, arb_hypgeom_legendre_p_rec+ , arb_hypgeom_legendre_p_ui+ , arb_hypgeom_legendre_p_ui_root+ -- * Dilogarithm+ , arb_hypgeom_dilog+ -- * Hypergeometric sums+ , arb_hypgeom_sum_fmpq_arb_forward+ , arb_hypgeom_sum_fmpq_arb_rs+ , arb_hypgeom_sum_fmpq_arb+ , arb_hypgeom_sum_fmpq_imag_arb_forward+ , arb_hypgeom_sum_fmpq_imag_arb_rs+ , arb_hypgeom_sum_fmpq_imag_arb_bs+ , arb_hypgeom_sum_fmpq_imag_arb+) where++-- Hypergeometric functions of real variables ----------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.C.String++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Arb.Types++-- Rising factorials -----------------------------------------------------------++-- | /_arb_hypgeom_rising_coeffs_1/ /c/ /k/ /n/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_rising_coeffs_1"+ _arb_hypgeom_rising_coeffs_1 :: Ptr CULong -> CULong -> CLong -> IO ()+-- | /_arb_hypgeom_rising_coeffs_2/ /c/ /k/ /n/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_rising_coeffs_2"+ _arb_hypgeom_rising_coeffs_2 :: Ptr CULong -> CULong -> CLong -> IO ()+-- | /_arb_hypgeom_rising_coeffs_fmpz/ /c/ /k/ /n/ +--+-- Sets /c/ to the coefficients of the rising factorial polynomial+-- \((X+k)_n\). The /1/ and /2/ versions respectively compute single-word+-- and double-word coefficients, without checking for overflow, while the+-- /fmpz/ version allows arbitrarily large coefficients. These functions+-- are mostly intended for internal use; the /fmpz/ version does not use an+-- asymptotically fast algorithm. The degree /n/ must be at least 2.+foreign import ccall "arb_hypgeom.h _arb_hypgeom_rising_coeffs_fmpz"+ _arb_hypgeom_rising_coeffs_fmpz :: Ptr CFmpz -> CULong -> CLong -> IO ()++-- | /arb_hypgeom_rising_ui_forward/ /res/ /x/ /n/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_rising_ui_forward"+ arb_hypgeom_rising_ui_forward :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()+-- | /arb_hypgeom_rising_ui_bs/ /res/ /x/ /n/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_rising_ui_bs"+ arb_hypgeom_rising_ui_bs :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()+-- | /arb_hypgeom_rising_ui_rs/ /res/ /x/ /n/ /m/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_rising_ui_rs"+ arb_hypgeom_rising_ui_rs :: Ptr CArb -> Ptr CArb -> CULong -> CULong -> CLong -> IO ()+-- | /arb_hypgeom_rising_ui_rec/ /res/ /x/ /n/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_rising_ui_rec"+ arb_hypgeom_rising_ui_rec :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()+-- | /arb_hypgeom_rising_ui/ /res/ /x/ /n/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_rising_ui"+ arb_hypgeom_rising_ui :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> IO ()+-- | /arb_hypgeom_rising/ /res/ /x/ /n/ /prec/ +--+-- Computes the rising factorial \((x)_n\).+-- +-- The /forward/ version uses the forward recurrence. The /bs/ version uses+-- binary splitting. The /rs/ version uses rectangular splitting. It takes+-- an extra tuning parameter /m/ which can be set to zero to choose+-- automatically. The /rec/ version chooses an algorithm automatically,+-- avoiding use of the gamma function (so that it can be used in the+-- computation of the gamma function). The default versions (/rising_ui/+-- and /rising_ui/) choose an algorithm automatically and may additionally+-- fall back on the gamma function.+foreign import ccall "arb_hypgeom.h arb_hypgeom_rising"+ arb_hypgeom_rising :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_rising_ui_jet_powsum/ /res/ /x/ /n/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_rising_ui_jet_powsum"+ arb_hypgeom_rising_ui_jet_powsum :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_rising_ui_jet_bs/ /res/ /x/ /n/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_rising_ui_jet_bs"+ arb_hypgeom_rising_ui_jet_bs :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_rising_ui_jet_rs/ /res/ /x/ /n/ /m/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_rising_ui_jet_rs"+ arb_hypgeom_rising_ui_jet_rs :: Ptr CArb -> Ptr CArb -> CULong -> CULong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_rising_ui_jet/ /res/ /x/ /n/ /len/ /prec/ +--+-- Computes the jet of the rising factorial \((x)_n\), truncated to length+-- /len/. In other words, constructs the polynomial+-- \((X + x)_n \in \mathbb{R}[X]\), truncated if+-- \(\operatorname{len} < n + 1\) (and zero-extended if+-- \(\operatorname{len} > n + 1\)).+-- +-- The /powsum/ version computes the sequence of powers of /x/ and forms+-- integral linear combinations of these. The /bs/ version uses binary+-- splitting. The /rs/ version uses rectangular splitting. It takes an+-- extra tuning parameter /m/ which can be set to zero to choose+-- automatically. The default version chooses an algorithm automatically.+foreign import ccall "arb_hypgeom.h arb_hypgeom_rising_ui_jet"+ arb_hypgeom_rising_ui_jet :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> CLong -> IO ()++-- Gamma function --------------------------------------------------------------++-- | /_arb_hypgeom_gamma_stirling_term_bounds/ /bound/ /zinv/ /N/ +--+-- For \(1 \le n < N\), sets /bound/ to an exponent bounding the /n/-th+-- term in the Stirling series for the gamma function, given a precomputed+-- upper bound for \(|z|^{-1}\). This function is intended for internal use+-- and does not check for underflow or underflow in the exponents.+foreign import ccall "arb_hypgeom.h _arb_hypgeom_gamma_stirling_term_bounds"+ _arb_hypgeom_gamma_stirling_term_bounds :: Ptr CLong -> Ptr CMag -> CLong -> IO ()++-- | /arb_hypgeom_gamma_stirling_sum_horner/ /res/ /z/ /N/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma_stirling_sum_horner"+ arb_hypgeom_gamma_stirling_sum_horner :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_gamma_stirling_sum_improved/ /res/ /z/ /N/ /K/ /prec/ +--+-- Sets /res/ to the final sum in the Stirling series for the gamma+-- function truncated before the term with index /N/, i.e. computes+-- \(\sum_{n=1}^{N-1} B_{2n} / (2n(2n-1) z^{2n-1})\). The /horner/ version+-- uses Horner scheme with gradual precision adjustments. The /improved/+-- version uses rectangular splitting for the low-index terms and reexpands+-- the high-index terms as hypergeometric polynomials, using a splitting+-- parameter /K/ (which can be set to 0 to use a default value).+foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma_stirling_sum_improved"+ arb_hypgeom_gamma_stirling_sum_improved :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_gamma_stirling/ /res/ /x/ /reciprocal/ /prec/ +--+-- Sets /res/ to the gamma function of /x/ computed using the Stirling+-- series together with argument reduction. If /reciprocal/ is set, the+-- reciprocal gamma function is computed instead.+foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma_stirling"+ arb_hypgeom_gamma_stirling :: Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /arb_hypgeom_gamma_taylor/ /res/ /x/ /reciprocal/ /prec/ +--+-- Attempts to compute the gamma function of /x/ using Taylor series+-- together with argument reduction. This is only supported if /x/ and+-- /prec/ are both small enough. If successful, returns 1; otherwise, does+-- nothing and returns 0. If /reciprocal/ is set, the reciprocal gamma+-- function is computed instead.+foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma_taylor"+ arb_hypgeom_gamma_taylor :: Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO CInt++-- | /arb_hypgeom_gamma/ /res/ /x/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma"+ arb_hypgeom_gamma :: Ptr CArb -> Ptr CArb -> CLong -> IO ()+-- | /arb_hypgeom_gamma_fmpq/ /res/ /x/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma_fmpq"+ arb_hypgeom_gamma_fmpq :: Ptr CArb -> Ptr CFmpq -> CLong -> IO ()+-- | /arb_hypgeom_gamma_fmpz/ /res/ /x/ /prec/ +--+-- Sets /res/ to the gamma function of /x/ computed using a default+-- algorithm choice.+foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma_fmpz"+ arb_hypgeom_gamma_fmpz :: Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_hypgeom_rgamma/ /res/ /x/ /prec/ +--+-- Sets /res/ to the reciprocal gamma function of /x/ computed using a+-- default algorithm choice.+foreign import ccall "arb_hypgeom.h arb_hypgeom_rgamma"+ arb_hypgeom_rgamma :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_lgamma/ /res/ /x/ /prec/ +--+-- Sets /res/ to the log-gamma function of /x/ computed using a default+-- algorithm choice.+foreign import ccall "arb_hypgeom.h arb_hypgeom_lgamma"+ arb_hypgeom_lgamma :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- Binomial coefficients -------------------------------------------------------++-- | /arb_hypgeom_central_bin_ui/ /res/ /n/ /prec/ +--+-- Computes the central binomial coefficient \({2n \choose n}\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_central_bin_ui"+ arb_hypgeom_central_bin_ui :: Ptr CArb -> CULong -> CLong -> IO ()++-- Generalized hypergeometric function -----------------------------------------++-- | /arb_hypgeom_pfq/ /res/ /a/ /p/ /b/ /q/ /z/ /regularized/ /prec/ +--+-- Computes the generalized hypergeometric function \({}_pF_{q}(z)\), or+-- the regularized version if /regularized/ is set.+foreign import ccall "arb_hypgeom.h arb_hypgeom_pfq"+ arb_hypgeom_pfq :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> Ptr CArb -> CInt -> CLong -> IO ()++-- Confluent hypergeometric functions ------------------------------------------++-- | /arb_hypgeom_0f1/ /res/ /a/ /z/ /regularized/ /prec/ +--+-- Computes the confluent hypergeometric limit function \({}_0F_1(a,z)\),+-- or \(\frac{1}{\Gamma(a)} {}_0F_1(a,z)\) if /regularized/ is set.+foreign import ccall "arb_hypgeom.h arb_hypgeom_0f1"+ arb_hypgeom_0f1 :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /arb_hypgeom_m/ /res/ /a/ /b/ /z/ /regularized/ /prec/ +--+-- Computes the confluent hypergeometric function+-- \(M(a,b,z) = {}_1F_1(a,b,z)\), or+-- \(\mathbf{M}(a,b,z) = \frac{1}{\Gamma(b)} {}_1F_1(a,b,z)\) if+-- /regularized/ is set.+foreign import ccall "arb_hypgeom.h arb_hypgeom_m"+ arb_hypgeom_m :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /arb_hypgeom_1f1/ /res/ /a/ /b/ /z/ /regularized/ /prec/ +--+-- Alias for @arb_hypgeom_m@.+foreign import ccall "arb_hypgeom.h arb_hypgeom_1f1"+ arb_hypgeom_1f1 :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /arb_hypgeom_1f1_integration/ /res/ /a/ /b/ /z/ /regularized/ /prec/ +--+-- Computes the confluent hypergeometric function using numerical+-- integration of the representation+-- +-- \[`\]+-- \[{}_1F_1(a,b,z) = \frac{\Gamma(b)}{\Gamma(a) \Gamma(b-a)} \int_0^1 e^{zt} t^{a-1} (1-t)^{b-a-1} dt.\]+-- +-- This algorithm can be useful if the parameters are large. This will+-- currently only return a finite enclosure if \(a \ge 1\) and+-- \(b - a \ge 1\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_1f1_integration"+ arb_hypgeom_1f1_integration :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /arb_hypgeom_u/ /res/ /a/ /b/ /z/ /prec/ +--+-- Computes the confluent hypergeometric function \(U(a,b,z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_u"+ arb_hypgeom_u :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_u_integration/ /res/ /a/ /b/ /z/ /regularized/ /prec/ +--+-- Computes the confluent hypergeometric function \(U(a,b,z)\) using+-- numerical integration of the representation+-- +-- \[`\]+-- \[U(a,b,z) = \frac{1}{\Gamma(a)} \int_0^{\infty} e^{-zt} t^{a-1} (1+t)^{b-a-1} dt.\]+-- +-- This algorithm can be useful if the parameters are large. This will+-- currently only return a finite enclosure if \(a \ge 1\) and \(z > 0\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_u_integration"+ arb_hypgeom_u_integration :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- Gauss hypergeometric function -----------------------------------------------++-- | /arb_hypgeom_2f1/ /res/ /a/ /b/ /c/ /z/ /regularized/ /prec/ +--+-- Computes the Gauss hypergeometric function \({}_2F_1(a,b,c,z)\), or+-- \(\mathbf{F}(a,b,c,z) = \frac{1}{\Gamma(c)} {}_2F_1(a,b,c,z)\) if+-- /regularized/ is set.+-- +-- Additional evaluation flags can be passed via the /regularized/+-- argument; see @acb_hypgeom_2f1@ for documentation.+foreign import ccall "arb_hypgeom.h arb_hypgeom_2f1"+ arb_hypgeom_2f1 :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /arb_hypgeom_2f1_integration/ /res/ /a/ /b/ /z/ /regularized/ /prec/ +--+-- Computes the Gauss hypergeometric function using numerical integration+-- of the representation+-- +-- \[`\]+-- \[{}_2F_1(a,b,c,z) = \frac{\Gamma(a)}{\Gamma(b) \Gamma(c-b)} \int_0^1 t^{b-1} (1-t)^{c-b-1} (1-zt)^{-a} dt.\]+-- +-- This algorithm can be useful if the parameters are large. This will+-- currently only return a finite enclosure if \(b \ge 1\) and+-- \(c - b \ge 1\) and \(z < 1\), possibly with /a/ and /b/ exchanged.+foreign import ccall "arb_hypgeom.h arb_hypgeom_2f1_integration"+ arb_hypgeom_2f1_integration :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- Error functions and Fresnel integrals ---------------------------------------++-- | /arb_hypgeom_erf/ /res/ /z/ /prec/ +--+-- Computes the error function \(\operatorname{erf}(z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_erf"+ arb_hypgeom_erf :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /_arb_hypgeom_erf_series/ /res/ /z/ /zlen/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_erf_series"+ _arb_hypgeom_erf_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_erf_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the error function of the power series /z/, truncated to length+-- /len/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_erf_series"+ arb_hypgeom_erf_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_erfc/ /res/ /z/ /prec/ +--+-- Computes the complementary error function+-- \(\operatorname{erfc}(z) = 1 - \operatorname{erf}(z)\). This function+-- avoids catastrophic cancellation for large positive /z/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_erfc"+ arb_hypgeom_erfc :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /_arb_hypgeom_erfc_series/ /res/ /z/ /zlen/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_erfc_series"+ _arb_hypgeom_erfc_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_erfc_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the complementary error function of the power series /z/,+-- truncated to length /len/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_erfc_series"+ arb_hypgeom_erfc_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_erfi/ /res/ /z/ /prec/ +--+-- Computes the imaginary error function+-- \(\operatorname{erfi}(z) = -i\operatorname{erf}(iz)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_erfi"+ arb_hypgeom_erfi :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /_arb_hypgeom_erfi_series/ /res/ /z/ /zlen/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_erfi_series"+ _arb_hypgeom_erfi_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_erfi_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the imaginary error function of the power series /z/, truncated+-- to length /len/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_erfi_series"+ arb_hypgeom_erfi_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_erfinv/ /res/ /z/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_erfinv"+ arb_hypgeom_erfinv :: Ptr CArb -> Ptr CArb -> CLong -> IO ()+-- | /arb_hypgeom_erfcinv/ /res/ /z/ /prec/ +--+-- Computes the inverse error function \(\operatorname{erf}^{-1}(z)\) or+-- inverse complementary error function \(\operatorname{erfc}^{-1}(z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_erfcinv"+ arb_hypgeom_erfcinv :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_fresnel/ /res1/ /res2/ /z/ /normalized/ /prec/ +--+-- Sets /res1/ to the Fresnel sine integral \(S(z)\) and /res2/ to the+-- Fresnel cosine integral \(C(z)\). Optionally, just a single function can+-- be computed by passing /NULL/ as the other output variable. The+-- definition \(S(z) = \int_0^z \sin(t^2) dt\) is used if /normalized/ is+-- 0, and \(S(z) = \int_0^z \sin(\tfrac{1}{2} \pi t^2) dt\) is used if+-- /normalized/ is 1 (the latter is the Abramowitz & Stegun convention).+-- \(C(z)\) is defined analogously.+foreign import ccall "arb_hypgeom.h arb_hypgeom_fresnel"+ arb_hypgeom_fresnel :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /_arb_hypgeom_fresnel_series/ /res1/ /res2/ /z/ /zlen/ /normalized/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_fresnel_series"+ _arb_hypgeom_fresnel_series :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CInt -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_fresnel_series/ /res1/ /res2/ /z/ /normalized/ /len/ /prec/ +--+-- Sets /res1/ to the Fresnel sine integral and /res2/ to the Fresnel+-- cosine integral of the power series /z/, truncated to length /len/.+-- Optionally, just a single function can be computed by passing /NULL/ as+-- the other output variable.+foreign import ccall "arb_hypgeom.h arb_hypgeom_fresnel_series"+ arb_hypgeom_fresnel_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CInt -> CLong -> CLong -> IO ()++-- Incomplete gamma and beta functions -----------------------------------------++-- | /arb_hypgeom_gamma_upper/ /res/ /s/ /z/ /regularized/ /prec/ +--+-- If /regularized/ is 0, computes the upper incomplete gamma function+-- \(\Gamma(s,z)\).+-- +-- If /regularized/ is 1, computes the regularized upper incomplete gamma+-- function \(Q(s,z) = \Gamma(s,z) / \Gamma(s)\).+-- +-- If /regularized/ is 2, computes the generalized exponential integral+-- \(z^{-s} \Gamma(s,z) = E_{1-s}(z)\) instead (this option is mainly+-- intended for internal use; @arb_hypgeom_expint@ is the intended+-- interface for computing the exponential integral).+foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma_upper"+ arb_hypgeom_gamma_upper :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /arb_hypgeom_gamma_upper_integration/ /res/ /s/ /z/ /regularized/ /prec/ +--+-- Computes the upper incomplete gamma function using numerical+-- integration.+foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma_upper_integration"+ arb_hypgeom_gamma_upper_integration :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /_arb_hypgeom_gamma_upper_series/ /res/ /s/ /z/ /zlen/ /regularized/ /n/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_gamma_upper_series"+ _arb_hypgeom_gamma_upper_series :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CInt -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_gamma_upper_series/ /res/ /s/ /z/ /regularized/ /n/ /prec/ +--+-- Sets /res/ to an upper incomplete gamma function where /s/ is a constant+-- and /z/ is a power series, truncated to length /n/. The /regularized/+-- argument has the same interpretation as in @arb_hypgeom_gamma_upper@.+foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma_upper_series"+ arb_hypgeom_gamma_upper_series :: Ptr CArbPoly -> Ptr CArb -> Ptr CArbPoly -> CInt -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_gamma_lower/ /res/ /s/ /z/ /regularized/ /prec/ +--+-- If /regularized/ is 0, computes the lower incomplete gamma function+-- \(\gamma(s,z) = \frac{z^s}{s} {}_1F_1(s, s+1, -z)\).+-- +-- If /regularized/ is 1, computes the regularized lower incomplete gamma+-- function \(P(s,z) = \gamma(s,z) / \Gamma(s)\).+-- +-- If /regularized/ is 2, computes a further regularized lower incomplete+-- gamma function \(\gamma^{*}(s,z) = z^{-s} P(s,z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma_lower"+ arb_hypgeom_gamma_lower :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /_arb_hypgeom_gamma_lower_series/ /res/ /s/ /z/ /zlen/ /regularized/ /n/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_gamma_lower_series"+ _arb_hypgeom_gamma_lower_series :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CInt -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_gamma_lower_series/ /res/ /s/ /z/ /regularized/ /n/ /prec/ +--+-- Sets /res/ to an lower incomplete gamma function where /s/ is a constant+-- and /z/ is a power series, truncated to length /n/. The /regularized/+-- argument has the same interpretation as in @arb_hypgeom_gamma_lower@.+foreign import ccall "arb_hypgeom.h arb_hypgeom_gamma_lower_series"+ arb_hypgeom_gamma_lower_series :: Ptr CArbPoly -> Ptr CArb -> Ptr CArbPoly -> CInt -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_beta_lower/ /res/ /a/ /b/ /z/ /regularized/ /prec/ +--+-- Computes the (lower) incomplete beta function, defined by+-- \(B(a,b;z) = \int_0^z t^{a-1} (1-t)^{b-1}\), optionally the regularized+-- incomplete beta function \(I(a,b;z) = B(a,b;z) / B(a,b;1)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_beta_lower"+ arb_hypgeom_beta_lower :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /_arb_hypgeom_beta_lower_series/ /res/ /a/ /b/ /z/ /zlen/ /regularized/ /n/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_beta_lower_series"+ _arb_hypgeom_beta_lower_series :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CInt -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_beta_lower_series/ /res/ /a/ /b/ /z/ /regularized/ /n/ /prec/ +--+-- Sets /res/ to the lower incomplete beta function \(B(a,b;z)\)+-- (optionally the regularized version \(I(a,b;z)\)) where /a/ and /b/ are+-- constants and /z/ is a power series, truncating the result to length+-- /n/. The underscore method requires positive lengths and does not+-- support aliasing.+foreign import ccall "arb_hypgeom.h arb_hypgeom_beta_lower_series"+ arb_hypgeom_beta_lower_series :: Ptr CArbPoly -> Ptr CArb -> Ptr CArb -> Ptr CArbPoly -> CInt -> CLong -> CLong -> IO ()++-- Internal evaluation functions -----------------------------------------------++-- | /_arb_hypgeom_gamma_lower_sum_rs_1/ /res/ /p/ /q/ /z/ /N/ /prec/ +--+-- Computes \(\sum_{k=0}^{N-1} z^k / (a)_k\) where \(a = p/q\) using+-- rectangular splitting. It is assumed that \(p + qN\) fits in a limb.+foreign import ccall "arb_hypgeom.h _arb_hypgeom_gamma_lower_sum_rs_1"+ _arb_hypgeom_gamma_lower_sum_rs_1 :: Ptr CArb -> CULong -> CULong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_hypgeom_gamma_upper_sum_rs_1/ /res/ /p/ /q/ /z/ /N/ /prec/ +--+-- Computes \(\sum_{k=0}^{N-1} (a)_k / z^k\) where \(a = p/q\) using+-- rectangular splitting. It is assumed that \(p + qN\) fits in a limb.+foreign import ccall "arb_hypgeom.h _arb_hypgeom_gamma_upper_sum_rs_1"+ _arb_hypgeom_gamma_upper_sum_rs_1 :: Ptr CArb -> CULong -> CULong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_hypgeom_gamma_upper_fmpq_inf_choose_N/ /err/ /a/ /z/ /abs_tol/ +--+-- Returns number of terms /N/ and sets /err/ to the truncation error for+-- evaluating \(\Gamma(a,z)\) using the asymptotic series at infinity,+-- targeting an absolute tolerance of /abs_tol/. The error may be set to+-- /err/ if the tolerance cannot be achieved. Assumes that /z/ is positive.+foreign import ccall "arb_hypgeom.h _arb_hypgeom_gamma_upper_fmpq_inf_choose_N"+ _arb_hypgeom_gamma_upper_fmpq_inf_choose_N :: Ptr CMag -> Ptr CFmpq -> Ptr CArb -> Ptr CMag -> IO CLong++-- | /_arb_hypgeom_gamma_upper_fmpq_inf_bsplit/ /res/ /a/ /z/ /N/ /prec/ +--+-- Sets /res/ to the approximation of \(\Gamma(a,z)\) obtained by+-- truncating the asymptotic series at infinity before term /N/. The+-- truncation error bound has to be added separately.+foreign import ccall "arb_hypgeom.h _arb_hypgeom_gamma_upper_fmpq_inf_bsplit"+ _arb_hypgeom_gamma_upper_fmpq_inf_bsplit :: Ptr CArb -> Ptr CFmpq -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_hypgeom_gamma_lower_fmpq_0_choose_N/ /err/ /a/ /z/ /abs_tol/ +--+-- Returns number of terms /N/ and sets /err/ to the truncation error for+-- evaluating \(\gamma(a,z)\) using the Taylor series at zero, targeting an+-- absolute tolerance of /abs_tol/. Assumes that /z/ is positive.+foreign import ccall "arb_hypgeom.h _arb_hypgeom_gamma_lower_fmpq_0_choose_N"+ _arb_hypgeom_gamma_lower_fmpq_0_choose_N :: Ptr CMag -> Ptr CFmpq -> Ptr CArb -> Ptr CMag -> IO CLong++-- | /_arb_hypgeom_gamma_lower_fmpq_0_bsplit/ /res/ /a/ /z/ /N/ /prec/ +--+-- Sets /res/ to the approximation of \(\gamma(a,z)\) obtained by+-- truncating the Taylor series at zero before term /N/. The truncation+-- error bound has to be added separately.+foreign import ccall "arb_hypgeom.h _arb_hypgeom_gamma_lower_fmpq_0_bsplit"+ _arb_hypgeom_gamma_lower_fmpq_0_bsplit :: Ptr CArb -> Ptr CFmpq -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_hypgeom_gamma_upper_singular_si_choose_N/ /err/ /n/ /z/ /abs_tol/ +--+-- Returns number of terms /N/ and sets /err/ to the truncation error for+-- evaluating \(\Gamma(-n,z)\) using the Taylor series at zero, targeting+-- an absolute tolerance of /abs_tol/.+foreign import ccall "arb_hypgeom.h _arb_hypgeom_gamma_upper_singular_si_choose_N"+ _arb_hypgeom_gamma_upper_singular_si_choose_N :: Ptr CMag -> CLong -> Ptr CArb -> Ptr CMag -> IO CLong++-- | /_arb_hypgeom_gamma_upper_singular_si_bsplit/ /res/ /n/ /z/ /N/ /prec/ +--+-- Sets /res/ to the approximation of \(\Gamma(-n,z)\) obtained by+-- truncating the Taylor series at zero before term /N/. The truncation+-- error bound has to be added separately.+foreign import ccall "arb_hypgeom.h _arb_hypgeom_gamma_upper_singular_si_bsplit"+ _arb_hypgeom_gamma_upper_singular_si_bsplit :: Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_gamma_upper_fmpq_step_bsplit/ /Gz1/ /a/ /z0/ /z1/ /Gz0/ /expmz0/ /abs_tol/ /prec/ +--+-- Given /Gz0/ and /expmz0/ representing the values \(\Gamma(a,z_0)\) and+-- \(\exp(-z_0)\), computes \(\Gamma(a,z_1)\) using the Taylor series at+-- \(z_0\) evaluated using binary splitting, targeting an absolute error of+-- /abs_tol/. Assumes that \(z_0\) and \(z_1\) are positive.+foreign import ccall "arb_hypgeom.h _arb_gamma_upper_fmpq_step_bsplit"+ _arb_gamma_upper_fmpq_step_bsplit :: Ptr CArb -> Ptr CFmpq -> Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CMag -> CLong -> IO ()++-- Exponential and trigonometric integrals -------------------------------------++-- | /arb_hypgeom_expint/ /res/ /s/ /z/ /prec/ +--+-- Computes the generalized exponential integral \(E_s(z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_expint"+ arb_hypgeom_expint :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_ei/ /res/ /z/ /prec/ +--+-- Computes the exponential integral \(\operatorname{Ei}(z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_ei"+ arb_hypgeom_ei :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /_arb_hypgeom_ei_series/ /res/ /z/ /zlen/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_ei_series"+ _arb_hypgeom_ei_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_ei_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the exponential integral of the power series /z/, truncated to+-- length /len/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_ei_series"+ arb_hypgeom_ei_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_hypgeom_si_asymp/ /res/ /z/ /N/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_si_asymp"+ _arb_hypgeom_si_asymp :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()+-- | /_arb_hypgeom_si_1f2/ /res/ /z/ /N/ /wp/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_si_1f2"+ _arb_hypgeom_si_1f2 :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_si/ /res/ /z/ /prec/ +--+-- Computes the sine integral \(\operatorname{Si}(z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_si"+ arb_hypgeom_si :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /_arb_hypgeom_si_series/ /res/ /z/ /zlen/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_si_series"+ _arb_hypgeom_si_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_si_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the sine integral of the power series /z/, truncated to length+-- /len/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_si_series"+ arb_hypgeom_si_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_hypgeom_ci_asymp/ /res/ /z/ /N/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_ci_asymp"+ _arb_hypgeom_ci_asymp :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()+-- | /_arb_hypgeom_ci_2f3/ /res/ /z/ /N/ /wp/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_ci_2f3"+ _arb_hypgeom_ci_2f3 :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_ci/ /res/ /z/ /prec/ +--+-- Computes the cosine integral \(\operatorname{Ci}(z)\). The result is+-- indeterminate if \(z < 0\) since the value of the function would be+-- complex.+foreign import ccall "arb_hypgeom.h arb_hypgeom_ci"+ arb_hypgeom_ci :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /_arb_hypgeom_ci_series/ /res/ /z/ /zlen/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_ci_series"+ _arb_hypgeom_ci_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_ci_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the cosine integral of the power series /z/, truncated to+-- length /len/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_ci_series"+ arb_hypgeom_ci_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_shi/ /res/ /z/ /prec/ +--+-- Computes the hyperbolic sine integral+-- \(\operatorname{Shi}(z) = -i \operatorname{Si}(iz)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_shi"+ arb_hypgeom_shi :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /_arb_hypgeom_shi_series/ /res/ /z/ /zlen/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_shi_series"+ _arb_hypgeom_shi_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_shi_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the hyperbolic sine integral of the power series /z/, truncated+-- to length /len/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_shi_series"+ arb_hypgeom_shi_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_chi/ /res/ /z/ /prec/ +--+-- Computes the hyperbolic cosine integral \(\operatorname{Chi}(z)\). The+-- result is indeterminate if \(z < 0\) since the value of the function+-- would be complex.+foreign import ccall "arb_hypgeom.h arb_hypgeom_chi"+ arb_hypgeom_chi :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /_arb_hypgeom_chi_series/ /res/ /z/ /zlen/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_chi_series"+ _arb_hypgeom_chi_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_chi_series/ /res/ /z/ /len/ /prec/ +--+-- Computes the hyperbolic cosine integral of the power series /z/,+-- truncated to length /len/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_chi_series"+ arb_hypgeom_chi_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_li/ /res/ /z/ /offset/ /prec/ +--+-- If /offset/ is zero, computes the logarithmic integral+-- \(\operatorname{li}(z) = \operatorname{Ei}(\log(z))\).+-- +-- If /offset/ is nonzero, computes the offset logarithmic integral+-- \(\operatorname{Li}(z) = \operatorname{li}(z) - \operatorname{li}(2)\).+-- +-- The result is indeterminate if \(z < 0\) since the value of the function+-- would be complex.+foreign import ccall "arb_hypgeom.h arb_hypgeom_li"+ arb_hypgeom_li :: Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /_arb_hypgeom_li_series/ /res/ /z/ /zlen/ /offset/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_li_series"+ _arb_hypgeom_li_series :: Ptr CArb -> Ptr CArb -> CLong -> CInt -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_li_series/ /res/ /z/ /offset/ /len/ /prec/ +--+-- Computes the logarithmic integral (optionally the offset version) of the+-- power series /z/, truncated to length /len/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_li_series"+ arb_hypgeom_li_series :: Ptr CArbPoly -> Ptr CArbPoly -> CInt -> CLong -> CLong -> IO ()++-- Bessel functions ------------------------------------------------------------++-- | /arb_hypgeom_bessel_j/ /res/ /nu/ /z/ /prec/ +--+-- Computes the Bessel function of the first kind \(J_{\nu}(z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_bessel_j"+ arb_hypgeom_bessel_j :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_bessel_y/ /res/ /nu/ /z/ /prec/ +--+-- Computes the Bessel function of the second kind \(Y_{\nu}(z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_bessel_y"+ arb_hypgeom_bessel_y :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_bessel_jy/ /res1/ /res2/ /nu/ /z/ /prec/ +--+-- Sets /res1/ to \(J_{\nu}(z)\) and /res2/ to \(Y_{\nu}(z)\), computed+-- simultaneously.+foreign import ccall "arb_hypgeom.h arb_hypgeom_bessel_jy"+ arb_hypgeom_bessel_jy :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_bessel_i/ /res/ /nu/ /z/ /prec/ +--+-- Computes the modified Bessel function of the first kind+-- \(I_{\nu}(z) = z^{\nu} (iz)^{-\nu} J_{\nu}(iz)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_bessel_i"+ arb_hypgeom_bessel_i :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_bessel_i_scaled/ /res/ /nu/ /z/ /prec/ +--+-- Computes the function \(e^{-z} I_{\nu}(z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_bessel_i_scaled"+ arb_hypgeom_bessel_i_scaled :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_bessel_k/ /res/ /nu/ /z/ /prec/ +--+-- Computes the modified Bessel function of the second kind \(K_{\nu}(z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_bessel_k"+ arb_hypgeom_bessel_k :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_bessel_k_scaled/ /res/ /nu/ /z/ /prec/ +--+-- Computes the function \(e^{z} K_{\nu}(z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_bessel_k_scaled"+ arb_hypgeom_bessel_k_scaled :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_bessel_i_integration/ /res/ /nu/ /z/ /scaled/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_bessel_i_integration"+ arb_hypgeom_bessel_i_integration :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()+-- | /arb_hypgeom_bessel_k_integration/ /res/ /nu/ /z/ /scaled/ /prec/ +--+-- Computes the modified Bessel functions using numerical integration.+foreign import ccall "arb_hypgeom.h arb_hypgeom_bessel_k_integration"+ arb_hypgeom_bessel_k_integration :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- Airy functions --------------------------------------------------------------++-- | /arb_hypgeom_airy/ /ai/ /ai_prime/ /bi/ /bi_prime/ /z/ /prec/ +--+-- Computes the Airy functions+-- \((\operatorname{Ai}(z), \operatorname{Ai}'(z), \operatorname{Bi}(z), \operatorname{Bi}'(z))\)+-- simultaneously. Any of the four function values can be omitted by+-- passing /NULL/ for the unwanted output variables, speeding up the+-- evaluation.+foreign import ccall "arb_hypgeom.h arb_hypgeom_airy"+ arb_hypgeom_airy :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_airy_jet/ /ai/ /bi/ /z/ /len/ /prec/ +--+-- Writes to /ai/ and /bi/ the respective Taylor expansions of the Airy+-- functions at the point /z/, truncated to length /len/. Either of the+-- outputs can be /NULL/ to avoid computing that function. The variable /z/+-- is not allowed to be aliased with the outputs. To simplify the+-- implementation, this method does not compute the series expansions of+-- the primed versions directly; these are easily obtained by computing one+-- extra coefficient and differentiating the output with+-- @_arb_poly_derivative@.+foreign import ccall "arb_hypgeom.h arb_hypgeom_airy_jet"+ arb_hypgeom_airy_jet :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_hypgeom_airy_series/ /ai/ /ai_prime/ /bi/ /bi_prime/ /z/ /zlen/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_airy_series"+ _arb_hypgeom_airy_series :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_airy_series/ /ai/ /ai_prime/ /bi/ /bi_prime/ /z/ /len/ /prec/ +--+-- Computes the Airy functions evaluated at the power series /z/, truncated+-- to length /len/. As with the other Airy methods, any of the outputs can+-- be /NULL/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_airy_series"+ arb_hypgeom_airy_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_airy_zero/ /a/ /a_prime/ /b/ /b_prime/ /n/ /prec/ +--+-- Computes the /n/-th real zero \(a_n\), \(a'_n\), \(b_n\), or \(b'_n\)+-- for the respective Airy function or Airy function derivative. Any+-- combination of the four output variables can be /NULL/. The zeros are+-- indexed by increasing magnitude, starting with \(n = 1\) to follow the+-- convention in the literature. An index /n/ that is not positive is+-- invalid input. The implementation uses asymptotic expansions for the+-- zeros < [PS1991]> together with the interval Newton method for+-- refinement.+foreign import ccall "arb_hypgeom.h arb_hypgeom_airy_zero"+ arb_hypgeom_airy_zero :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CFmpz -> CLong -> IO ()++-- Coulomb wave functions ------------------------------------------------------++-- | /arb_hypgeom_coulomb/ /F/ /G/ /l/ /eta/ /z/ /prec/ +--+-- Writes to /F/, /G/ the values of the respective Coulomb wave functions+-- \(F_{\ell}(\eta,z)\) and \(G_{\ell}(\eta,z)\). Either of the outputs can+-- be /NULL/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_coulomb"+ arb_hypgeom_coulomb :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_coulomb_jet/ /F/ /G/ /l/ /eta/ /z/ /len/ /prec/ +--+-- Writes to /F/, /G/ the respective Taylor expansions of the Coulomb wave+-- functions at the point /z/, truncated to length /len/. Either of the+-- outputs can be /NULL/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_coulomb_jet"+ arb_hypgeom_coulomb_jet :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_hypgeom_coulomb_series/ /F/ /G/ /l/ /eta/ /z/ /zlen/ /len/ /prec/ +foreign import ccall "arb_hypgeom.h _arb_hypgeom_coulomb_series"+ _arb_hypgeom_coulomb_series :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_coulomb_series/ /F/ /G/ /l/ /eta/ /z/ /len/ /prec/ +--+-- Computes the Coulomb wave functions evaluated at the power series /z/,+-- truncated to length /len/. Either of the outputs can be /NULL/.+foreign import ccall "arb_hypgeom.h arb_hypgeom_coulomb_series"+ arb_hypgeom_coulomb_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArb -> Ptr CArb -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- Orthogonal polynomials and functions ----------------------------------------++-- | /arb_hypgeom_chebyshev_t/ /res/ /nu/ /z/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_chebyshev_t"+ arb_hypgeom_chebyshev_t :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()+-- | /arb_hypgeom_chebyshev_u/ /res/ /nu/ /z/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_chebyshev_u"+ arb_hypgeom_chebyshev_u :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()+-- | /arb_hypgeom_jacobi_p/ /res/ /n/ /a/ /b/ /z/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_jacobi_p"+ arb_hypgeom_jacobi_p :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()+-- | /arb_hypgeom_gegenbauer_c/ /res/ /n/ /m/ /z/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_gegenbauer_c"+ arb_hypgeom_gegenbauer_c :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()+-- | /arb_hypgeom_laguerre_l/ /res/ /n/ /m/ /z/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_laguerre_l"+ arb_hypgeom_laguerre_l :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()+-- | /arb_hypgeom_hermite_h/ /res/ /nu/ /z/ /prec/ +--+-- Computes Chebyshev, Jacobi, Gegenbauer, Laguerre or Hermite polynomials,+-- or their extensions to non-integer orders.+foreign import ccall "arb_hypgeom.h arb_hypgeom_hermite_h"+ arb_hypgeom_hermite_h :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_legendre_p/ /res/ /n/ /m/ /z/ /type/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_legendre_p"+ arb_hypgeom_legendre_p :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()+-- | /arb_hypgeom_legendre_q/ /res/ /n/ /m/ /z/ /type/ /prec/ +--+-- Computes Legendre functions of the first and second kind. See+-- @acb_hypgeom_legendre_p@ and @acb_hypgeom_legendre_q@ for definitions.+foreign import ccall "arb_hypgeom.h arb_hypgeom_legendre_q"+ arb_hypgeom_legendre_q :: Ptr CArb -> Ptr CArb -> Ptr CArb -> Ptr CArb -> CInt -> CLong -> IO ()++-- | /arb_hypgeom_legendre_p_ui_deriv_bound/ /dp/ /dp2/ /n/ /x/ /x2sub1/ +--+-- Sets /dp/ to an upper bound for \(P'_n(x)\) and /dp2/ to an upper bound+-- for \(P''_n(x)\) given /x/ assumed to represent a real number with+-- \(|x| \le 1\). The variable /x2sub1/ must contain the precomputed value+-- \(1-x^2\) (or \(x^2-1\)). This method is used internally to bound the+-- propagated error for Legendre polynomials.+foreign import ccall "arb_hypgeom.h arb_hypgeom_legendre_p_ui_deriv_bound"+ arb_hypgeom_legendre_p_ui_deriv_bound :: Ptr CMag -> Ptr CMag -> CULong -> Ptr CArb -> Ptr CArb -> IO ()++-- | /arb_hypgeom_legendre_p_ui_zero/ /res/ /res_prime/ /n/ /x/ /K/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_legendre_p_ui_zero"+ arb_hypgeom_legendre_p_ui_zero :: Ptr CArb -> Ptr CArb -> CULong -> Ptr CArb -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_legendre_p_ui_one/ /res/ /res_prime/ /n/ /x/ /K/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_legendre_p_ui_one"+ arb_hypgeom_legendre_p_ui_one :: Ptr CArb -> Ptr CArb -> CULong -> Ptr CArb -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_legendre_p_ui_asymp/ /res/ /res_prime/ /n/ /x/ /K/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_legendre_p_ui_asymp"+ arb_hypgeom_legendre_p_ui_asymp :: Ptr CArb -> Ptr CArb -> CULong -> Ptr CArb -> CLong -> CLong -> IO ()+-- -- | /arb_hypgeom_legendre_p_rec/ /res/ /res_prime/ /n/ /x/ /prec/ +-- foreign import ccall "arb_hypgeom.h arb_hypgeom_legendre_p_rec"+-- arb_hypgeom_legendre_p_rec :: Ptr CArb -> Ptr CArb -> CULong -> Ptr CArb -> CLong -> IO ()+-- | /arb_hypgeom_legendre_p_ui/ /res/ /res_prime/ /n/ /x/ /prec/ +--+-- Evaluates the ordinary Legendre polynomial \(P_n(x)\). If /res_prime/ is+-- non-NULL, simultaneously evaluates the derivative \(P'_n(x)\).+-- +-- The overall algorithm is described in < [JM2018]>.+-- +-- The versions /zero/, /one/ respectively use the hypergeometric series+-- expansions at \(x = 0\) and \(x = 1\) while the /asymp/ version uses an+-- asymptotic series on \((-1,1)\) intended for large /n/. The parameter+-- /K/ specifies the exact number of expansion terms to use (if the series+-- expansion truncated at this point does not give the exact polynomial, an+-- error bound is computed automatically). The asymptotic expansion with+-- error bounds is given in < [Bog2012]>. The /rec/ version uses the+-- forward recurrence implemented using fixed-point arithmetic; it is only+-- intended for the interval \((-1,1)\), moderate /n/ and modest precision.+-- +-- The default version attempts to choose the best algorithm automatically.+-- It also estimates the amount of cancellation in the hypergeometric+-- series and increases the working precision to compensate, bounding the+-- propagated error using derivative bounds.+foreign import ccall "arb_hypgeom.h arb_hypgeom_legendre_p_ui"+ arb_hypgeom_legendre_p_ui :: Ptr CArb -> Ptr CArb -> CULong -> Ptr CArb -> CLong -> IO ()++-- | /arb_hypgeom_legendre_p_ui_root/ /res/ /weight/ /n/ /k/ /prec/ +--+-- Sets /res/ to the /k/-th root of the Legendre polynomial \(P_n(x)\). We+-- index the roots in decreasing order+-- +-- \[`\]+-- \[1 > x_0 > x_1 > \ldots > x_{n-1} > -1\]+-- +-- (which corresponds to ordering the roots of \(P_n(\cos(\theta))\) in+-- order of increasing \(\theta\)). If /weight/ is non-NULL, it is set to+-- the weight corresponding to the node \(x_k\) for Gaussian quadrature on+-- \([-1,1]\). Note that only \(\lceil n / 2 \rceil\) roots need to be+-- computed, since the remaining roots are given by \(x_k = -x_{n-1-k}\).+-- +-- We compute an enclosing interval using an asymptotic approximation+-- followed by some number of Newton iterations, using the error bounds+-- given in < [Pet1999]>. If very high precision is requested, the root is+-- subsequently refined using interval Newton steps with doubling working+-- precision.+foreign import ccall "arb_hypgeom.h arb_hypgeom_legendre_p_ui_root"+ arb_hypgeom_legendre_p_ui_root :: Ptr CArb -> Ptr CArb -> CULong -> CULong -> CLong -> IO ()++-- Dilogarithm -----------------------------------------------------------------++-- | /arb_hypgeom_dilog/ /res/ /z/ /prec/ +--+-- Computes the dilogarithm \(\operatorname{Li}_2(z)\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_dilog"+ arb_hypgeom_dilog :: Ptr CArb -> Ptr CArb -> CLong -> IO ()++-- Hypergeometric sums ---------------------------------------------------------++-- | /arb_hypgeom_sum_fmpq_arb_forward/ /res/ /a/ /alen/ /b/ /blen/ /z/ /reciprocal/ /N/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_sum_fmpq_arb_forward"+ arb_hypgeom_sum_fmpq_arb_forward :: Ptr CArb -> Ptr CFmpq -> CLong -> Ptr CFmpq -> CLong -> Ptr CArb -> CInt -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_sum_fmpq_arb_rs/ /res/ /a/ /alen/ /b/ /blen/ /z/ /reciprocal/ /N/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_sum_fmpq_arb_rs"+ arb_hypgeom_sum_fmpq_arb_rs :: Ptr CArb -> Ptr CFmpq -> CLong -> Ptr CFmpq -> CLong -> Ptr CArb -> CInt -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_sum_fmpq_arb/ /res/ /a/ /alen/ /b/ /blen/ /z/ /reciprocal/ /N/ /prec/ +--+-- Sets /res/ to the finite hypergeometric sum+-- \(\sum_{n=0}^{N-1} (\textbf{a})_n z^n / (\textbf{b})_n\) where+-- \(\textbf{x}_n = (x_1)_n (x_2)_n \cdots\), given vectors of rational+-- parameters /a/ (of length /alen/) and /b/ (of length /blen/). If+-- /reciprocal/ is set, replace \(z\) by \(1 / z\). The /forward/ version+-- uses the forward recurrence, optimized by delaying divisions, the /rs/+-- version uses rectangular splitting, and the default version uses an+-- automatic algorithm choice.+foreign import ccall "arb_hypgeom.h arb_hypgeom_sum_fmpq_arb"+ arb_hypgeom_sum_fmpq_arb :: Ptr CArb -> Ptr CFmpq -> CLong -> Ptr CFmpq -> CLong -> Ptr CArb -> CInt -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_sum_fmpq_imag_arb_forward/ /res1/ /res2/ /a/ /alen/ /b/ /blen/ /z/ /reciprocal/ /N/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_sum_fmpq_imag_arb_forward"+ arb_hypgeom_sum_fmpq_imag_arb_forward :: Ptr CArb -> Ptr CArb -> Ptr CFmpq -> CLong -> Ptr CFmpq -> CLong -> Ptr CArb -> CInt -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_sum_fmpq_imag_arb_rs/ /res1/ /res2/ /a/ /alen/ /b/ /blen/ /z/ /reciprocal/ /N/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_sum_fmpq_imag_arb_rs"+ arb_hypgeom_sum_fmpq_imag_arb_rs :: Ptr CArb -> Ptr CArb -> Ptr CFmpq -> CLong -> Ptr CFmpq -> CLong -> Ptr CArb -> CInt -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_sum_fmpq_imag_arb_bs/ /res1/ /res2/ /a/ /alen/ /b/ /blen/ /z/ /reciprocal/ /N/ /prec/ +foreign import ccall "arb_hypgeom.h arb_hypgeom_sum_fmpq_imag_arb_bs"+ arb_hypgeom_sum_fmpq_imag_arb_bs :: Ptr CArb -> Ptr CArb -> Ptr CFmpq -> CLong -> Ptr CFmpq -> CLong -> Ptr CArb -> CInt -> CLong -> CLong -> IO ()+-- | /arb_hypgeom_sum_fmpq_imag_arb/ /res1/ /res2/ /a/ /alen/ /b/ /blen/ /z/ /reciprocal/ /N/ /prec/ +--+-- Sets /res1/ and /res2/ to the real and imaginary part of the finite+-- hypergeometric sum+-- \(\sum_{n=0}^{N-1} (\textbf{a})_n (i z)^n / (\textbf{b})_n\). If+-- /reciprocal/ is set, replace \(z\) by \(1 / z\).+foreign import ccall "arb_hypgeom.h arb_hypgeom_sum_fmpq_imag_arb"+ arb_hypgeom_sum_fmpq_imag_arb :: Ptr CArb -> Ptr CArb -> Ptr CFmpq -> CLong -> Ptr CFmpq -> CLong -> Ptr CArb -> CInt -> CLong -> CLong -> IO ()+
+ src/Data/Number/Flint/Arb/Instances.hs view
@@ -0,0 +1,18 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Arb.Instances where++import Test.QuickCheck++import System.IO.Unsafe+import Foreign.C.String+import Foreign.Marshal.Alloc ( free )++import Data.Number.Flint.Arb++instance Show Arb where+ show x = unsafePerformIO $ do+ (_, cs) <- withArb x $ \x -> arb_get_str x 16 arb_str_no_radius+ s <- peekCString cs+ free cs+ return s+
+ src/Data/Number/Flint/Arb/Mag.hs view
@@ -0,0 +1,41 @@+{-|+module : Data.Number.Flint.Arb.Mag+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+++The @mag_t@ type holds an unsigned floating-point number with a+fixed-precision mantissa (30 bits) and an arbitrary-precision exponent+(represented as an @fmpz_t@), suited for representing magnitude bounds.+The special values zero and positive infinity are supported, but not+NaN.++Operations that involve rounding will always produce a valid upper+bound, or a lower bound if the function name has the suffix /lower/. For+performance reasons, no attempt is made to compute the best possible+bounds: in general, a bound may be several ulps larger\/smaller than the+optimal bound. Some functions such as @mag_set@ and @mag_mul_2exp_si@+are always exact and therefore do not require separate /lower/ versions.+--+A common mistake is to forget computing a lower bound for the argument+of a decreasing function that is meant to be bounded from above, or vice+versa. For example, to compute an upper bound for \((x+1)/(y+1)\), the+parameter /x/ should initially be an upper bound while /y/ should be a+lower bound, and one should do:++For a lower bound of the same expression, /x/ should be a lower bound+while /y/ should be an upper bound, and one should do:++Applications requiring floating-point arithmetic with more flexibility+(such as correct rounding, or higher precision) should use the @arf_t@+type instead. For calculations where a complex alternation between upper+and lower bounds is necessary, it may be cleaner to use @arb_t@+arithmetic and convert to a @mag_t@ bound only in the end.+-}++module Data.Number.Flint.Arb.Mag (+ module Data.Number.Flint.Arb.Mag.FFI+ ) where++import Data.Number.Flint.Arb.Mag.FFI
+ src/Data/Number/Flint/Arb/Mag/FFI.hsc view
@@ -0,0 +1,859 @@+{-|+module : Data.Number.Flint.Arb.Mag.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Arb.Mag.FFI (+ -- * Fixed-precision unsigned floating-point numbers for bounds+ -- * Types+ Mag (..)+ , CMag (..)+ , newMag+ , withMag+ , withNewMag+ -- * Memory management+ , mag_init+ , mag_clear+ , mag_swap+ , _mag_vec_init+ , _mag_vec_clear+ , mag_allocated_bytes+ -- * Special values+ , mag_zero+ , mag_one+ , mag_inf+ , mag_is_special+ , mag_is_zero+ , mag_is_inf+ , mag_is_finite+ , mag_d_log_lower_bound+ , mag_d_log_upper_bound+ -- * Assignment and conversions+ , mag_init_set+ , mag_set+ , mag_set_d+ , mag_set_ui+ , mag_set_fmpz+ , mag_set_d_lower+ , mag_set_ui_lower+ , mag_set_fmpz_lower+ , mag_set_d_2exp_fmpz+ , mag_set_fmpz_2exp_fmpz+ , mag_set_ui_2exp_si+ , mag_set_d_2exp_fmpz_lower+ , mag_set_fmpz_2exp_fmpz_lower+ , mag_get_d+ , mag_get_d_log2_approx+ , mag_get_fmpq+ , mag_get_fmpz+ , mag_get_fmpz_lower+ -- * Comparisons+ , mag_equal+ , mag_cmp+ , mag_cmp_2exp_si+ , mag_min+ , mag_max+ -- * Input and output+ , mag_print+ , mag_fprint+ , mag_dump_str+ , mag_load_str+ , mag_dump_file+ , mag_load_file+ -- * Random generation+ , mag_randtest+ , mag_randtest_special+ -- * Arithmetic+ , mag_add+ , mag_add_ui+ , mag_add_lower+ , mag_add_ui_lower+ , mag_add_2exp_fmpz+ , mag_add_ui_2exp_si+ , mag_sub+ , mag_sub_lower+ , mag_mul_2exp_si+ , mag_mul_2exp_fmpz+ , mag_mul+ , mag_mul_ui+ , mag_mul_fmpz+ , mag_mul_lower+ , mag_mul_ui_lower+ , mag_mul_fmpz_lower+ , mag_addmul+ , mag_div+ , mag_div_ui+ , mag_div_fmpz+ , mag_div_lower+ , mag_inv+ , mag_inv_lower+ -- * Fast, unsafe arithmetic+ , mag_fast_init_set+ , mag_fast_zero+ , mag_fast_is_zero+ , mag_fast_mul+ , mag_fast_addmul+ , mag_fast_add_2exp_si+ , mag_fast_mul_2exp_si+ -- * Powers and logarithms+ , mag_pow_ui+ , mag_pow_fmpz+ , mag_pow_ui_lower+ , mag_pow_fmpz_lower+ , mag_sqrt+ , mag_sqrt_lower+ , mag_rsqrt+ , mag_rsqrt_lower+ , mag_hypot+ , mag_root+ , mag_log+ , mag_log_lower+ , mag_neg_log+ , mag_neg_log_lower+ , mag_log_ui+ , mag_log1p+ , mag_exp+ , mag_exp_lower+ , mag_expinv+ , mag_expinv_lower+ , mag_expm1+ , mag_exp_tail+ , mag_binpow_uiui+ , mag_geom_series+ -- * Special functions+ , mag_const_pi+ , mag_const_pi_lower+ , mag_atan+ , mag_atan_lower+ , mag_cosh+ , mag_cosh_lower+ , mag_sinh+ , mag_sinh_lower+ , mag_fac_ui+ , mag_rfac_ui+ , mag_bin_uiui+ , mag_bernoulli_div_fac_ui+ , mag_polylog_tail+ , mag_hurwitz_zeta_uiui+) where++-- Fixed-precision unsigned floating-point numbers for bounds ------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Alloc (free)++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Arb.Types++#include <flint/mag.h>++-- Types -----------------------------------------------------------------------++newMag = do+ x <- mallocForeignPtr+ withForeignPtr x mag_init+ addForeignPtrFinalizer p_mag_clear x+ return $ Mag x++withMag (Mag p) f = do+ withForeignPtr p $ \fp -> (Mag p,) <$> f fp++withNewMag f = do+ x <- newMag+ withMag x f+ +-- Memory management -----------------------------------------------------------++-- | /mag_init/ /x/ +-- +-- Initializes the variable /x/ for use. Its value is set to zero.+foreign import ccall "mag.h mag_init"+ mag_init :: Ptr CMag -> IO ()++-- | /mag_clear/ /x/ +-- +-- Clears the variable /x/, freeing or recycling its allocated memory.+foreign import ccall "mag.h mag_clear"+ mag_clear :: Ptr CMag -> IO ()++foreign import ccall "mag.h &mag_clear"+ p_mag_clear :: FunPtr (Ptr CMag -> IO ())++-- | /mag_swap/ /x/ /y/ +-- +-- Swaps /x/ and /y/ efficiently.+foreign import ccall "mag.h mag_swap"+ mag_swap :: Ptr CMag -> Ptr CMag -> IO ()++-- | /_mag_vec_init/ /n/ +-- +-- Allocates a vector of length /n/. All entries are set to zero.+foreign import ccall "mag.h _mag_vec_init"+ _mag_vec_init :: CLong -> IO (Ptr CMag)++-- | /_mag_vec_clear/ /v/ /n/ +-- +-- Clears a vector of length /n/.+foreign import ccall "mag.h _mag_vec_clear"+ _mag_vec_clear :: (Ptr CMag) -> CLong -> IO ()++-- | /mag_allocated_bytes/ /x/ +-- +-- Returns the total number of bytes heap-allocated internally by this+-- object. The count excludes the size of the structure itself. Add+-- @sizeof(mag_struct)@ to get the size of the object as a whole.+foreign import ccall "mag.h mag_allocated_bytes"+ mag_allocated_bytes :: Ptr CMag -> IO CLong++-- Special values --------------------------------------------------------------++-- | /mag_zero/ /res/ +-- +-- Sets /res/ to zero.+foreign import ccall "mag.h mag_zero"+ mag_zero :: Ptr CMag -> IO ()++-- | /mag_one/ /res/ +-- +-- Sets /res/ to one.+foreign import ccall "mag.h mag_one"+ mag_one :: Ptr CMag -> IO ()++-- | /mag_inf/ /res/ +-- +-- Sets /res/ to positive infinity.+foreign import ccall "mag.h mag_inf"+ mag_inf :: Ptr CMag -> IO ()++-- | /mag_is_special/ /x/ +-- +-- Returns nonzero iff /x/ is zero or positive infinity.+foreign import ccall "mag.h mag_is_special"+ mag_is_special :: Ptr CMag -> IO CInt++-- | /mag_is_zero/ /x/ +-- +-- Returns nonzero iff /x/ is zero.+foreign import ccall "mag.h mag_is_zero"+ mag_is_zero :: Ptr CMag -> IO CInt++-- | /mag_is_inf/ /x/ +-- +-- Returns nonzero iff /x/ is positive infinity.+foreign import ccall "mag.h mag_is_inf"+ mag_is_inf :: Ptr CMag -> IO CInt++-- | /mag_is_finite/ /x/ +-- +-- Returns nonzero iff /x/ is not positive infinity (since there is no NaN+-- value, this function is exactly the logical negation of @mag_is_inf@).+foreign import ccall "mag.h mag_is_finite"+ mag_is_finite :: Ptr CMag -> IO CInt++foreign import ccall "mag.h mag_d_log_lower_bound"+ mag_d_log_lower_bound :: CDouble -> CDouble++foreign import ccall "mag.h mag_d_log_upper_bound"+ mag_d_log_upper_bound :: CDouble -> CDouble++-- Assignment and conversions --------------------------------------------------++-- | /mag_init_set/ /res/ /x/ +-- +-- Initializes /res/ and sets it to the value of /x/. This operation is+-- always exact.+foreign import ccall "mag.h mag_init_set"+ mag_init_set :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_set/ /res/ /x/ +-- +-- Sets /res/ to the value of /x/. This operation is always exact.+foreign import ccall "mag.h mag_set"+ mag_set :: Ptr CMag -> Ptr CMag -> IO ()++foreign import ccall "mag.h mag_set_d"+ mag_set_d :: Ptr CMag -> CDouble -> IO ()++foreign import ccall "mag.h mag_set_ui"+ mag_set_ui :: Ptr CMag -> CULong -> IO ()++-- | /mag_set_fmpz/ /res/ /x/ +-- +-- Sets /res/ to an upper bound for \(|x|\). The operation may be inexact+-- even if /x/ is exactly representable.+foreign import ccall "mag.h mag_set_fmpz"+ mag_set_fmpz :: Ptr CMag -> Ptr CFmpz -> IO ()++foreign import ccall "mag.h mag_set_d_lower"+ mag_set_d_lower :: Ptr CMag -> CDouble -> IO ()++foreign import ccall "mag.h mag_set_ui_lower"+ mag_set_ui_lower :: Ptr CMag -> CULong -> IO ()++-- | /mag_set_fmpz_lower/ /res/ /x/ +-- +-- Sets /res/ to a lower bound for \(|x|\). The operation may be inexact+-- even if /x/ is exactly representable.+foreign import ccall "mag.h mag_set_fmpz_lower"+ mag_set_fmpz_lower :: Ptr CMag -> Ptr CFmpz -> IO ()++foreign import ccall "mag.h mag_set_d_2exp_fmpz"+ mag_set_d_2exp_fmpz :: Ptr CMag -> CDouble -> Ptr CFmpz -> IO ()++foreign import ccall "mag.h mag_set_fmpz_2exp_fmpz"+ mag_set_fmpz_2exp_fmpz :: Ptr CMag -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /mag_set_ui_2exp_si/ /res/ /x/ /y/ +-- +-- Sets /res/ to an upper bound for \(|x| \cdot 2^y\).+foreign import ccall "mag.h mag_set_ui_2exp_si"+ mag_set_ui_2exp_si :: Ptr CMag -> CULong -> CLong -> IO ()++foreign import ccall "mag.h mag_set_d_2exp_fmpz_lower"+ mag_set_d_2exp_fmpz_lower :: Ptr CMag -> CDouble -> Ptr CFmpz -> IO ()++-- | /mag_set_fmpz_2exp_fmpz_lower/ /res/ /x/ /y/ +-- +-- Sets /res/ to a lower bound for \(|x| \cdot 2^y\).+foreign import ccall "mag.h mag_set_fmpz_2exp_fmpz_lower"+ mag_set_fmpz_2exp_fmpz_lower :: Ptr CMag -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /mag_get_d/ /x/ +-- +-- Returns a /double/ giving an upper bound for /x/.+foreign import ccall "mag.h mag_get_d"+ mag_get_d :: Ptr CMag -> IO CDouble++-- | /mag_get_d_log2_approx/ /x/ +-- +-- Returns a /double/ approximating \(\log_2(x)\), suitable for estimating+-- magnitudes (warning: not a rigorous bound). The value is clamped between+-- /COEFF_MIN/ and /COEFF_MAX/.+foreign import ccall "mag.h mag_get_d_log2_approx"+ mag_get_d_log2_approx :: Ptr CMag -> IO CDouble++foreign import ccall "mag.h mag_get_fmpq"+ mag_get_fmpq :: Ptr CFmpq -> Ptr CMag -> IO ()++foreign import ccall "mag.h mag_get_fmpz"+ mag_get_fmpz :: Ptr CFmpz -> Ptr CMag -> IO ()++-- | /mag_get_fmpz_lower/ /res/ /x/ +-- +-- Sets /res/, respectively, to the exact rational number represented by+-- /x/, the integer exactly representing the ceiling function of /x/, or+-- the integer exactly representing the floor function of /x/.+-- +-- These functions are unsafe: the user must check in advance that /x/ is+-- of reasonable magnitude. If /x/ is infinite or has a bignum exponent, an+-- abort will be raised. If the exponent otherwise is too large or too+-- small, the available memory could be exhausted resulting in undefined+-- behavior.+foreign import ccall "mag.h mag_get_fmpz_lower"+ mag_get_fmpz_lower :: Ptr CFmpz -> Ptr CMag -> IO ()++-- Comparisons -----------------------------------------------------------------++-- | /mag_equal/ /x/ /y/ +-- +-- Returns nonzero iff /x/ and /y/ have the same value.+foreign import ccall "mag.h mag_equal"+ mag_equal :: Ptr CMag -> Ptr CMag -> IO CInt++-- | /mag_cmp/ /x/ /y/ +-- +-- Returns negative, zero, or positive, depending on whether /x/ is+-- smaller, equal, or larger than /y/.+foreign import ccall "mag.h mag_cmp"+ mag_cmp :: Ptr CMag -> Ptr CMag -> IO CInt++-- | /mag_cmp_2exp_si/ /x/ /y/ +-- +-- Returns negative, zero, or positive, depending on whether /x/ is+-- smaller, equal, or larger than \(2^y\).+foreign import ccall "mag.h mag_cmp_2exp_si"+ mag_cmp_2exp_si :: Ptr CMag -> CLong -> IO CInt++foreign import ccall "mag.h mag_min"+ mag_min :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_max/ /res/ /x/ /y/ +-- +-- Sets /res/ respectively to the smaller or the larger of /x/ and /y/.+foreign import ccall "mag.h mag_max"+ mag_max :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++-- Input and output ------------------------------------------------------------++-- | /mag_print/ /x/ +-- +-- Prints /x/ to standard output.+mag_print x = do+ cs <- mag_get_str x+ s <- peekCString cs+ free cs+ putStr s+ +-- | /mag_fprint/ /file/ /x/ +-- +-- Prints /x/ to the stream /file/.+foreign import ccall "mag.h mag_fprint"+ mag_fprint :: Ptr CFile -> Ptr CMag -> IO ()++-- | /mag_get_str/ /x/+-- Returns a string representation of /x/. The memory needs to be deallocated+-- with /flint_free/+foreign import ccall "mag.h mag_get_str"+ mag_get_str :: Ptr CMag -> IO CString+ +-- | /mag_dump_str/ /x/ +-- +-- Allocates a string and writes a binary representation of /x/ to it that+-- can be read by @mag_load_str@. The returned string needs to be+-- deallocated with /flint_free/.+foreign import ccall "mag.h mag_dump_str"+ mag_dump_str :: Ptr CMag -> IO CString++-- | /mag_load_str/ /x/ /str/ +-- +-- Parses /str/ into /x/. Returns a nonzero value if /str/ is not formatted+-- correctly.+foreign import ccall "mag.h mag_load_str"+ mag_load_str :: Ptr CMag -> CString -> IO CInt++-- | /mag_dump_file/ /stream/ /x/ +-- +-- Writes a binary representation of /x/ to /stream/ that can be read by+-- @mag_load_file@. Returns a nonzero value if the data could not be+-- written.+foreign import ccall "mag.h mag_dump_file"+ mag_dump_file :: Ptr CFile -> Ptr CMag -> IO CInt++-- | /mag_load_file/ /x/ /stream/ +-- +-- Reads /x/ from /stream/. Returns a nonzero value if the data is not+-- formatted correctly or the read failed. Note that the data is assumed to+-- be delimited by a whitespace or end-of-file, i.e., when writing multiple+-- values with @mag_dump_file@ make sure to insert a whitespace to separate+-- consecutive values.+foreign import ccall "mag.h mag_load_file"+ mag_load_file :: Ptr CMag -> Ptr CFile -> IO CInt++-- Random generation -----------------------------------------------------------++-- | /mag_randtest/ /res/ /state/ /expbits/ +-- +-- Sets /res/ to a random finite value, with an exponent up to /expbits/+-- bits large.+foreign import ccall "mag.h mag_randtest"+ mag_randtest :: Ptr CMag -> Ptr CFRandState -> CLong -> IO ()++-- | /mag_randtest_special/ /res/ /state/ /expbits/ +-- +-- Like @mag_randtest@, but also sometimes sets /res/ to infinity.+foreign import ccall "mag.h mag_randtest_special"+ mag_randtest_special :: Ptr CMag -> Ptr CFRandState -> CLong -> IO ()++-- Arithmetic ------------------------------------------------------------------++foreign import ccall "mag.h mag_add"+ mag_add :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_add_ui/ /res/ /x/ /y/ +-- +-- Sets /res/ to an upper bound for \(x + y\).+foreign import ccall "mag.h mag_add_ui"+ mag_add_ui :: Ptr CMag -> Ptr CMag -> CULong -> IO ()++foreign import ccall "mag.h mag_add_lower"+ mag_add_lower :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_add_ui_lower/ /res/ /x/ /y/ +-- +-- Sets /res/ to a lower bound for \(x + y\).+foreign import ccall "mag.h mag_add_ui_lower"+ mag_add_ui_lower :: Ptr CMag -> Ptr CMag -> CULong -> IO ()++-- | /mag_add_2exp_fmpz/ /res/ /x/ /e/ +-- +-- Sets /res/ to an upper bound for \(x + 2^e\).+foreign import ccall "mag.h mag_add_2exp_fmpz"+ mag_add_2exp_fmpz :: Ptr CMag -> Ptr CMag -> Ptr CFmpz -> IO ()++-- | /mag_add_ui_2exp_si/ /res/ /x/ /y/ /e/ +-- +-- Sets /res/ to an upper bound for \(x + y 2^e\).+foreign import ccall "mag.h mag_add_ui_2exp_si"+ mag_add_ui_2exp_si :: Ptr CMag -> Ptr CMag -> CULong -> CLong -> IO ()++-- | /mag_sub/ /res/ /x/ /y/ +-- +-- Sets /res/ to an upper bound for \(\max(x-y, 0)\).+foreign import ccall "mag.h mag_sub"+ mag_sub :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_sub_lower/ /res/ /x/ /y/ +-- +-- Sets /res/ to a lower bound for \(\max(x-y, 0)\).+foreign import ccall "mag.h mag_sub_lower"+ mag_sub_lower :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++foreign import ccall "mag.h mag_mul_2exp_si"+ mag_mul_2exp_si :: Ptr CMag -> Ptr CMag -> CLong -> IO ()++-- | /mag_mul_2exp_fmpz/ /res/ /x/ /y/ +-- +-- Sets /res/ to \(x \cdot 2^y\). This operation is exact.+foreign import ccall "mag.h mag_mul_2exp_fmpz"+ mag_mul_2exp_fmpz :: Ptr CMag -> Ptr CMag -> Ptr CFmpz -> IO ()++foreign import ccall "mag.h mag_mul"+ mag_mul :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++foreign import ccall "mag.h mag_mul_ui"+ mag_mul_ui :: Ptr CMag -> Ptr CMag -> CULong -> IO ()++-- | /mag_mul_fmpz/ /res/ /x/ /y/ +-- +-- Sets /res/ to an upper bound for \(xy\).+foreign import ccall "mag.h mag_mul_fmpz"+ mag_mul_fmpz :: Ptr CMag -> Ptr CMag -> Ptr CFmpz -> IO ()++foreign import ccall "mag.h mag_mul_lower"+ mag_mul_lower :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++foreign import ccall "mag.h mag_mul_ui_lower"+ mag_mul_ui_lower :: Ptr CMag -> Ptr CMag -> CULong -> IO ()++-- | /mag_mul_fmpz_lower/ /res/ /x/ /y/ +-- +-- Sets /res/ to a lower bound for \(xy\).+foreign import ccall "mag.h mag_mul_fmpz_lower"+ mag_mul_fmpz_lower :: Ptr CMag -> Ptr CMag -> Ptr CFmpz -> IO ()++-- | /mag_addmul/ /z/ /x/ /y/ +-- +-- Sets /z/ to an upper bound for \(z + xy\).+foreign import ccall "mag.h mag_addmul"+ mag_addmul :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++foreign import ccall "mag.h mag_div"+ mag_div :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++foreign import ccall "mag.h mag_div_ui"+ mag_div_ui :: Ptr CMag -> Ptr CMag -> CULong -> IO ()++-- | /mag_div_fmpz/ /res/ /x/ /y/ +-- +-- Sets /res/ to an upper bound for \(x / y\).+foreign import ccall "mag.h mag_div_fmpz"+ mag_div_fmpz :: Ptr CMag -> Ptr CMag -> Ptr CFmpz -> IO ()++-- | /mag_div_lower/ /res/ /x/ /y/ +-- +-- Sets /res/ to a lower bound for \(x / y\).+foreign import ccall "mag.h mag_div_lower"+ mag_div_lower :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_inv/ /res/ /x/ +-- +-- Sets /res/ to an upper bound for \(1 / x\).+foreign import ccall "mag.h mag_inv"+ mag_inv :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_inv_lower/ /res/ /x/ +-- +-- Sets /res/ to a lower bound for \(1 / x\).+foreign import ccall "mag.h mag_inv_lower"+ mag_inv_lower :: Ptr CMag -> Ptr CMag -> IO ()++-- Fast, unsafe arithmetic -----------------------------------------------------++-- The following methods assume that all inputs are finite and that all+-- exponents (in all inputs as well as the final result) fit as /fmpz/+-- inline values. They also assume that the output variables do not have+-- promoted exponents, as they will be overwritten directly (thus leaking+-- memory).+--+-- | /mag_fast_init_set/ /x/ /y/ +-- +-- Initialises /x/ and sets it to the value of /y/.+foreign import ccall "mag.h mag_fast_init_set"+ mag_fast_init_set :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_fast_zero/ /res/ +-- +-- Sets /res/ to zero.+foreign import ccall "mag.h mag_fast_zero"+ mag_fast_zero :: Ptr CMag -> IO ()++-- | /mag_fast_is_zero/ /x/ +-- +-- Returns nonzero iff /x/ to zero.+foreign import ccall "mag.h mag_fast_is_zero"+ mag_fast_is_zero :: Ptr CMag -> IO CInt++-- | /mag_fast_mul/ /res/ /x/ /y/ +-- +-- Sets /res/ to an upper bound for \(xy\).+foreign import ccall "mag.h mag_fast_mul"+ mag_fast_mul :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_fast_addmul/ /z/ /x/ /y/ +-- +-- Sets /z/ to an upper bound for \(z + xy\).+foreign import ccall "mag.h mag_fast_addmul"+ mag_fast_addmul :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_fast_add_2exp_si/ /res/ /x/ /e/ +-- +-- Sets /res/ to an upper bound for \(x + 2^e\).+foreign import ccall "mag.h mag_fast_add_2exp_si"+ mag_fast_add_2exp_si :: Ptr CMag -> Ptr CMag -> CLong -> IO ()++-- | /mag_fast_mul_2exp_si/ /res/ /x/ /e/ +-- +-- Sets /res/ to an upper bound for \(x 2^e\).+foreign import ccall "mag.h mag_fast_mul_2exp_si"+ mag_fast_mul_2exp_si :: Ptr CMag -> Ptr CMag -> CLong -> IO ()++-- Powers and logarithms -------------------------------------------------------++foreign import ccall "mag.h mag_pow_ui"+ mag_pow_ui :: Ptr CMag -> Ptr CMag -> CULong -> IO ()++-- | /mag_pow_fmpz/ /res/ /x/ /e/ +-- +-- Sets /res/ to an upper bound for \(x^e\).+foreign import ccall "mag.h mag_pow_fmpz"+ mag_pow_fmpz :: Ptr CMag -> Ptr CMag -> Ptr CFmpz -> IO ()++foreign import ccall "mag.h mag_pow_ui_lower"+ mag_pow_ui_lower :: Ptr CMag -> Ptr CMag -> CULong -> IO ()++-- | /mag_pow_fmpz_lower/ /res/ /x/ /e/ +-- +-- Sets /res/ to a lower bound for \(x^e\).+foreign import ccall "mag.h mag_pow_fmpz_lower"+ mag_pow_fmpz_lower :: Ptr CMag -> Ptr CMag -> Ptr CFmpz -> IO ()++-- | /mag_sqrt/ /res/ /x/ +-- +-- Sets /res/ to an upper bound for \(\sqrt{x}\).+foreign import ccall "mag.h mag_sqrt"+ mag_sqrt :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_sqrt_lower/ /res/ /x/ +-- +-- Sets /res/ to a lower bound for \(\sqrt{x}\).+foreign import ccall "mag.h mag_sqrt_lower"+ mag_sqrt_lower :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_rsqrt/ /res/ /x/ +-- +-- Sets /res/ to an upper bound for \(1/\sqrt{x}\).+foreign import ccall "mag.h mag_rsqrt"+ mag_rsqrt :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_rsqrt_lower/ /res/ /x/ +-- +-- Sets /res/ to an lower bound for \(1/\sqrt{x}\).+foreign import ccall "mag.h mag_rsqrt_lower"+ mag_rsqrt_lower :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_hypot/ /res/ /x/ /y/ +-- +-- Sets /res/ to an upper bound for \(\sqrt{x^2 + y^2}\).+foreign import ccall "mag.h mag_hypot"+ mag_hypot :: Ptr CMag -> Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_root/ /res/ /x/ /n/ +-- +-- Sets /res/ to an upper bound for \(x^{1/n}\).+foreign import ccall "mag.h mag_root"+ mag_root :: Ptr CMag -> Ptr CMag -> CULong -> IO ()++-- | /mag_log/ /res/ /x/ +-- +-- Sets /res/ to an upper bound for \(\log(\max(1,x))\).+foreign import ccall "mag.h mag_log"+ mag_log :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_log_lower/ /res/ /x/ +-- +-- Sets /res/ to a lower bound for \(\log(\max(1,x))\).+foreign import ccall "mag.h mag_log_lower"+ mag_log_lower :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_neg_log/ /res/ /x/ +-- +-- Sets /res/ to an upper bound for \(-\log(\min(1,x))\), i.e. an upper+-- bound for \(|\log(x)|\) for \(x \le 1\).+foreign import ccall "mag.h mag_neg_log"+ mag_neg_log :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_neg_log_lower/ /res/ /x/ +-- +-- Sets /res/ to a lower bound for \(-\log(\min(1,x))\), i.e. a lower bound+-- for \(|\log(x)|\) for \(x \le 1\).+foreign import ccall "mag.h mag_neg_log_lower"+ mag_neg_log_lower :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_log_ui/ /res/ /n/ +-- +-- Sets /res/ to an upper bound for \(\log(n)\).+foreign import ccall "mag.h mag_log_ui"+ mag_log_ui :: Ptr CMag -> CULong -> IO ()++-- | /mag_log1p/ /res/ /x/ +-- +-- Sets /res/ to an upper bound for \(\log(1+x)\). The bound is computed+-- accurately for small /x/.+foreign import ccall "mag.h mag_log1p"+ mag_log1p :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_exp/ /res/ /x/ +-- +-- Sets /res/ to an upper bound for \(\exp(x)\).+foreign import ccall "mag.h mag_exp"+ mag_exp :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_exp_lower/ /res/ /x/ +-- +-- Sets /res/ to a lower bound for \(\exp(x)\).+foreign import ccall "mag.h mag_exp_lower"+ mag_exp_lower :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_expinv/ /res/ /x/ +-- +-- Sets /res/ to an upper bound for \(\exp(-x)\).+foreign import ccall "mag.h mag_expinv"+ mag_expinv :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_expinv_lower/ /res/ /x/ +-- +-- Sets /res/ to a lower bound for \(\exp(-x)\).+foreign import ccall "mag.h mag_expinv_lower"+ mag_expinv_lower :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_expm1/ /res/ /x/ +-- +-- Sets /res/ to an upper bound for \(\exp(x) - 1\). The bound is computed+-- accurately for small /x/.+foreign import ccall "mag.h mag_expm1"+ mag_expm1 :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_exp_tail/ /res/ /x/ /N/ +-- +-- Sets /res/ to an upper bound for \(\sum_{k=N}^{\infty} x^k / k!\).+foreign import ccall "mag.h mag_exp_tail"+ mag_exp_tail :: Ptr CMag -> Ptr CMag -> CULong -> IO ()++-- | /mag_binpow_uiui/ /res/ /m/ /n/ +-- +-- Sets /res/ to an upper bound for \((1 + 1/m)^n\).+foreign import ccall "mag.h mag_binpow_uiui"+ mag_binpow_uiui :: Ptr CMag -> CULong -> CULong -> IO ()++-- | /mag_geom_series/ /res/ /x/ /N/ +-- +-- Sets /res/ to an upper bound for \(\sum_{k=N}^{\infty} x^k\).+foreign import ccall "mag.h mag_geom_series"+ mag_geom_series :: Ptr CMag -> Ptr CMag -> CULong -> IO ()++-- Special functions -----------------------------------------------------------++foreign import ccall "mag.h mag_const_pi"+ mag_const_pi :: Ptr CMag -> IO ()++-- | /mag_const_pi_lower/ /res/ +-- +-- Sets /res/ to an upper (respectively lower) bound for \(\pi\).+foreign import ccall "mag.h mag_const_pi_lower"+ mag_const_pi_lower :: Ptr CMag -> IO ()++foreign import ccall "mag.h mag_atan"+ mag_atan :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_atan_lower/ /res/ /x/ +-- +-- Sets /res/ to an upper (respectively lower) bound for+-- \(\operatorname{atan}(x)\).+foreign import ccall "mag.h mag_atan_lower"+ mag_atan_lower :: Ptr CMag -> Ptr CMag -> IO ()++foreign import ccall "mag.h mag_cosh"+ mag_cosh :: Ptr CMag -> Ptr CMag -> IO ()++foreign import ccall "mag.h mag_cosh_lower"+ mag_cosh_lower :: Ptr CMag -> Ptr CMag -> IO ()++foreign import ccall "mag.h mag_sinh"+ mag_sinh :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_sinh_lower/ /res/ /x/ +-- +-- Sets /res/ to an upper or lower bound for \(\cosh(x)\) or \(\sinh(x)\).+foreign import ccall "mag.h mag_sinh_lower"+ mag_sinh_lower :: Ptr CMag -> Ptr CMag -> IO ()++-- | /mag_fac_ui/ /res/ /n/ +-- +-- Sets /res/ to an upper bound for \(n!\).+foreign import ccall "mag.h mag_fac_ui"+ mag_fac_ui :: Ptr CMag -> CULong -> IO ()++-- | /mag_rfac_ui/ /res/ /n/ +-- +-- Sets /res/ to an upper bound for \(1/n!\).+foreign import ccall "mag.h mag_rfac_ui"+ mag_rfac_ui :: Ptr CMag -> CULong -> IO ()++-- | /mag_bin_uiui/ /res/ /n/ /k/ +-- +-- Sets /res/ to an upper bound for the binomial coefficient+-- \({n \choose k}\).+foreign import ccall "mag.h mag_bin_uiui"+ mag_bin_uiui :: Ptr CMag -> CULong -> CULong -> IO ()++-- | /mag_bernoulli_div_fac_ui/ /res/ /n/ +-- +-- Sets /res/ to an upper bound for \(|B_n| / n!\) where \(B_n\) denotes a+-- Bernoulli number.+foreign import ccall "mag.h mag_bernoulli_div_fac_ui"+ mag_bernoulli_div_fac_ui :: Ptr CMag -> CULong -> IO ()++-- | /mag_polylog_tail/ /res/ /z/ /s/ /d/ /N/ +-- +-- Sets /res/ to an upper bound for+-- +-- \[`\]+-- \[\sum_{k=N}^{\infty} \frac{z^k \log^d(k)}{k^s}.\]+-- +-- The bounding strategy is described in @algorithms_polylogarithms@. Note:+-- in applications where \(s\) in this formula may be real or complex, the+-- user can simply substitute any convenient integer \(s'\) such that+-- \(s' \le \operatorname{Re}(s)\).+foreign import ccall "mag.h mag_polylog_tail"+ mag_polylog_tail :: Ptr CMag -> Ptr CMag -> CLong -> CULong -> CULong -> IO ()++-- | /mag_hurwitz_zeta_uiui/ /res/ /s/ /a/ +-- +-- Sets /res/ to an upper bound for+-- \(\zeta(s,a) = \sum_{k=0}^{\infty} (k+a)^{-s}\). We use the formula+-- +-- \[`\]+-- \[\zeta(s,a) \le \frac{1}{a^s} + \frac{1}{(s-1) a^{s-1}}\]+-- +-- which is obtained by estimating the sum by an integral. If \(s \le 1\)+-- or \(a = 0\), the bound is infinite.+foreign import ccall "mag.h mag_hurwitz_zeta_uiui"+ mag_hurwitz_zeta_uiui :: Ptr CMag -> CULong -> CULong -> IO ()+
+ src/Data/Number/Flint/Arb/Mat.hs view
@@ -0,0 +1,13 @@+{- |+An @ArbMat@ represents a dense matrix over the real numbers,+implemented as an array of entries of type @arb_struct@. The dimension+(number of rows and columns) of a matrix is fixed at initialization, and+the user must ensure that inputs and outputs to an operation have+compatible dimensions. The number of rows or columns in a matrix can be+zero.+-}+module Data.Number.Flint.Arb.Mat (+ module Data.Number.Flint.Arb.Mat.FFI+ ) where++import Data.Number.Flint.Arb.Mat.FFI
+ src/Data/Number/Flint/Arb/Mat/FFI.hsc view
@@ -0,0 +1,1133 @@+{-|+module : Data.Number.Flint.Arb.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Arb.Mat.FFI (+ -- * Matrices over the real numbers+ -- * Types+ ArbMat (..)+ , CArbMat (..)+ -- * Constructors+ , newArbMat+ , newArbMatFromFmpzMat+ , newArbMatFromFmpzMatRound+ , newArbMatFromFmpqMat+ , withArbMat+ , withNewArbMat+ -- * Memory management+ , arb_mat_init+ , arb_mat_clear+ , arb_mat_allocated_bytes+ , arb_mat_window_init+ , arb_mat_window_clear+ -- * Conversions+ , arb_mat_set+ , arb_mat_entry+ , arb_mat_set_fmpz_mat+ , arb_mat_set_round_fmpz_mat+ , arb_mat_set_fmpq_mat+ -- * Random generation+ , arb_mat_randtest+ -- * Input and output+ , arb_mat_get_strd+ , arb_mat_get_strn + , arb_mat_printd+ , arb_mat_fprintd+ , arb_mat_fprintn+ -- * Comparisons+ , arb_mat_equal+ , arb_mat_overlaps+ , arb_mat_contains+ , arb_mat_contains_fmpz_mat+ , arb_mat_contains_fmpq_mat+ , arb_mat_eq+ , arb_mat_ne+ , arb_mat_is_empty+ , arb_mat_is_square+ , arb_mat_is_exact+ , arb_mat_is_zero+ , arb_mat_is_finite+ , arb_mat_is_triu+ , arb_mat_is_tril+ , arb_mat_is_diag+ -- * Special matrices+ , arb_mat_zero+ , arb_mat_one+ , arb_mat_ones+ , arb_mat_indeterminate+ , arb_mat_hilbert+ , arb_mat_pascal+ , arb_mat_stirling+ , arb_mat_dct+ -- * Transpose+ , arb_mat_transpose+ -- * Norms+ , arb_mat_bound_inf_norm+ , arb_mat_frobenius_norm+ , arb_mat_bound_frobenius_norm+ -- * Arithmetic+ , arb_mat_neg+ , arb_mat_add+ , arb_mat_sub+ , arb_mat_mul_classical+ , arb_mat_mul_threaded+ , arb_mat_mul_block+ , arb_mat_mul+ , arb_mat_mul_entrywise+ , arb_mat_sqr_classical+ , arb_mat_sqr+ , arb_mat_pow_ui+ , _arb_mat_addmul_rad_mag_fast+ , arb_mat_approx_mul+ -- * Scalar arithmetic+ , arb_mat_scalar_mul_2exp_si+ , arb_mat_scalar_addmul_si+ , arb_mat_scalar_addmul_fmpz+ , arb_mat_scalar_addmul_arb+ , arb_mat_scalar_mul_si+ , arb_mat_scalar_mul_fmpz+ , arb_mat_scalar_mul_arb+ , arb_mat_scalar_div_si+ , arb_mat_scalar_div_fmpz+ , arb_mat_scalar_div_arb+ -- * Gaussian elimination and solving+ , arb_mat_lu_classical+ , arb_mat_lu_recursive+ , arb_mat_lu+ , arb_mat_solve_tril_classical+ , arb_mat_solve_tril_recursive+ , arb_mat_solve_tril+ , arb_mat_solve_triu_classical+ , arb_mat_solve_triu_recursive+ , arb_mat_solve_triu+ , arb_mat_solve_lu_precomp+ , arb_mat_solve+ , arb_mat_solve_lu+ , arb_mat_solve_precond+ , arb_mat_solve_preapprox+ , arb_mat_inv+ , arb_mat_det_lu+ , arb_mat_det_precond+ , arb_mat_det+ , arb_mat_approx_solve_triu+ , arb_mat_approx_solve_tril+ , arb_mat_approx_lu+ , arb_mat_approx_solve_lu_precomp+ , arb_mat_approx_solve+ , arb_mat_approx_inv+ -- * Cholesky decomposition and solving+ , _arb_mat_cholesky_banachiewicz+ , arb_mat_cho+ , arb_mat_solve_cho_precomp+ , arb_mat_spd_solve+ , arb_mat_inv_cho_precomp+ , arb_mat_spd_inv+ , _arb_mat_ldl_inplace+ , _arb_mat_ldl_golub_and_van_loan+ , arb_mat_ldl+ , arb_mat_solve_ldl_precomp+ , arb_mat_inv_ldl_precomp+ -- * Characteristic polynomial and companion matrix+ , _arb_mat_charpoly+ , arb_mat_charpoly+ , _arb_mat_companion+ , arb_mat_companion+ -- * Special functions+ , arb_mat_exp_taylor_sum+ , arb_mat_exp+ , arb_mat_trace+ , _arb_mat_diag_prod+ , arb_mat_diag_prod+ -- * Sparsity structure+ --, arb_mat_entrywise_is_zero+ , arb_mat_entrywise_not_is_zero+ , arb_mat_count_is_zero+ , arb_mat_count_not_is_zero+ -- * Component and error operations+ , arb_mat_get_mid+ , arb_mat_add_error_mag+) where ++-- __arb_mat.h__ -- matrices over the real numbers -----------------------------++import System.IO.Unsafe++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mat++import Data.Number.Flint.Fmpq.Mat++import Data.Number.Flint.Arb.Types++#include <flint/arb_mat.h>++-- Types -----------------------------------------------------------------------++data ArbMat = ArbMat {-# UNPACK #-} !(ForeignPtr CArbMat) +data CArbMat = CArbMat (Ptr CArb) CLong CLong (Ptr (Ptr CArb)) ++instance Storable CArbMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size arb_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment arb_mat_t}+ peek = error "CArbMat.peek: Not defined."+ poke = error "CArbMat.poke: Not defined."+ +newArbMat rows cols = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> arb_mat_init x rows cols+ addForeignPtrFinalizer p_arb_mat_clear x+ return $ ArbMat x++newArbMatFromFmpzMat a = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpzMat a $ \a -> do+ CFmpzMat _ rows cols _ <- peek a+ arb_mat_init x rows cols+ arb_mat_set_fmpz_mat x a+ addForeignPtrFinalizer p_arb_mat_clear x+ return $ ArbMat x++newArbMatFromFmpzMatRound a prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpzMat a $ \a -> do+ CFmpzMat _ rows cols _ <- peek a+ arb_mat_init x rows cols+ arb_mat_set_round_fmpz_mat x a prec+ addForeignPtrFinalizer p_arb_mat_clear x+ return $ ArbMat x++newArbMatFromFmpqMat a prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpqMat a $ \a -> do+ CFmpqMat _ rows cols _ <- peek a+ arb_mat_init x rows cols+ arb_mat_set_fmpq_mat x a prec+ addForeignPtrFinalizer p_arb_mat_clear x+ return $ ArbMat x++{-# INLINE withArbMat #-}+withArbMat (ArbMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (ArbMat x,)++{-# INLINE withNewArbMat #-}+withNewArbMat rows cols f = do+ x <- newArbMat rows cols+ withArbMat x f++-- Memory management -----------------------------------------------------------++-- | /arb_mat_init/ /mat/ /r/ /c/ +-- +-- Initializes the matrix, setting it to the zero matrix with /r/ rows and+-- /c/ columns.+foreign import ccall "arb_mat.h arb_mat_init"+ arb_mat_init :: Ptr CArbMat -> CLong -> CLong -> IO ()++-- | /arb_mat_clear/ /mat/ +-- +-- Clears the matrix, deallocating all entries.+foreign import ccall "arb_mat.h arb_mat_clear"+ arb_mat_clear :: Ptr CArbMat -> IO ()++foreign import ccall "arb_mat.h &arb_mat_clear"+ p_arb_mat_clear :: FunPtr (Ptr CArbMat -> IO ())++-- | /arb_mat_allocated_bytes/ /x/ +-- +-- Returns the total number of bytes heap-allocated internally by this+-- object. The count excludes the size of the structure itself. Add+-- @sizeof(arb_mat_struct)@ to get the size of the object as a whole.+foreign import ccall "arb_mat.h arb_mat_allocated_bytes"+ arb_mat_allocated_bytes :: Ptr CArbMat -> IO CLong++-- | /arb_mat_window_init/ /window/ /mat/ /r1/ /c1/ /r2/ /c2/ +-- +-- Initializes /window/ to a window matrix into the submatrix of /mat/+-- starting at the corner at row /r1/ and column /c1/ (inclusive) and+-- ending at row /r2/ and column /c2/ (exclusive).+foreign import ccall "arb_mat.h arb_mat_window_init"+ arb_mat_window_init :: Ptr CArbMat -> Ptr CArbMat -> CLong -> CLong -> CLong -> CLong -> IO ()++-- | /arb_mat_window_clear/ /window/ +-- +-- Frees the window matrix.+foreign import ccall "arb_mat.h arb_mat_window_clear"+ arb_mat_window_clear :: Ptr CArbMat -> IO ()++-- Conversions -----------------------------------------------------------------++foreign import ccall "arb_mat.h arb_mat_set"+ arb_mat_set :: Ptr CArbMat -> Ptr CArbMat -> IO ()++foreign import ccall "arb_mat.h arb_mat_entry_"+ arb_mat_entry :: Ptr CArbMat -> CLong -> CLong -> IO (Ptr CArb)++foreign import ccall "arb_mat.h arb_mat_set_fmpz_mat"+ arb_mat_set_fmpz_mat :: Ptr CArbMat -> Ptr CFmpzMat -> IO ()++foreign import ccall "arb_mat.h arb_mat_set_round_fmpz_mat"+ arb_mat_set_round_fmpz_mat :: Ptr CArbMat -> Ptr CFmpzMat -> CLong -> IO ()++-- | /arb_mat_set_fmpq_mat/ /dest/ /src/ /prec/ +-- +-- Sets /dest/ to /src/. The operands must have identical dimensions.+foreign import ccall "arb_mat.h arb_mat_set_fmpq_mat"+ arb_mat_set_fmpq_mat :: Ptr CArbMat -> Ptr CFmpqMat -> CLong -> IO ()++-- Random generation -----------------------------------------------------------++-- | /arb_mat_randtest/ /mat/ /state/ /prec/ /mag_bits/ +-- +-- Sets /mat/ to a random matrix with up to /prec/ bits of precision and+-- with exponents of width up to /mag_bits/.+foreign import ccall "arb_mat.h arb_mat_randtest"+ arb_mat_randtest :: Ptr CArbMat -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- Input and output ------------------------------------------------------------++foreign import ccall "arb_mat.h arb_mat_get_strd"+ arb_mat_get_strd :: Ptr CArbMat -> CLong -> IO CString++foreign import ccall "arb_mat.h arb_mat_get_strn"+ arb_mat_get_strn :: Ptr CArbMat -> CLong -> ArbStrOption -> IO CString++-- | /arb_mat_printd/ /mat/ /digits/ +-- +-- Prints each entry in the matrix with the specified number of decimal+-- digits.+arb_mat_printd :: Ptr CArbMat -> CLong -> IO ()+arb_mat_printd mat digits = do+ printCStr (flip arb_mat_get_strd digits) mat+ return ()+ +-- | /arb_mat_fprintd/ /file/ /mat/ /digits/ +-- +-- Prints each entry in the matrix with the specified number of decimal+-- digits to the stream /file/.+foreign import ccall "arb_mat.h arb_mat_fprintd"+ arb_mat_fprintd :: Ptr CFile -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_fprintn"+ arb_mat_fprintn :: Ptr CFile -> Ptr CArbMat -> CLong -> ArbStrOption -> IO ()++-- Comparisons -----------------------------------------------------------------++-- Predicate methods return 1 if the property certainly holds and 0+-- otherwise.+--+-- | /arb_mat_equal/ /mat1/ /mat2/ +-- +-- Returns whether the matrices have the same dimensions and identical+-- intervals as entries.+foreign import ccall "arb_mat.h arb_mat_equal"+ arb_mat_equal :: Ptr CArbMat -> Ptr CArbMat -> IO CInt++-- | /arb_mat_overlaps/ /mat1/ /mat2/ +-- +-- Returns whether the matrices have the same dimensions and each entry in+-- /mat1/ overlaps with the corresponding entry in /mat2/.+foreign import ccall "arb_mat.h arb_mat_overlaps"+ arb_mat_overlaps :: Ptr CArbMat -> Ptr CArbMat -> IO CInt++foreign import ccall "arb_mat.h arb_mat_contains"+ arb_mat_contains :: Ptr CArbMat -> Ptr CArbMat -> IO CInt++foreign import ccall "arb_mat.h arb_mat_contains_fmpz_mat"+ arb_mat_contains_fmpz_mat :: Ptr CArbMat -> Ptr CFmpzMat -> IO CInt++-- | /arb_mat_contains_fmpq_mat/ /mat1/ /mat2/ +-- +-- Returns whether the matrices have the same dimensions and each entry in+-- /mat2/ is contained in the corresponding entry in /mat1/.+foreign import ccall "arb_mat.h arb_mat_contains_fmpq_mat"+ arb_mat_contains_fmpq_mat :: Ptr CArbMat -> Ptr CFmpqMat -> IO CInt++-- | /arb_mat_eq/ /mat1/ /mat2/ +-- +-- Returns whether /mat1/ and /mat2/ certainly represent the same matrix.+foreign import ccall "arb_mat.h arb_mat_eq"+ arb_mat_eq :: Ptr CArbMat -> Ptr CArbMat -> IO CInt++-- | /arb_mat_ne/ /mat1/ /mat2/ +-- +-- Returns whether /mat1/ and /mat2/ certainly do not represent the same+-- matrix.+foreign import ccall "arb_mat.h arb_mat_ne"+ arb_mat_ne :: Ptr CArbMat -> Ptr CArbMat -> IO CInt++-- | /arb_mat_is_empty/ /mat/ +-- +-- Returns whether the number of rows or the number of columns in /mat/ is+-- zero.+foreign import ccall "arb_mat.h arb_mat_is_empty"+ arb_mat_is_empty :: Ptr CArbMat -> IO CInt++-- | /arb_mat_is_square/ /mat/ +-- +-- Returns whether the number of rows is equal to the number of columns in+-- /mat/.+foreign import ccall "arb_mat.h arb_mat_is_square"+ arb_mat_is_square :: Ptr CArbMat -> IO CInt++-- | /arb_mat_is_exact/ /mat/ +-- +-- Returns whether all entries in /mat/ have zero radius.+foreign import ccall "arb_mat.h arb_mat_is_exact"+ arb_mat_is_exact :: Ptr CArbMat -> IO CInt++-- | /arb_mat_is_zero/ /mat/ +-- +-- Returns whether all entries in /mat/ are exactly zero.+foreign import ccall "arb_mat.h arb_mat_is_zero"+ arb_mat_is_zero :: Ptr CArbMat -> IO CInt++-- | /arb_mat_is_finite/ /mat/ +-- +-- Returns whether all entries in /mat/ are finite.+foreign import ccall "arb_mat.h arb_mat_is_finite"+ arb_mat_is_finite :: Ptr CArbMat -> IO CInt++-- | /arb_mat_is_triu/ /mat/ +-- +-- Returns whether /mat/ is upper triangular; that is, all entries below+-- the main diagonal are exactly zero.+foreign import ccall "arb_mat.h arb_mat_is_triu"+ arb_mat_is_triu :: Ptr CArbMat -> IO CInt++-- | /arb_mat_is_tril/ /mat/ +-- +-- Returns whether /mat/ is lower triangular; that is, all entries above+-- the main diagonal are exactly zero.+foreign import ccall "arb_mat.h arb_mat_is_tril"+ arb_mat_is_tril :: Ptr CArbMat -> IO CInt++-- | /arb_mat_is_diag/ /mat/ +-- +-- Returns whether /mat/ is a diagonal matrix; that is, all entries off the+-- main diagonal are exactly zero.+foreign import ccall "arb_mat.h arb_mat_is_diag"+ arb_mat_is_diag :: Ptr CArbMat -> IO CInt++-- Special matrices ------------------------------------------------------------++-- | /arb_mat_zero/ /mat/ +-- +-- Sets all entries in mat to zero.+foreign import ccall "arb_mat.h arb_mat_zero"+ arb_mat_zero :: Ptr CArbMat -> IO ()++-- | /arb_mat_one/ /mat/ +-- +-- Sets the entries on the main diagonal to ones, and all other entries to+-- zero.+foreign import ccall "arb_mat.h arb_mat_one"+ arb_mat_one :: Ptr CArbMat -> IO ()++-- | /arb_mat_ones/ /mat/ +-- +-- Sets all entries in the matrix to ones.+foreign import ccall "arb_mat.h arb_mat_ones"+ arb_mat_ones :: Ptr CArbMat -> IO ()++-- | /arb_mat_indeterminate/ /mat/ +-- +-- Sets all entries in the matrix to indeterminate (NaN).+foreign import ccall "arb_mat.h arb_mat_indeterminate"+ arb_mat_indeterminate :: Ptr CArbMat -> IO ()++-- | /arb_mat_hilbert/ /mat/ /prec/ +-- +-- Sets /mat/ to the Hilbert matrix, which has entries+-- \(A_{j,k} = 1/(j+k+1)\).+foreign import ccall "arb_mat.h arb_mat_hilbert"+ arb_mat_hilbert :: Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_pascal/ /mat/ /triangular/ /prec/ +-- +-- Sets /mat/ to a Pascal matrix, whose entries are binomial coefficients.+-- If /triangular/ is 0, constructs a full symmetric matrix with the rows+-- of Pascal\'s triangle as successive antidiagonals. If /triangular/ is 1,+-- constructs the upper triangular matrix with the rows of Pascal\'s+-- triangle as columns, and if /triangular/ is -1, constructs the lower+-- triangular matrix with the rows of Pascal\'s triangle as rows.+-- +-- The entries are computed using recurrence relations. When the dimensions+-- get large, some precision loss is possible; in that case, the user may+-- wish to create the matrix at slightly higher precision and then round it+-- to the final precision.+foreign import ccall "arb_mat.h arb_mat_pascal"+ arb_mat_pascal :: Ptr CArbMat -> CInt -> CLong -> IO ()++-- | /arb_mat_stirling/ /mat/ /kind/ /prec/ +-- +-- Sets /mat/ to a Stirling matrix, whose entries are Stirling numbers. If+-- /kind/ is 0, the entries are set to the unsigned Stirling numbers of the+-- first kind. If /kind/ is 1, the entries are set to the signed Stirling+-- numbers of the first kind. If /kind/ is 2, the entries are set to the+-- Stirling numbers of the second kind.+-- +-- The entries are computed using recurrence relations. When the dimensions+-- get large, some precision loss is possible; in that case, the user may+-- wish to create the matrix at slightly higher precision and then round it+-- to the final precision.+foreign import ccall "arb_mat.h arb_mat_stirling"+ arb_mat_stirling :: Ptr CArbMat -> CInt -> CLong -> IO ()++-- | /arb_mat_dct/ /mat/ /type/ /prec/ +-- +-- Sets /mat/ to the DCT (discrete cosine transform) matrix of order /n/+-- where /n/ is the smallest dimension of /mat/ (if /mat/ is not square,+-- the matrix is extended periodically along the larger dimension). There+-- are many different conventions for defining DCT matrices; here, we use+-- the normalized \"DCT-II\" transform matrix+-- +-- \[`\]+-- \[A_{j,k} = \sqrt{\frac{2}{n}} \cos\left(\frac{\pi j}{n} \left(k+\frac{1}{2}\right)\right)\]+-- +-- which satisfies \(A^{-1} = A^T\). The /type/ parameter is currently+-- ignored and should be set to 0. In the future, it might be used to+-- select a different convention.+foreign import ccall "arb_mat.h arb_mat_dct"+ arb_mat_dct :: Ptr CArbMat -> CInt -> CLong -> IO ()++-- Transpose -------------------------------------------------------------------++-- | /arb_mat_transpose/ /dest/ /src/ +-- +-- Sets /dest/ to the exact transpose /src/. The operands must have+-- compatible dimensions. Aliasing is allowed.+foreign import ccall "arb_mat.h arb_mat_transpose"+ arb_mat_transpose :: Ptr CArbMat -> Ptr CArbMat -> IO ()++-- Norms -----------------------------------------------------------------------++-- | /arb_mat_bound_inf_norm/ /b/ /A/ +-- +-- Sets /b/ to an upper bound for the infinity norm (i.e. the largest+-- absolute value row sum) of /A/.+foreign import ccall "arb_mat.h arb_mat_bound_inf_norm"+ arb_mat_bound_inf_norm :: Ptr CMag -> Ptr CArbMat -> IO ()++-- | /arb_mat_frobenius_norm/ /res/ /A/ /prec/ +-- +-- Sets /res/ to the Frobenius norm (i.e. the square root of the sum of+-- squares of entries) of /A/.+foreign import ccall "arb_mat.h arb_mat_frobenius_norm"+ arb_mat_frobenius_norm :: Ptr CArb -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_bound_frobenius_norm/ /res/ /A/ +-- +-- Sets /res/ to an upper bound for the Frobenius norm of /A/.+foreign import ccall "arb_mat.h arb_mat_bound_frobenius_norm"+ arb_mat_bound_frobenius_norm :: Ptr CMag -> Ptr CArbMat -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- | /arb_mat_neg/ /dest/ /src/ +-- +-- Sets /dest/ to the exact negation of /src/. The operands must have the+-- same dimensions.+foreign import ccall "arb_mat.h arb_mat_neg"+ arb_mat_neg :: Ptr CArbMat -> Ptr CArbMat -> IO ()++-- | /arb_mat_add/ /res/ /mat1/ /mat2/ /prec/ +-- +-- Sets res to the sum of /mat1/ and /mat2/. The operands must have the+-- same dimensions.+foreign import ccall "arb_mat.h arb_mat_add"+ arb_mat_add :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_sub/ /res/ /mat1/ /mat2/ /prec/ +-- +-- Sets /res/ to the difference of /mat1/ and /mat2/. The operands must+-- have the same dimensions.+foreign import ccall "arb_mat.h arb_mat_sub"+ arb_mat_sub :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_mul_classical"+ arb_mat_mul_classical :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_mul_threaded"+ arb_mat_mul_threaded :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_mul_block"+ arb_mat_mul_block :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_mul/ /res/ /mat1/ /mat2/ /prec/ +-- +-- Sets /res/ to the matrix product of /mat1/ and /mat2/. The operands must+-- have compatible dimensions for matrix multiplication.+-- +-- The /classical/ version performs matrix multiplication in the trivial+-- way.+-- +-- The /block/ version decomposes the input matrices into one or several+-- blocks of uniformly scaled matrices and multiplies large blocks via+-- /fmpz_mat_mul/. It also invokes @_arb_mat_addmul_rad_mag_fast@ for the+-- radius matrix multiplications.+-- +-- The /threaded/ version performs classical multiplication but splits the+-- computation over the number of threads returned by+-- /flint_get_num_threads()/.+-- +-- The default version chooses an algorithm automatically.+foreign import ccall "arb_mat.h arb_mat_mul"+ arb_mat_mul :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_mul_entrywise/ /C/ /A/ /B/ /prec/ +-- +-- Sets /C/ to the entrywise product of /A/ and /B/. The operands must have+-- the same dimensions.+foreign import ccall "arb_mat.h arb_mat_mul_entrywise"+ arb_mat_mul_entrywise :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_sqr_classical"+ arb_mat_sqr_classical :: Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_sqr/ /res/ /mat/ /prec/ +-- +-- Sets /res/ to the matrix square of /mat/. The operands must both be+-- square with the same dimensions.+foreign import ccall "arb_mat.h arb_mat_sqr"+ arb_mat_sqr :: Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_pow_ui/ /res/ /mat/ /exp/ /prec/ +-- +-- Sets /res/ to /mat/ raised to the power /exp/. Requires that /mat/ is a+-- square matrix.+foreign import ccall "arb_mat.h arb_mat_pow_ui"+ arb_mat_pow_ui :: Ptr CArbMat -> Ptr CArbMat -> CULong -> CLong -> IO ()++-- | /_arb_mat_addmul_rad_mag_fast/ /C/ /A/ /B/ /ar/ /ac/ /bc/ +-- +-- Helper function for matrix multiplication. Adds to the radii of /C/ the+-- matrix product of the matrices represented by /A/ and /B/, where /A/ is+-- a linear array of coefficients in row-major order and /B/ is a linear+-- array of coefficients in column-major order. This function assumes that+-- all exponents are small and is unsafe for general use.+foreign import ccall "arb_mat.h _arb_mat_addmul_rad_mag_fast"+ _arb_mat_addmul_rad_mag_fast :: Ptr CArbMat -> Ptr CMag -> Ptr CMag -> CLong -> CLong -> CLong -> IO ()++-- | /arb_mat_approx_mul/ /res/ /mat1/ /mat2/ /prec/ +-- +-- Approximate matrix multiplication. The input radii are ignored and the+-- output matrix is set to an approximate floating-point result. The radii+-- in the output matrix will /not/ necessarily be zeroed.+foreign import ccall "arb_mat.h arb_mat_approx_mul"+ arb_mat_approx_mul :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++-- Scalar arithmetic -----------------------------------------------------------++-- | /arb_mat_scalar_mul_2exp_si/ /B/ /A/ /c/ +-- +-- Sets /B/ to /A/ multiplied by \(2^c\).+foreign import ccall "arb_mat.h arb_mat_scalar_mul_2exp_si"+ arb_mat_scalar_mul_2exp_si :: Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_scalar_addmul_si"+ arb_mat_scalar_addmul_si :: Ptr CArbMat -> Ptr CArbMat -> CLong -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_scalar_addmul_fmpz"+ arb_mat_scalar_addmul_fmpz :: Ptr CArbMat -> Ptr CArbMat -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_mat_scalar_addmul_arb/ /B/ /A/ /c/ /prec/ +-- +-- Sets /B/ to \(B + A \times c\).+foreign import ccall "arb_mat.h arb_mat_scalar_addmul_arb"+ arb_mat_scalar_addmul_arb :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_scalar_mul_si"+ arb_mat_scalar_mul_si :: Ptr CArbMat -> Ptr CArbMat -> CLong -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_scalar_mul_fmpz"+ arb_mat_scalar_mul_fmpz :: Ptr CArbMat -> Ptr CArbMat -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_mat_scalar_mul_arb/ /B/ /A/ /c/ /prec/ +-- +-- Sets /B/ to \(A \times c\).+foreign import ccall "arb_mat.h arb_mat_scalar_mul_arb"+ arb_mat_scalar_mul_arb :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArb -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_scalar_div_si"+ arb_mat_scalar_div_si :: Ptr CArbMat -> Ptr CArbMat -> CLong -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_scalar_div_fmpz"+ arb_mat_scalar_div_fmpz :: Ptr CArbMat -> Ptr CArbMat -> Ptr CFmpz -> CLong -> IO ()++-- | /arb_mat_scalar_div_arb/ /B/ /A/ /c/ /prec/ +-- +-- Sets /B/ to \(A / c\).+foreign import ccall "arb_mat.h arb_mat_scalar_div_arb"+ arb_mat_scalar_div_arb :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArb -> CLong -> IO ()++-- Gaussian elimination and solving --------------------------------------------++foreign import ccall "arb_mat.h arb_mat_lu_classical"+ arb_mat_lu_classical :: Ptr CLong -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++foreign import ccall "arb_mat.h arb_mat_lu_recursive"+ arb_mat_lu_recursive :: Ptr CLong -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++-- | /arb_mat_lu/ /perm/ /LU/ /A/ /prec/ +-- +-- Given an \(n \times n\) matrix \(A\), computes an LU decomposition+-- \(PLU = A\) using Gaussian elimination with partial pivoting. The input+-- and output matrices can be the same, performing the decomposition+-- in-place.+-- +-- Entry \(i\) in the permutation vector perm is set to the row index in+-- the input matrix corresponding to row \(i\) in the output matrix.+-- +-- The algorithm succeeds and returns nonzero if it can find \(n\)+-- invertible (i.e. not containing zero) pivot entries. This guarantees+-- that the matrix is invertible.+-- +-- The algorithm fails and returns zero, leaving the entries in \(P\) and+-- \(LU\) undefined, if it cannot find \(n\) invertible pivot elements. In+-- this case, either the matrix is singular, the input matrix was computed+-- to insufficient precision, or the LU decomposition was attempted at+-- insufficient precision.+-- +-- The /classical/ version uses Gaussian elimination directly while the+-- /recursive/ version performs the computation in a block recursive way to+-- benefit from fast matrix multiplication. The default version chooses an+-- algorithm automatically.+foreign import ccall "arb_mat.h arb_mat_lu"+ arb_mat_lu :: Ptr CLong -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++foreign import ccall "arb_mat.h arb_mat_solve_tril_classical"+ arb_mat_solve_tril_classical :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CInt -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_solve_tril_recursive"+ arb_mat_solve_tril_recursive :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CInt -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_solve_tril"+ arb_mat_solve_tril :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CInt -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_solve_triu_classical"+ arb_mat_solve_triu_classical :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CInt -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_solve_triu_recursive"+ arb_mat_solve_triu_recursive :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CInt -> CLong -> IO ()++-- | /arb_mat_solve_triu/ /X/ /U/ /B/ /unit/ /prec/ +-- +-- Solves the lower triangular system \(LX = B\) or the upper triangular+-- system \(UX = B\), respectively. If /unit/ is set, the main diagonal of+-- /L/ or /U/ is taken to consist of all ones, and in that case the actual+-- entries on the diagonal are not read at all and can contain other data.+-- +-- The /classical/ versions perform the computations iteratively while the+-- /recursive/ versions perform the computations in a block recursive way+-- to benefit from fast matrix multiplication. The default versions choose+-- an algorithm automatically.+foreign import ccall "arb_mat.h arb_mat_solve_triu"+ arb_mat_solve_triu :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CInt -> CLong -> IO ()++-- | /arb_mat_solve_lu_precomp/ /X/ /perm/ /LU/ /B/ /prec/ +-- +-- Solves \(AX = B\) given the precomputed nonsingular LU decomposition+-- \(A = PLU\). The matrices \(X\) and \(B\) are allowed to be aliased with+-- each other, but \(X\) is not allowed to be aliased with \(LU\).+foreign import ccall "arb_mat.h arb_mat_solve_lu_precomp"+ arb_mat_solve_lu_precomp :: Ptr CArbMat -> Ptr CLong -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_solve"+ arb_mat_solve :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++foreign import ccall "arb_mat.h arb_mat_solve_lu"+ arb_mat_solve_lu :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++-- | /arb_mat_solve_precond/ /X/ /A/ /B/ /prec/ +-- +-- Solves \(AX = B\) where \(A\) is a nonsingular \(n \times n\) matrix and+-- \(X\) and \(B\) are \(n \times m\) matrices.+-- +-- If \(m > 0\) and \(A\) cannot be inverted numerically (indicating either+-- that \(A\) is singular or that the precision is insufficient), the+-- values in the output matrix are left undefined and zero is returned. A+-- nonzero return value guarantees that \(A\) is invertible and that the+-- exact solution matrix is contained in the output.+-- +-- Three algorithms are provided:+-- +-- - The /lu/ version performs LU decomposition directly in ball+-- arithmetic. This is fast, but the bounds typically blow up+-- exponentially with /n/, even if the system is well-conditioned. This+-- algorithm is usually the best choice at very high precision.+-- - The /precond/ version computes an approximate inverse to+-- precondition the system < [HS1967]>. This is usually several times+-- slower than direct LU decomposition, but the bounds do not blow up+-- with /n/ if the system is well-conditioned. This algorithm is+-- usually the best choice for large systems at low to moderate+-- precision.+-- - The default version selects between /lu/ and /precomp/+-- automatically.+-- +-- The automatic choice should be reasonable most of the time, but users+-- may benefit from trying either /lu/ or /precond/ in specific+-- applications. For example, the /lu/ solver often performs better for+-- ill-conditioned systems where use of very high precision is unavoidable.+foreign import ccall "arb_mat.h arb_mat_solve_precond"+ arb_mat_solve_precond :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++-- | /arb_mat_solve_preapprox/ /X/ /A/ /B/ /R/ /T/ /prec/ +-- +-- Solves \(AX = B\) where \(A\) is a nonsingular \(n \times n\) matrix and+-- \(X\) and \(B\) are \(n \times m\) matrices, given an approximation+-- \(R\) of the matrix inverse of \(A\), and given the approximation \(T\)+-- of the solution \(X\).+-- +-- If \(m > 0\) and \(A\) cannot be inverted numerically (indicating either+-- that \(A\) is singular or that the precision is insufficient, or that+-- \(R\) is not a close enough approximation of the inverse of \(A\)), the+-- values in the output matrix are left undefined and zero is returned. A+-- nonzero return value guarantees that \(A\) is invertible and that the+-- exact solution matrix is contained in the output.+foreign import ccall "arb_mat.h arb_mat_solve_preapprox"+ arb_mat_solve_preapprox :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++-- | /arb_mat_inv/ /X/ /A/ /prec/ +-- +-- Sets \(X = A^{-1}\) where \(A\) is a square matrix, computed by solving+-- the system \(AX = I\).+-- +-- If \(A\) cannot be inverted numerically (indicating either that \(A\) is+-- singular or that the precision is insufficient), the values in the+-- output matrix are left undefined and zero is returned. A nonzero return+-- value guarantees that the matrix is invertible and that the exact+-- inverse is contained in the output.+foreign import ccall "arb_mat.h arb_mat_inv"+ arb_mat_inv :: Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++foreign import ccall "arb_mat.h arb_mat_det_lu"+ arb_mat_det_lu :: Ptr CArb -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_det_precond"+ arb_mat_det_precond :: Ptr CArb -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_det/ /det/ /A/ /prec/ +-- +-- Sets /det/ to the determinant of the matrix /A/.+-- +-- The /lu/ version uses Gaussian elimination with partial pivoting. If at+-- some point an invertible pivot element cannot be found, the elimination+-- is stopped and the magnitude of the determinant of the remaining+-- submatrix is bounded using Hadamard\'s inequality.+-- +-- The /precond/ version computes an approximate LU factorization of /A/+-- and multiplies by the inverse /L/ and /U/ martices as preconditioners to+-- obtain a matrix close to the identity matrix < [Rum2010]>. An enclosure+-- for this determinant is computed using Gershgorin circles. This is about+-- four times slower than direct Gaussian elimination, but much more+-- numerically stable.+-- +-- The default version automatically selects between the /lu/ and /precond/+-- versions and additionally handles small or triangular matrices by direct+-- formulas.+foreign import ccall "arb_mat.h arb_mat_det"+ arb_mat_det :: Ptr CArb -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_approx_solve_triu"+ arb_mat_approx_solve_triu :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CInt -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_approx_solve_tril"+ arb_mat_approx_solve_tril :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CInt -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_approx_lu"+ arb_mat_approx_lu :: Ptr CLong -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++foreign import ccall "arb_mat.h arb_mat_approx_solve_lu_precomp"+ arb_mat_approx_solve_lu_precomp :: Ptr CArbMat -> Ptr CLong -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h arb_mat_approx_solve"+ arb_mat_approx_solve :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++-- | /arb_mat_approx_inv/ /X/ /A/ /prec/ +-- +-- These methods perform approximate solving /without any error control/.+-- The radii in the input matrices are ignored, the computations are done+-- numerically with floating-point arithmetic (using ordinary Gaussian+-- elimination and triangular solving, accelerated through the use of block+-- recursive strategies for large matrices), and the output matrices are+-- set to the approximate floating-point results with zeroed error bounds.+-- +-- Approximate solutions are useful for computing preconditioning matrices+-- for certified solutions. Some users may also find these methods useful+-- for doing ordinary numerical linear algebra in applications where error+-- bounds are not needed.+foreign import ccall "arb_mat.h arb_mat_approx_inv"+ arb_mat_approx_inv :: Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++-- Cholesky decomposition and solving ------------------------------------------++foreign import ccall "arb_mat.h _arb_mat_cholesky_banachiewicz"+ _arb_mat_cholesky_banachiewicz :: Ptr CArbMat -> CLong -> IO CInt++-- | /arb_mat_cho/ /L/ /A/ /prec/ +-- +-- Computes the Cholesky decomposition of /A/, returning nonzero iff the+-- symmetric matrix defined by the lower triangular part of /A/ is+-- certainly positive definite.+-- +-- If a nonzero value is returned, then /L/ is set to the lower triangular+-- matrix such that \(A = L * L^T\).+-- +-- If zero is returned, then either the matrix is not symmetric positive+-- definite, the input matrix was computed to insufficient precision, or+-- the decomposition was attempted at insufficient precision.+-- +-- The underscore method computes /L/ from /A/ in-place, leaving the strict+-- upper triangular region undefined.+foreign import ccall "arb_mat.h arb_mat_cho"+ arb_mat_cho :: Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++-- | /arb_mat_solve_cho_precomp/ /X/ /L/ /B/ /prec/ +-- +-- Solves \(AX = B\) given the precomputed Cholesky decomposition+-- \(A = L L^T\). The matrices /X/ and /B/ are allowed to be aliased with+-- each other, but /X/ is not allowed to be aliased with /L/.+foreign import ccall "arb_mat.h arb_mat_solve_cho_precomp"+ arb_mat_solve_cho_precomp :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_spd_solve/ /X/ /A/ /B/ /prec/ +-- +-- Solves \(AX = B\) where /A/ is a symmetric positive definite matrix and+-- /X/ and /B/ are \(n \times m\) matrices, using Cholesky decomposition.+-- +-- If \(m > 0\) and /A/ cannot be factored using Cholesky decomposition+-- (indicating either that /A/ is not symmetric positive definite or that+-- the precision is insufficient), the values in the output matrix are left+-- undefined and zero is returned. A nonzero return value guarantees that+-- the symmetric matrix defined through the lower triangular part of /A/ is+-- invertible and that the exact solution matrix is contained in the+-- output.+foreign import ccall "arb_mat.h arb_mat_spd_solve"+ arb_mat_spd_solve :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++-- | /arb_mat_inv_cho_precomp/ /X/ /L/ /prec/ +-- +-- Sets \(X = A^{-1}\) where \(A\) is a symmetric positive definite matrix+-- whose Cholesky decomposition /L/ has been computed with @arb_mat_cho@.+-- The inverse is calculated using the method of < [Kri2013]> which is more+-- efficient than solving \(AX = I\) with @arb_mat_solve_cho_precomp@.+foreign import ccall "arb_mat.h arb_mat_inv_cho_precomp"+ arb_mat_inv_cho_precomp :: Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_spd_inv/ /X/ /A/ /prec/ +-- +-- Sets \(X = A^{-1}\) where /A/ is a symmetric positive definite matrix.+-- It is calculated using the method of < [Kri2013]> which computes fewer+-- intermediate results than solving \(AX = I\) with @arb_mat_spd_solve@.+-- +-- If /A/ cannot be factored using Cholesky decomposition (indicating+-- either that /A/ is not symmetric positive definite or that the precision+-- is insufficient), the values in the output matrix are left undefined and+-- zero is returned. A nonzero return value guarantees that the symmetric+-- matrix defined through the lower triangular part of /A/ is invertible+-- and that the exact inverse is contained in the output.+foreign import ccall "arb_mat.h arb_mat_spd_inv"+ arb_mat_spd_inv :: Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++foreign import ccall "arb_mat.h _arb_mat_ldl_inplace"+ _arb_mat_ldl_inplace :: Ptr CArbMat -> CLong -> IO CInt++foreign import ccall "arb_mat.h _arb_mat_ldl_golub_and_van_loan"+ _arb_mat_ldl_golub_and_van_loan :: Ptr CArbMat -> CLong -> IO CInt++-- | /arb_mat_ldl/ /res/ /A/ /prec/ +-- +-- Computes the \(LDL^T\) decomposition of /A/, returning nonzero iff the+-- symmetric matrix defined by the lower triangular part of /A/ is+-- certainly positive definite.+-- +-- If a nonzero value is returned, then /res/ is set to a lower triangular+-- matrix that encodes the \(L * D * L^T\) decomposition of /A/. In+-- particular, \(L\) is a lower triangular matrix with ones on its diagonal+-- and whose strictly lower triangular region is the same as that of /res/.+-- \(D\) is a diagonal matrix with the same diagonal as that of /res/.+-- +-- If zero is returned, then either the matrix is not symmetric positive+-- definite, the input matrix was computed to insufficient precision, or+-- the decomposition was attempted at insufficient precision.+-- +-- The underscore methods compute /res/ from /A/ in-place, leaving the+-- strict upper triangular region undefined. The default method uses+-- algorithm 4.1.2 from < [GVL1996]>.+foreign import ccall "arb_mat.h arb_mat_ldl"+ arb_mat_ldl :: Ptr CArbMat -> Ptr CArbMat -> CLong -> IO CInt++-- | /arb_mat_solve_ldl_precomp/ /X/ /L/ /B/ /prec/ +-- +-- Solves \(AX = B\) given the precomputed \(A = LDL^T\) decomposition+-- encoded by /L/. The matrices /X/ and /B/ are allowed to be aliased with+-- each other, but /X/ is not allowed to be aliased with /L/.+foreign import ccall "arb_mat.h arb_mat_solve_ldl_precomp"+ arb_mat_solve_ldl_precomp :: Ptr CArbMat -> Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_inv_ldl_precomp/ /X/ /L/ /prec/ +-- +-- Sets \(X = A^{-1}\) where \(A\) is a symmetric positive definite matrix+-- whose \(LDL^T\) decomposition encoded by /L/ has been computed with+-- @arb_mat_ldl@. The inverse is calculated using the method of+-- < [Kri2013]> which is more efficient than solving \(AX = I\) with+-- @arb_mat_solve_ldl_precomp@.+foreign import ccall "arb_mat.h arb_mat_inv_ldl_precomp"+ arb_mat_inv_ldl_precomp :: Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++-- Characteristic polynomial and companion matrix ------------------------------++foreign import ccall "arb_mat.h _arb_mat_charpoly"+ _arb_mat_charpoly :: Ptr CArb -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_charpoly/ /poly/ /mat/ /prec/ +-- +-- Sets /poly/ to the characteristic polynomial of /mat/ which must be a+-- square matrix. If the matrix has /n/ rows, the underscore method+-- requires space for \(n + 1\) output coefficients. Employs a+-- division-free algorithm using \(O(n^4)\) operations.+foreign import ccall "arb_mat.h arb_mat_charpoly"+ arb_mat_charpoly :: Ptr CArbPoly -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h _arb_mat_companion"+ _arb_mat_companion :: Ptr CArbMat -> Ptr CArb -> CLong -> IO ()++-- | /arb_mat_companion/ /mat/ /poly/ /prec/ +-- +-- Sets the /n/ by /n/ matrix /mat/ to the companion matrix of the+-- polynomial /poly/ which must have degree /n/. The underscore method+-- reads \(n + 1\) input coefficients.+foreign import ccall "arb_mat.h arb_mat_companion"+ arb_mat_companion :: Ptr CArbMat -> Ptr CArbPoly -> CLong -> IO ()++-- Special functions -----------------------------------------------------------++-- | /arb_mat_exp_taylor_sum/ /S/ /A/ /N/ /prec/ +-- +-- Sets /S/ to the truncated exponential Taylor series+-- \(S = \sum_{k=0}^{N-1} A^k / k!\). Uses rectangular splitting to compute+-- the sum using \(O(\sqrt{N})\) matrix multiplications. The recurrence+-- relation for factorials is used to get scalars that are small integers+-- instead of full factorials. As in < [Joh2014b]>, all divisions are+-- postponed to the end by computing partial factorials of length+-- \(O(\sqrt{N})\). The scalars could be reduced by doing more divisions,+-- but this appears to be slower in most cases.+foreign import ccall "arb_mat.h arb_mat_exp_taylor_sum"+ arb_mat_exp_taylor_sum :: Ptr CArbMat -> Ptr CArbMat -> CLong -> CLong -> IO ()++-- | /arb_mat_exp/ /B/ /A/ /prec/ +-- +-- Sets /B/ to the exponential of the matrix /A/, defined by the Taylor+-- series+-- +-- \[`\]+-- \[\exp(A) = \sum_{k=0}^{\infty} \frac{A^k}{k!}.\]+-- +-- The function is evaluated as \(\exp(A/2^r)^{2^r}\), where \(r\) is+-- chosen to give rapid convergence.+-- +-- The elementwise error when truncating the Taylor series after /N/ terms+-- is bounded by the error in the infinity norm, for which we have+-- +-- \[`+-- \left\|\exp(2^{-r}A) - \sum_{k=0}^{N-1}+-- \frac{\left(2^{-r} A\right)^k}{k!} \right\|_{\infty} =+-- \left\|\sum_{k=N}^{\infty} \frac{\left(2^{-r} A\right)^k}{k!}\right\|_{\infty} \le+-- \sum_{k=N}^{\infty} \frac{(2^{-r} \|A\|_{\infty})^k}{k!}.\]+-- +-- We bound the sum on the right using @mag_exp_tail@. Truncation error is+-- not added to entries whose values are determined by the sparsity+-- structure of \(A\).+foreign import ccall "arb_mat.h arb_mat_exp"+ arb_mat_exp :: Ptr CArbMat -> Ptr CArbMat -> CLong -> IO ()++-- | /arb_mat_trace/ /trace/ /mat/ /prec/ +-- +-- Sets /trace/ to the trace of the matrix, i.e. the sum of entries on the+-- main diagonal of /mat/. The matrix is required to be square.+foreign import ccall "arb_mat.h arb_mat_trace"+ arb_mat_trace :: Ptr CArb -> Ptr CArbMat -> CLong -> IO ()++foreign import ccall "arb_mat.h _arb_mat_diag_prod"+ _arb_mat_diag_prod :: Ptr CArb -> Ptr CArbMat -> CLong -> CLong -> CLong -> IO ()++-- | /arb_mat_diag_prod/ /res/ /mat/ /prec/ +-- +-- Sets /res/ to the product of the entries on the main diagonal of /mat/.+-- The underscore method computes the product of the entries between index+-- /a/ inclusive and /b/ exclusive (the indices must be in range).+foreign import ccall "arb_mat.h arb_mat_diag_prod"+ arb_mat_diag_prod :: Ptr CArb -> Ptr CArbMat -> CLong -> IO ()++-- Sparsity structure ----------------------------------------------------------++-- -- | /arb_mat_entrywise_is_zero/ /dest/ /src/ +-- -- +-- -- Sets each entry of /dest/ to indicate whether the corresponding entry of+-- -- /src/ is certainly zero. If the entry of /src/ at row \(i\) and column+-- -- \(j\) is zero according to @arb_is_zero@ then the entry of /dest/ at+-- -- that row and column is set to one, otherwise that entry of /dest/ is set+-- -- to zero.+-- foreign import ccall "arb_mat.h arb_mat_entrywise_is_zero"+-- arb_mat_entrywise_is_zero :: Ptr CFmpzMat -> Ptr CArbMat -> IO ()++-- | /arb_mat_entrywise_not_is_zero/ /dest/ /src/ +-- +-- Sets each entry of /dest/ to indicate whether the corresponding entry of+-- /src/ is not certainly zero. This the complement of+-- @arb_mat_entrywise_is_zero@.+foreign import ccall "arb_mat.h arb_mat_entrywise_not_is_zero"+ arb_mat_entrywise_not_is_zero :: Ptr CFmpzMat -> Ptr CArbMat -> IO ()++-- | /arb_mat_count_is_zero/ /mat/ +-- +-- Returns the number of entries of /mat/ that are certainly zero according+-- to @arb_is_zero@.+foreign import ccall "arb_mat.h arb_mat_count_is_zero"+ arb_mat_count_is_zero :: Ptr CArbMat -> IO CLong++-- | /arb_mat_count_not_is_zero/ /mat/ +-- +-- Returns the number of entries of /mat/ that are not certainly zero.+foreign import ccall "arb_mat.h arb_mat_count_not_is_zero"+ arb_mat_count_not_is_zero :: Ptr CArbMat -> IO CLong++-- Component and error operations ----------------------------------------------++-- | /arb_mat_get_mid/ /B/ /A/ +-- +-- Sets the entries of /B/ to the exact midpoints of the entries of /A/.+foreign import ccall "arb_mat.h arb_mat_get_mid"+ arb_mat_get_mid :: Ptr CArbMat -> Ptr CArbMat -> IO ()++-- | /arb_mat_add_error_mag/ /mat/ /err/ +-- +-- Adds /err/ in-place to the radii of the entries of /mat/.+foreign import ccall "arb_mat.h arb_mat_add_error_mag"+ arb_mat_add_error_mag :: Ptr CArbMat -> Ptr CMag -> IO ()++-- Eigenvalues and eigenvectors ------------------------------------------------++-- To compute eigenvalues and eigenvectors, one can convert to an+-- @acb_mat_t@ and use the functions in+-- @acb_mat.h: Eigenvalues and eigenvectors\<acb-mat-eigenvalues>@. In the+-- future dedicated methods for real matrices will be added here.+--
+ src/Data/Number/Flint/Arb/Mat/Instances.hs view
@@ -0,0 +1,19 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Arb.Mat.Instances where++import System.IO.Unsafe++import Foreign.C.String+import Foreign.Marshal.Alloc ( free )+import Foreign.Storable++import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.Mat++instance Show ArbMat where+ show x = unsafePerformIO $ do+ (_, cs) <- withArbMat x $ \x -> do arb_mat_get_strn x 16 arb_str_no_radius+ s <- peekCString cs+ free cs+ return s+
+ src/Data/Number/Flint/Arb/Poly.hs view
@@ -0,0 +1,16 @@+{- |+An @ArbPoly@ represents a polynomial over the real numbers,+implemented as an array of coefficients of type @arb_struct@.++Most functions are provided in two versions: an underscore method which+operates directly on pre-allocated arrays of coefficients and generally+has some restrictions (such as requiring the lengths to be nonzero and+not supporting aliasing of the input and output arrays), and a+non-underscore method which performs automatic memory management and+handles degenerate cases.+-}+module Data.Number.Flint.Arb.Poly (+ module Data.Number.Flint.Arb.Poly.FFI+ ) where++import Data.Number.Flint.Arb.Poly.FFI
+ src/Data/Number/Flint/Arb/Poly/FFI.hsc view
@@ -0,0 +1,1981 @@+{-|+module : Data.Number.Flint.Arb.Poly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Arb.Poly.FFI (+ -- * Polynomials over the real numbers+ ArbPoly (..)+ , CArbPoly (..)+ , newArbPoly+ , newArbPolyFromFmpzPoly+ , newArbPolyFromFmpqPoly+ , withArbPoly+ , withNewArbPoly+ , withNewArbPolyFromFmpzPoly+ , withNewArbPolyFromFmpqPoly+ -- * Memory management+ , arb_poly_init+ , arb_poly_clear+ , arb_poly_fit_length+ , _arb_poly_set_length+ , _arb_poly_normalise+ , arb_poly_allocated_bytes+ -- * Basic manipulation+ , arb_poly_length+ , arb_poly_degree+ , arb_poly_is_zero+ , arb_poly_is_one+ , arb_poly_is_x+ , arb_poly_zero+ , arb_poly_one+ , arb_poly_set+ , arb_poly_set_round+ , arb_poly_set_trunc+ , arb_poly_set_trunc_round+ , arb_poly_set_coeff_si+ , arb_poly_set_coeff_arb+ , arb_poly_get_coeff_arb+ , _arb_poly_shift_right+ , arb_poly_shift_right+ , _arb_poly_shift_left+ , arb_poly_shift_left+ , arb_poly_truncate+ , arb_poly_valuation+ -- * Conversions+ , arb_poly_set_fmpz_poly+ , arb_poly_set_fmpq_poly+ , arb_poly_set_si+ -- * Input and output+ , arb_poly_get_strd+ , arb_poly_printd+ , arb_poly_fprintd+ -- * Random generation+ , arb_poly_randtest+ -- * Comparisons+ , arb_poly_contains+ , arb_poly_contains_fmpz_poly+ , arb_poly_contains_fmpq_poly+ , arb_poly_equal+ , _arb_poly_overlaps+ , arb_poly_overlaps+ , arb_poly_get_unique_fmpz_poly+ -- * Bounds+ , _arb_poly_majorant+ , arb_poly_majorant+ -- * Arithmetic+ , _arb_poly_add+ , arb_poly_add+ , arb_poly_add_si+ , _arb_poly_sub+ , arb_poly_sub+ , arb_poly_add_series+ , arb_poly_sub_series+ , arb_poly_neg+ , arb_poly_scalar_mul_2exp_si+ , arb_poly_scalar_mul+ , arb_poly_scalar_div+ , _arb_poly_mullow_classical+ , _arb_poly_mullow_block+ , _arb_poly_mullow+ , arb_poly_mullow_classical+ --, arb_poly_mullow_ztrunc+ , arb_poly_mullow_block+ , arb_poly_mullow+ , _arb_poly_mul+ , arb_poly_mul+ , _arb_poly_inv_series+ , arb_poly_inv_series+ , _arb_poly_div_series+ , arb_poly_div_series+ , _arb_poly_div+ , _arb_poly_rem+ , _arb_poly_divrem+ , arb_poly_divrem+ , _arb_poly_div_root+ -- * Composition+ , _arb_poly_taylor_shift+ , arb_poly_taylor_shift+ , _arb_poly_compose+ , arb_poly_compose+ , _arb_poly_compose_series+ , arb_poly_compose_series+ , _arb_poly_revert_series_lagrange+ , arb_poly_revert_series_lagrange+ , _arb_poly_revert_series_newton+ , arb_poly_revert_series_newton+ , _arb_poly_revert_series_lagrange_fast+ , arb_poly_revert_series_lagrange_fast+ , _arb_poly_revert_series+ , arb_poly_revert_series+ -- * Evaluation+ , _arb_poly_evaluate_horner+ , arb_poly_evaluate_horner+ , _arb_poly_evaluate_rectangular+ , arb_poly_evaluate_rectangular+ , _arb_poly_evaluate+ , arb_poly_evaluate+ , _arb_poly_evaluate_acb_horner+ , arb_poly_evaluate_acb_horner+ , _arb_poly_evaluate_acb_rectangular+ , arb_poly_evaluate_acb_rectangular+ , _arb_poly_evaluate_acb+ , arb_poly_evaluate_acb+ , _arb_poly_evaluate2_horner+ , arb_poly_evaluate2_horner+ , _arb_poly_evaluate2_rectangular+ , arb_poly_evaluate2_rectangular+ , _arb_poly_evaluate2+ , arb_poly_evaluate2+ , _arb_poly_evaluate2_acb_horner+ , arb_poly_evaluate2_acb_horner+ , _arb_poly_evaluate2_acb_rectangular+ , arb_poly_evaluate2_acb_rectangular+ , _arb_poly_evaluate2_acb+ , arb_poly_evaluate2_acb+ -- * Product trees+ , _arb_poly_product_roots+ , arb_poly_product_roots+ , _arb_poly_product_roots_complex+ , arb_poly_product_roots_complex+ , _arb_poly_tree_alloc+ , _arb_poly_tree_free+ , _arb_poly_tree_build+ -- * Multipoint evaluation+ , _arb_poly_evaluate_vec_iter+ , arb_poly_evaluate_vec_iter+ , _arb_poly_evaluate_vec_fast_precomp+ , _arb_poly_evaluate_vec_fast+ , arb_poly_evaluate_vec_fast+ -- * Interpolation+ , _arb_poly_interpolate_newton+ , arb_poly_interpolate_newton+ , _arb_poly_interpolate_barycentric+ , arb_poly_interpolate_barycentric+ , _arb_poly_interpolation_weights+ , _arb_poly_interpolate_fast_precomp+ , _arb_poly_interpolate_fast+ , arb_poly_interpolate_fast+ -- * Differentiation+ , _arb_poly_derivative+ , arb_poly_derivative+ , _arb_poly_nth_derivative+ , arb_poly_nth_derivative+ , _arb_poly_integral+ , arb_poly_integral+ -- * Transforms+ , _arb_poly_borel_transform+ , arb_poly_borel_transform+ , _arb_poly_inv_borel_transform+ , arb_poly_inv_borel_transform+ , _arb_poly_binomial_transform_basecase+ , arb_poly_binomial_transform_basecase+ , _arb_poly_binomial_transform_convolution+ , arb_poly_binomial_transform_convolution+ , _arb_poly_binomial_transform+ , arb_poly_binomial_transform+ , _arb_poly_graeffe_transform+ , arb_poly_graeffe_transform+ -- * Powers and elementary functions+ , _arb_poly_pow_ui_trunc_binexp+ , arb_poly_pow_ui_trunc_binexp+ , _arb_poly_pow_ui+ , arb_poly_pow_ui+ , _arb_poly_pow_series+ , arb_poly_pow_series+ , _arb_poly_pow_arb_series+ , arb_poly_pow_arb_series+ , _arb_poly_sqrt_series+ , arb_poly_sqrt_series+ , _arb_poly_rsqrt_series+ , arb_poly_rsqrt_series+ , _arb_poly_log_series+ , arb_poly_log_series+ , _arb_poly_log1p_series+ , arb_poly_log1p_series+ , _arb_poly_atan_series+ , arb_poly_atan_series+ , _arb_poly_asin_series+ , arb_poly_asin_series+ , _arb_poly_acos_series+ , arb_poly_acos_series+ , _arb_poly_exp_series_basecase+ , arb_poly_exp_series_basecase+ , _arb_poly_exp_series+ , arb_poly_exp_series+ , _arb_poly_sin_cos_series+ , arb_poly_sin_cos_series+ , _arb_poly_sin_series+ , arb_poly_sin_series+ , _arb_poly_cos_series+ , arb_poly_cos_series+ , _arb_poly_tan_series+ , arb_poly_tan_series+ , _arb_poly_sin_cos_pi_series+ , arb_poly_sin_cos_pi_series+ , _arb_poly_sin_pi_series+ , arb_poly_sin_pi_series+ , _arb_poly_cos_pi_series+ , arb_poly_cos_pi_series+ , _arb_poly_cot_pi_series+ , arb_poly_cot_pi_series+ , _arb_poly_sinh_cosh_series_basecase+ , arb_poly_sinh_cosh_series_basecase+ , _arb_poly_sinh_cosh_series_exponential+ , arb_poly_sinh_cosh_series_exponential+ , _arb_poly_sinh_cosh_series+ , arb_poly_sinh_cosh_series+ , _arb_poly_sinh_series+ , arb_poly_sinh_series+ , _arb_poly_cosh_series+ , arb_poly_cosh_series+ , _arb_poly_sinc_series+ , arb_poly_sinc_series+ , _arb_poly_sinc_pi_series+ , arb_poly_sinc_pi_series+ -- * Lambert W function+ , _arb_poly_lambertw_series+ , arb_poly_lambertw_series+ -- * Gamma function and factorials+ , _arb_poly_gamma_series+ , arb_poly_gamma_series+ , _arb_poly_rgamma_series+ , arb_poly_rgamma_series+ , _arb_poly_lgamma_series+ , arb_poly_lgamma_series+ , _arb_poly_digamma_series+ , arb_poly_digamma_series+ , _arb_poly_rising_ui_series+ , arb_poly_rising_ui_series+ -- * Zeta function+ , arb_poly_zeta_series+ , _arb_poly_riemann_siegel_theta_series+ , arb_poly_riemann_siegel_theta_series+ , _arb_poly_riemann_siegel_z_series+ , arb_poly_riemann_siegel_z_series+ -- * Root-finding+ , _arb_poly_root_bound_fujiwara+ , arb_poly_root_bound_fujiwara+ , _arb_poly_newton_convergence_factor+ , _arb_poly_newton_step+ , _arb_poly_newton_refine_root+ -- * Other special polynomials+ , _arb_poly_swinnerton_dyer_ui+ , arb_poly_swinnerton_dyer_ui+) where++-- Polynomials over the real numbers -------------------------------------------++#include <flint/arb.h>+#include <flint/acb_poly.h>++import System.IO.Unsafe ( unsafePerformIO )++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr )+import Foreign.Marshal ( free )++import Foreign.Storable++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpq.Poly++import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.Types++import Data.Number.Flint.Acb+import Data.Number.Flint.Acb.Types++-- arb_poly_t ------------------------------------------------------------------++-- | Createst a new `CArbPoly` structure encapsulated in `ArbPoly`.+{-# INLINE newArbPoly #-}+newArbPoly = do+ p <- mallocForeignPtr+ withForeignPtr p arb_poly_init+ addForeignPtrFinalizer p_arb_poly_clear p+ return $ ArbPoly p++newArbPolyFromFmpzPoly poly prec = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p -> do+ arb_poly_init p+ withFmpzPoly poly $ \poly -> arb_poly_set_fmpz_poly p poly prec+ addForeignPtrFinalizer p_arb_poly_clear p+ return $ ArbPoly p++newArbPolyFromFmpqPoly poly prec = do + p <- mallocForeignPtr+ withForeignPtr p $ \p -> do+ arb_poly_init p+ withFmpqPoly poly $ \poly -> arb_poly_set_fmpq_poly p poly prec+ addForeignPtrFinalizer p_arb_poly_clear p+ return $ ArbPoly p++-- | Use `ArbPoly` in f.+{-# INLINE withArbPoly #-}+withArbPoly (ArbPoly p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (ArbPoly p,)++-- | Use new `ArbPoly` ptr in f.+{-# INLINE withNewArbPoly #-}+withNewArbPoly f = do+ p <- newArbPoly+ withArbPoly p f++withNewArbPolyFromFmpzPoly poly prec f = do+ p <- newArbPolyFromFmpzPoly poly prec+ withArbPoly p f++withNewArbPolyFromFmpqPoly poly prec f = do+ p <- newArbPolyFromFmpqPoly poly prec+ withArbPoly p f++instance Storable CArbPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size arb_poly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment arb_poly_t}+ peek = error "CArbPoly.peek: Not defined"+ poke = error "CArbPoly.poke: Not defined"++-- Memory management -----------------------------------------------------------++-- | /arb_poly_init/ /poly/ +--+-- Initializes the polynomial for use, setting it to the zero polynomial.+foreign import ccall "arb_poly.h arb_poly_init"+ arb_poly_init :: Ptr CArbPoly -> IO ()++-- | /arb_poly_clear/ /poly/ +--+-- Clears the polynomial, deallocating all coefficients and the coefficient+-- array.+foreign import ccall "arb_poly.h arb_poly_clear"+ arb_poly_clear :: Ptr CArbPoly -> IO ()++foreign import ccall "arb_poly.h &arb_poly_clear"+ p_arb_poly_clear :: FunPtr (Ptr CArbPoly -> IO ())++-- | /arb_poly_fit_length/ /poly/ /len/ +--+-- Makes sure that the coefficient array of the polynomial contains at+-- least /len/ initialized coefficients.+foreign import ccall "arb_poly.h arb_poly_fit_length"+ arb_poly_fit_length :: Ptr CArbPoly -> CLong -> IO ()++-- | /_arb_poly_set_length/ /poly/ /len/ +--+-- Directly changes the length of the polynomial, without allocating or+-- deallocating coefficients. The value should not exceed the allocation+-- length.+foreign import ccall "arb_poly.h _arb_poly_set_length"+ _arb_poly_set_length :: Ptr CArbPoly -> CLong -> IO ()++-- | /_arb_poly_normalise/ /poly/ +--+-- Strips any trailing coefficients which are identical to zero.+foreign import ccall "arb_poly.h _arb_poly_normalise"+ _arb_poly_normalise :: Ptr CArbPoly -> IO ()++-- | /arb_poly_allocated_bytes/ /x/ +--+-- Returns the total number of bytes heap-allocated internally by this+-- object. The count excludes the size of the structure itself. Add+-- @sizeof(arb_poly_struct)@ to get the size of the object as a whole.+foreign import ccall "arb_poly.h arb_poly_allocated_bytes"+ arb_poly_allocated_bytes :: Ptr CArbPoly -> IO CLong++-- Basic manipulation ----------------------------------------------------------++-- | /arb_poly_length/ /poly/ +--+-- Returns the length of /poly/, i.e. zero if /poly/ is identically zero,+-- and otherwise one more than the index of the highest term that is not+-- identically zero.+foreign import ccall "arb_poly.h arb_poly_length"+ arb_poly_length :: Ptr CArbPoly -> IO CLong++-- | /arb_poly_degree/ /poly/ +--+-- Returns the degree of /poly/, defined as one less than its length. Note+-- that if one or several leading coefficients are balls containing zero,+-- this value can be larger than the true degree of the exact polynomial+-- represented by /poly/, so the return value of this function is+-- effectively an upper bound.+foreign import ccall "arb_poly.h arb_poly_degree"+ arb_poly_degree :: Ptr CArbPoly -> IO CLong++-- | /arb_poly_is_zero/ /poly/ +--+foreign import ccall "arb_poly.h arb_poly_is_zero"+ arb_poly_is_zero :: Ptr CArbPoly -> IO CInt++-- | /arb_poly_is_one/ /poly/ +--+foreign import ccall "arb_poly.h arb_poly_is_one"+ arb_poly_is_one :: Ptr CArbPoly -> IO CInt++-- | /arb_poly_is_x/ /poly/ +--+-- Returns 1 if /poly/ is exactly the polynomial 0, 1 or /x/ respectively.+-- Returns 0 otherwise.+foreign import ccall "arb_poly.h arb_poly_is_x"+ arb_poly_is_x :: Ptr CArbPoly -> IO CInt++-- | /arb_poly_zero/ /poly/ +--+foreign import ccall "arb_poly.h arb_poly_zero"+ arb_poly_zero :: Ptr CArbPoly -> IO ()++-- | /arb_poly_one/ /poly/ +--+-- Sets /poly/ to the constant 0 respectively 1.+foreign import ccall "arb_poly.h arb_poly_one"+ arb_poly_one :: Ptr CArbPoly -> IO ()++-- | /arb_poly_set/ /dest/ /src/ +--+-- Sets /dest/ to a copy of /src/.+foreign import ccall "arb_poly.h arb_poly_set"+ arb_poly_set :: Ptr CArbPoly -> Ptr CArbPoly -> IO ()++-- | /arb_poly_set_round/ /dest/ /src/ /prec/ +--+-- Sets /dest/ to a copy of /src/, rounded to /prec/ bits.+foreign import ccall "arb_poly.h arb_poly_set_round"+ arb_poly_set_round :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /arb_poly_set_trunc/ /dest/ /src/ /n/ +--+foreign import ccall "arb_poly.h arb_poly_set_trunc"+ arb_poly_set_trunc :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /arb_poly_set_trunc_round/ /dest/ /src/ /n/ /prec/ +--+-- Sets /dest/ to a copy of /src/, truncated to length /n/ and rounded to+-- /prec/ bits.+foreign import ccall "arb_poly.h arb_poly_set_trunc_round"+ arb_poly_set_trunc_round :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_poly_set_coeff_si/ /poly/ /n/ /c/ +--+foreign import ccall "arb_poly.h arb_poly_set_coeff_si"+ arb_poly_set_coeff_si :: Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_poly_set_coeff_arb/ /poly/ /n/ /c/ +--+-- Sets the coefficient with index /n/ in /poly/ to the value /c/. We+-- require that /n/ is nonnegative.+foreign import ccall "arb_poly.h arb_poly_set_coeff_arb"+ arb_poly_set_coeff_arb :: Ptr CArbPoly -> CLong -> Ptr CArb -> IO ()++-- | /arb_poly_get_coeff_arb/ /v/ /poly/ /n/ +--+-- Sets /v/ to the value of the coefficient with index /n/ in /poly/. We+-- require that /n/ is nonnegative.+foreign import ccall "arb_poly.h arb_poly_get_coeff_arb"+ arb_poly_get_coeff_arb :: Ptr CArb -> Ptr CArbPoly -> CLong -> IO ()++-- | /_arb_poly_shift_right/ /res/ /poly/ /len/ /n/ +--+foreign import ccall "arb_poly.h _arb_poly_shift_right"+ _arb_poly_shift_right :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_shift_right/ /res/ /poly/ /n/ +--+-- Sets /res/ to /poly/ divided by \(x^n\), throwing away the lower+-- coefficients. We require that /n/ is nonnegative.+foreign import ccall "arb_poly.h arb_poly_shift_right"+ arb_poly_shift_right :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /_arb_poly_shift_left/ /res/ /poly/ /len/ /n/ +--+foreign import ccall "arb_poly.h _arb_poly_shift_left"+ _arb_poly_shift_left :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_shift_left/ /res/ /poly/ /n/ +--+-- Sets /res/ to /poly/ multiplied by \(x^n\). We require that /n/ is+-- nonnegative.+foreign import ccall "arb_poly.h arb_poly_shift_left"+ arb_poly_shift_left :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /arb_poly_truncate/ /poly/ /n/ +--+-- Truncates /poly/ to have length at most /n/, i.e. degree strictly+-- smaller than /n/. We require that /n/ is nonnegative.+foreign import ccall "arb_poly.h arb_poly_truncate"+ arb_poly_truncate :: Ptr CArbPoly -> CLong -> IO ()++-- | /arb_poly_valuation/ /poly/ +--+-- Returns the degree of the lowest term that is not exactly zero in+-- /poly/. Returns -1 if /poly/ is the zero polynomial.+foreign import ccall "arb_poly.h arb_poly_valuation"+ arb_poly_valuation :: Ptr CArbPoly -> IO CLong++-- Conversions -----------------------------------------------------------------++-- | /arb_poly_set_fmpz_poly/ /poly/ /src/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_set_fmpz_poly"+ arb_poly_set_fmpz_poly :: Ptr CArbPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /arb_poly_set_fmpq_poly/ /poly/ /src/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_set_fmpq_poly"+ arb_poly_set_fmpq_poly :: Ptr CArbPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /arb_poly_set_si/ /poly/ /src/ +--+-- Sets /poly/ to /src/, rounding the coefficients to /prec/ bits.+foreign import ccall "arb_poly.h arb_poly_set_si"+ arb_poly_set_si :: Ptr CArbPoly -> CLong -> IO ()++-- Input and output ------------------------------------------------------------++foreign import ccall "arb_poly.h arb_poly_get_strd"+ arb_poly_get_strd :: Ptr CArbPoly -> CLong -> IO CString++-- | /arb_poly_printd/ /poly/ /digits/ +--+-- Prints the polynomial as an array of coefficients, printing each+-- coefficient using /arb_printd/.+arb_poly_printd :: Ptr CArbPoly -> CLong -> IO ()+arb_poly_printd poly digits = do+ printCStr (flip arb_poly_get_strd digits) poly+ return ()+ +-- | /arb_poly_fprintd/ /file/ /poly/ /digits/ +--+-- Prints the polynomial as an array of coefficients to the stream /file/,+-- printing each coefficient using /arb_fprintd/.+foreign import ccall "arb_poly.h arb_poly_fprintd"+ arb_poly_fprintd :: Ptr CFile -> Ptr CArbPoly -> CLong -> IO ()++-- Random generation -----------------------------------------------------------++-- | /arb_poly_randtest/ /poly/ /state/ /len/ /prec/ /mag_bits/ +--+-- Creates a random polynomial with length at most /len/.+foreign import ccall "arb_poly.h arb_poly_randtest"+ arb_poly_randtest :: Ptr CArbPoly -> Ptr CFRandState -> CLong -> CLong -> CLong -> IO ()++-- Comparisons -----------------------------------------------------------------++-- | /arb_poly_contains/ /poly1/ /poly2/ +--+foreign import ccall "arb_poly.h arb_poly_contains"+ arb_poly_contains :: Ptr CArbPoly -> Ptr CArbPoly -> IO CInt++-- | /arb_poly_contains_fmpz_poly/ /poly1/ /poly2/ +--+foreign import ccall "arb_poly.h arb_poly_contains_fmpz_poly"+ arb_poly_contains_fmpz_poly :: Ptr CArbPoly -> Ptr CFmpzPoly -> IO CInt++-- | /arb_poly_contains_fmpq_poly/ /poly1/ /poly2/ +--+-- Returns nonzero iff /poly1/ contains /poly2/.+foreign import ccall "arb_poly.h arb_poly_contains_fmpq_poly"+ arb_poly_contains_fmpq_poly :: Ptr CArbPoly -> Ptr CFmpqPoly -> IO CInt++-- | /arb_poly_equal/ /A/ /B/ +--+-- Returns nonzero iff /A/ and /B/ are equal as polynomial balls, i.e. all+-- coefficients have equal midpoint and radius.+foreign import ccall "arb_poly.h arb_poly_equal"+ arb_poly_equal :: Ptr CArbPoly -> Ptr CArbPoly -> IO CInt++-- | /_arb_poly_overlaps/ /poly1/ /len1/ /poly2/ /len2/ +--+foreign import ccall "arb_poly.h _arb_poly_overlaps"+ _arb_poly_overlaps :: Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO CInt++-- | /arb_poly_overlaps/ /poly1/ /poly2/ +--+-- Returns nonzero iff /poly1/ overlaps with /poly2/. The underscore+-- function requires that /len1/ ist at least as large as /len2/.+foreign import ccall "arb_poly.h arb_poly_overlaps"+ arb_poly_overlaps :: Ptr CArbPoly -> Ptr CArbPoly -> IO CInt++-- | /arb_poly_get_unique_fmpz_poly/ /z/ /x/ +--+-- If /x/ contains a unique integer polynomial, sets /z/ to that value and+-- returns nonzero. Otherwise (if /x/ represents no integers or more than+-- one integer), returns zero, possibly partially modifying /z/.+foreign import ccall "arb_poly.h arb_poly_get_unique_fmpz_poly"+ arb_poly_get_unique_fmpz_poly :: Ptr CFmpzPoly -> Ptr CArbPoly -> IO CInt++-- Bounds ----------------------------------------------------------------------++-- | /_arb_poly_majorant/ /res/ /poly/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_majorant"+ _arb_poly_majorant :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_majorant/ /res/ /poly/ /prec/ +--+-- Sets /res/ to an exact real polynomial whose coefficients are upper+-- bounds for the absolute values of the coefficients in /poly/, rounded to+-- /prec/ bits.+foreign import ccall "arb_poly.h arb_poly_majorant"+ arb_poly_majorant :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- | /_arb_poly_add/ /C/ /A/ /lenA/ /B/ /lenB/ /prec/ +--+-- Sets /{C, max(lenA, lenB)}/ to the sum of /{A, lenA}/ and /{B, lenB}/.+-- Allows aliasing of the input and output operands.+foreign import ccall "arb_poly.h _arb_poly_add"+ _arb_poly_add :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_add/ /C/ /A/ /B/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_add"+ arb_poly_add :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /arb_poly_add_si/ /C/ /A/ /B/ /prec/ +--+-- Sets /C/ to the sum of /A/ and /B/.+foreign import ccall "arb_poly.h arb_poly_add_si"+ arb_poly_add_si :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_sub/ /C/ /A/ /lenA/ /B/ /lenB/ /prec/ +--+-- Sets /{C, max(lenA, lenB)}/ to the difference of /{A, lenA}/ and /{B,+-- lenB}/. Allows aliasing of the input and output operands.+foreign import ccall "arb_poly.h _arb_poly_sub"+ _arb_poly_sub :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_sub/ /C/ /A/ /B/ /prec/ +--+-- Sets /C/ to the difference of /A/ and /B/.+foreign import ccall "arb_poly.h arb_poly_sub"+ arb_poly_sub :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /arb_poly_add_series/ /C/ /A/ /B/ /len/ /prec/ +--+-- Sets /C/ to the sum of /A/ and /B/, truncated to length /len/.+foreign import ccall "arb_poly.h arb_poly_add_series"+ arb_poly_add_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_poly_sub_series/ /C/ /A/ /B/ /len/ /prec/ +--+-- Sets /C/ to the difference of /A/ and /B/, truncated to length /len/.+foreign import ccall "arb_poly.h arb_poly_sub_series"+ arb_poly_sub_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_poly_neg/ /C/ /A/ +--+-- Sets /C/ to the negation of /A/.+foreign import ccall "arb_poly.h arb_poly_neg"+ arb_poly_neg :: Ptr CArbPoly -> Ptr CArbPoly -> IO ()++-- | /arb_poly_scalar_mul_2exp_si/ /C/ /A/ /c/ +--+-- Sets /C/ to /A/ multiplied by \(2^c\).+foreign import ccall "arb_poly.h arb_poly_scalar_mul_2exp_si"+ arb_poly_scalar_mul_2exp_si :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /arb_poly_scalar_mul/ /C/ /A/ /c/ /prec/ +--+-- Sets /C/ to /A/ multiplied by /c/.+foreign import ccall "arb_poly.h arb_poly_scalar_mul"+ arb_poly_scalar_mul :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArb -> CLong -> IO ()++-- | /arb_poly_scalar_div/ /C/ /A/ /c/ /prec/ +--+-- Sets /C/ to /A/ divided by /c/.+foreign import ccall "arb_poly.h arb_poly_scalar_div"+ arb_poly_scalar_div :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArb -> CLong -> IO ()++-- | /_arb_poly_mullow_classical/ /C/ /A/ /lenA/ /B/ /lenB/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_mullow_classical"+ _arb_poly_mullow_classical :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /_arb_poly_mullow_block/ /C/ /A/ /lenA/ /B/ /lenB/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_mullow_block"+ _arb_poly_mullow_block :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /_arb_poly_mullow/ /C/ /A/ /lenA/ /B/ /lenB/ /n/ /prec/ +--+-- Sets /{C, n}/ to the product of /{A, lenA}/ and /{B, lenB}/, truncated+-- to length /n/. The output is not allowed to be aliased with either of+-- the inputs. We require \(\mathrm{lenA} \ge \mathrm{lenB} > 0\),+-- \(n > 0\), \(\mathrm{lenA} + \mathrm{lenB} - 1 \ge n\).+-- +-- The /classical/ version uses a plain loop. This has good numerical+-- stability but gets slow for large /n/.+-- +-- The /block/ version decomposes the product into several subproducts+-- which are computed exactly over the integers.+-- +-- It first attempts to find an integer \(c\) such that \(A(2^c x)\) and+-- \(B(2^c x)\) have slowly varying coefficients, to reduce the number of+-- blocks.+-- +-- The scaling factor \(c\) is chosen in a quick, heuristic way by picking+-- the first and last nonzero terms in each polynomial. If the indices in+-- \(A\) are \(a_2, a_1\) and the log-2 magnitudes are \(e_2, e_1\), and+-- the indices in \(B\) are \(b_2, b_1\) with corresponding magnitudes+-- \(f_2, f_1\), then we compute \(c\) as the weighted arithmetic mean of+-- the slopes, rounded to the nearest integer:+-- +-- \[`\]+-- \[c = \left\lfloor+-- \frac{(e_2 - e_1) + (f_2 + f_1)}{(a_2 - a_1) + (b_2 - b_1)}+-- + \frac{1}{2}+-- \right \rfloor.\]+-- +-- This strategy is used because it is simple. It is not optimal in all+-- cases, but will typically give good performance when multiplying two+-- power series with a similar decay rate.+-- +-- The default algorithm chooses the /classical/ algorithm for short+-- polynomials and the /block/ algorithm for long polynomials.+-- +-- If the input pointers are identical (and the lengths are the same), they+-- are assumed to represent the same polynomial, and its square is+-- computed.+foreign import ccall "arb_poly.h _arb_poly_mullow"+ _arb_poly_mullow :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_mullow_classical/ /C/ /A/ /B/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_mullow_classical"+ arb_poly_mullow_classical :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- -- | /arb_poly_mullow_ztrunc/ /C/ /A/ /B/ /n/ /prec/ +-- --+-- foreign import ccall "arb_poly.h arb_poly_mullow_ztrunc"+-- arb_poly_mullow_ztrunc :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_poly_mullow_block/ /C/ /A/ /B/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_mullow_block"+ arb_poly_mullow_block :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /arb_poly_mullow/ /C/ /A/ /B/ /n/ /prec/ +--+-- Sets /C/ to the product of /A/ and /B/, truncated to length /n/. If the+-- same variable is passed for /A/ and /B/, sets /C/ to the square of /A/+-- truncated to length /n/.+foreign import ccall "arb_poly.h arb_poly_mullow"+ arb_poly_mullow :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_mul/ /C/ /A/ /lenA/ /B/ /lenB/ /prec/ +--+-- Sets /{C, lenA + lenB - 1}/ to the product of /{A, lenA}/ and /{B,+-- lenB}/. The output is not allowed to be aliased with either of the+-- inputs. We require \(\mathrm{lenA} \ge \mathrm{lenB} > 0\). This+-- function is implemented as a simple wrapper for @_arb_poly_mullow@.+-- +-- If the input pointers are identical (and the lengths are the same), they+-- are assumed to represent the same polynomial, and its square is+-- computed.+foreign import ccall "arb_poly.h _arb_poly_mul"+ _arb_poly_mul :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_mul/ /C/ /A/ /B/ /prec/ +--+-- Sets /C/ to the product of /A/ and /B/. If the same variable is passed+-- for /A/ and /B/, sets /C/ to the square of /A/.+foreign import ccall "arb_poly.h arb_poly_mul"+ arb_poly_mul :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /_arb_poly_inv_series/ /Q/ /A/ /Alen/ /len/ /prec/ +--+-- Sets /{Q, len}/ to the power series inverse of /{A, Alen}/. Uses Newton+-- iteration.+foreign import ccall "arb_poly.h _arb_poly_inv_series"+ _arb_poly_inv_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_inv_series/ /Q/ /A/ /n/ /prec/ +--+-- Sets /Q/ to the power series inverse of /A/, truncated to length /n/.+foreign import ccall "arb_poly.h arb_poly_inv_series"+ arb_poly_inv_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_div_series/ /Q/ /A/ /Alen/ /B/ /Blen/ /n/ /prec/ +--+-- Sets /{Q, n}/ to the power series quotient of /{A, Alen}/ by /{B,+-- Blen}/. Uses Newton iteration followed by multiplication.+foreign import ccall "arb_poly.h _arb_poly_div_series"+ _arb_poly_div_series :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_div_series/ /Q/ /A/ /B/ /n/ /prec/ +--+-- Sets /Q/ to the power series quotient /A/ divided by /B/, truncated to+-- length /n/.+foreign import ccall "arb_poly.h arb_poly_div_series"+ arb_poly_div_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_div/ /Q/ /A/ /lenA/ /B/ /lenB/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_div"+ _arb_poly_div :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_poly_rem/ /R/ /A/ /lenA/ /B/ /lenB/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_rem"+ _arb_poly_rem :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_poly_divrem/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_divrem"+ _arb_poly_divrem :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_divrem/ /Q/ /R/ /A/ /B/ /prec/ +--+-- Performs polynomial division with remainder, computing a quotient \(Q\)+-- and a remainder \(R\) such that \(A = BQ + R\). The implementation+-- reverses the inputs and performs power series division.+-- +-- If the leading coefficient of \(B\) contains zero (or if \(B\) is+-- identically zero), returns 0 indicating failure without modifying the+-- outputs. Otherwise returns nonzero.+foreign import ccall "arb_poly.h arb_poly_divrem"+ arb_poly_divrem :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO CInt++-- | /_arb_poly_div_root/ /Q/ /R/ /A/ /len/ /c/ /prec/ +--+-- Divides \(A\) by the polynomial \(x - c\), computing the quotient \(Q\)+-- as well as the remainder \(R = f(c)\).+foreign import ccall "arb_poly.h _arb_poly_div_root"+ _arb_poly_div_root :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++-- Composition -----------------------------------------------------------------++-- | /_arb_poly_taylor_shift/ /g/ /c/ /n/ /prec/ +foreign import ccall "arb_poly.h _arb_poly_taylor_shift"+ _arb_poly_taylor_shift :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()+-- | /arb_poly_taylor_shift/ /g/ /f/ /c/ /prec/ +--+-- Sets /g/ to the Taylor shift \(f(x+c)\). The underscore methods act+-- in-place on /g/ = /f/ which has length /n/.+foreign import ccall "arb_poly.h arb_poly_taylor_shift"+ arb_poly_taylor_shift :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArb -> CLong -> IO ()++-- | /_arb_poly_compose/ /res/ /poly1/ /len1/ /poly2/ /len2/ /prec/ +foreign import ccall "arb_poly.h _arb_poly_compose"+ _arb_poly_compose :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()+-- | /arb_poly_compose/ /res/ /poly1/ /poly2/ /prec/ +--+-- Sets /res/ to the composition \(h(x) = f(g(x))\) where \(f\) is given by+-- /poly1/ and \(g\) is given by /poly2/. The underscore method does not+-- support aliasing of the output with either input polynomial.+foreign import ccall "arb_poly.h arb_poly_compose"+ arb_poly_compose :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /_arb_poly_compose_series/ /res/ /poly1/ /len1/ /poly2/ /len2/ /n/ /prec/ +foreign import ccall "arb_poly.h _arb_poly_compose_series"+ _arb_poly_compose_series :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_poly_compose_series/ /res/ /poly1/ /poly2/ /n/ /prec/ +--+-- Sets /res/ to the power series composition \(h(x) = f(g(x))\) truncated+-- to order \(O(x^n)\) where \(f\) is given by /poly1/ and \(g\) is given+-- by /poly2/. Wraps @_gr_poly_compose_series@ which chooses automatically+-- between various algorithms.+-- +-- We require that the constant term in \(g(x)\) is exactly zero. The+-- underscore method does not support aliasing of the output with either+-- input polynomial.+foreign import ccall "arb_poly.h arb_poly_compose_series"+ arb_poly_compose_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_revert_series_lagrange/ /h/ /f/ /flen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_revert_series_lagrange"+ _arb_poly_revert_series_lagrange :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_revert_series_lagrange/ /h/ /f/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_revert_series_lagrange"+ arb_poly_revert_series_lagrange :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_revert_series_newton/ /h/ /f/ /flen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_revert_series_newton"+ _arb_poly_revert_series_newton :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_revert_series_newton/ /h/ /f/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_revert_series_newton"+ arb_poly_revert_series_newton :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_revert_series_lagrange_fast/ /h/ /f/ /flen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_revert_series_lagrange_fast"+ _arb_poly_revert_series_lagrange_fast :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_revert_series_lagrange_fast/ /h/ /f/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_revert_series_lagrange_fast"+ arb_poly_revert_series_lagrange_fast :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_revert_series/ /h/ /f/ /flen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_revert_series"+ _arb_poly_revert_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_revert_series/ /h/ /f/ /n/ /prec/ +--+-- Sets \(h\) to the power series reversion of \(f\), i.e. the expansion of+-- the compositional inverse function \(f^{-1}(x)\), truncated to order+-- \(O(x^n)\), using respectively Lagrange inversion, Newton iteration,+-- fast Lagrange inversion, and a default algorithm choice.+-- +-- We require that the constant term in \(f\) is exactly zero and that the+-- linear term is nonzero. The underscore methods assume that /flen/ is at+-- least 2, and do not support aliasing.+foreign import ccall "arb_poly.h arb_poly_revert_series"+ arb_poly_revert_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- Evaluation ------------------------------------------------------------------++-- | /_arb_poly_evaluate_horner/ /y/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate_horner"+ _arb_poly_evaluate_horner :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++-- | /arb_poly_evaluate_horner/ /y/ /f/ /x/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_evaluate_horner"+ arb_poly_evaluate_horner :: Ptr CArb -> Ptr CArbPoly -> Ptr CArb -> CLong -> IO ()++-- | /_arb_poly_evaluate_rectangular/ /y/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate_rectangular"+ _arb_poly_evaluate_rectangular :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++-- | /arb_poly_evaluate_rectangular/ /y/ /f/ /x/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_evaluate_rectangular"+ arb_poly_evaluate_rectangular :: Ptr CArb -> Ptr CArbPoly -> Ptr CArb -> CLong -> IO ()++-- | /_arb_poly_evaluate/ /y/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate"+ _arb_poly_evaluate :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++-- | /arb_poly_evaluate/ /y/ /f/ /x/ /prec/ +--+-- Sets \(y = f(x)\), evaluated respectively using Horner\'s rule,+-- rectangular splitting, and an automatic algorithm choice.+foreign import ccall "arb_poly.h arb_poly_evaluate"+ arb_poly_evaluate :: Ptr CArb -> Ptr CArbPoly -> Ptr CArb -> CLong -> IO ()++-- | /_arb_poly_evaluate_acb_horner/ /y/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate_acb_horner"+ _arb_poly_evaluate_acb_horner :: Ptr CAcb -> Ptr CArb -> CLong -> Ptr CAcb -> CLong -> IO ()++-- | /arb_poly_evaluate_acb_horner/ /y/ /f/ /x/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_evaluate_acb_horner"+ arb_poly_evaluate_acb_horner :: Ptr CAcb -> Ptr CArbPoly -> Ptr CAcb -> CLong -> IO ()++-- | /_arb_poly_evaluate_acb_rectangular/ /y/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate_acb_rectangular"+ _arb_poly_evaluate_acb_rectangular :: Ptr CAcb -> Ptr CArb -> CLong -> Ptr CAcb -> CLong -> IO ()++-- | /arb_poly_evaluate_acb_rectangular/ /y/ /f/ /x/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_evaluate_acb_rectangular"+ arb_poly_evaluate_acb_rectangular :: Ptr CAcb -> Ptr CArbPoly -> Ptr CAcb -> CLong -> IO ()++-- | /_arb_poly_evaluate_acb/ /y/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate_acb"+ _arb_poly_evaluate_acb :: Ptr CAcb -> Ptr CArb -> CLong -> Ptr CAcb -> CLong -> IO ()++-- | /arb_poly_evaluate_acb/ /y/ /f/ /x/ /prec/ +--+-- Sets \(y = f(x)\) where \(x\) is a complex number, evaluating the+-- polynomial respectively using Horner\'s rule, rectangular splitting, and+-- an automatic algorithm choice.+foreign import ccall "arb_poly.h arb_poly_evaluate_acb"+ arb_poly_evaluate_acb :: Ptr CAcb -> Ptr CArbPoly -> Ptr CAcb -> CLong -> IO ()++-- | /_arb_poly_evaluate2_horner/ /y/ /z/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate2_horner"+ _arb_poly_evaluate2_horner :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++-- | /arb_poly_evaluate2_horner/ /y/ /z/ /f/ /x/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_evaluate2_horner"+ arb_poly_evaluate2_horner :: Ptr CArb -> Ptr CArb -> Ptr CArbPoly -> Ptr CArb -> CLong -> IO ()++-- | /_arb_poly_evaluate2_rectangular/ /y/ /z/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate2_rectangular"+ _arb_poly_evaluate2_rectangular :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++-- | /arb_poly_evaluate2_rectangular/ /y/ /z/ /f/ /x/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_evaluate2_rectangular"+ arb_poly_evaluate2_rectangular :: Ptr CArb -> Ptr CArb -> Ptr CArbPoly -> Ptr CArb -> CLong -> IO ()++-- | /_arb_poly_evaluate2/ /y/ /z/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate2"+ _arb_poly_evaluate2 :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++-- | /arb_poly_evaluate2/ /y/ /z/ /f/ /x/ /prec/ +--+-- Sets \(y = f(x), z = f'(x)\), evaluated respectively using Horner\'s+-- rule, rectangular splitting, and an automatic algorithm choice.+-- +-- When Horner\'s rule is used, the only advantage of evaluating the+-- function and its derivative simultaneously is that one does not have to+-- generate the derivative polynomial explicitly. With the rectangular+-- splitting algorithm, the powers can be reused, making simultaneous+-- evaluation slightly faster.+foreign import ccall "arb_poly.h arb_poly_evaluate2"+ arb_poly_evaluate2 :: Ptr CArb -> Ptr CArb -> Ptr CArbPoly -> Ptr CArb -> CLong -> IO ()++-- | /_arb_poly_evaluate2_acb_horner/ /y/ /z/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate2_acb_horner"+ _arb_poly_evaluate2_acb_horner :: Ptr CAcb -> Ptr CAcb -> Ptr CArb -> CLong -> Ptr CAcb -> CLong -> IO ()++-- | /arb_poly_evaluate2_acb_horner/ /y/ /z/ /f/ /x/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_evaluate2_acb_horner"+ arb_poly_evaluate2_acb_horner :: Ptr CAcb -> Ptr CAcb -> Ptr CArbPoly -> Ptr CAcb -> CLong -> IO ()++-- | /_arb_poly_evaluate2_acb_rectangular/ /y/ /z/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate2_acb_rectangular"+ _arb_poly_evaluate2_acb_rectangular :: Ptr CAcb -> Ptr CAcb -> Ptr CArb -> CLong -> Ptr CAcb -> CLong -> IO ()++-- | /arb_poly_evaluate2_acb_rectangular/ /y/ /z/ /f/ /x/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_evaluate2_acb_rectangular"+ arb_poly_evaluate2_acb_rectangular :: Ptr CAcb -> Ptr CAcb -> Ptr CArbPoly -> Ptr CAcb -> CLong -> IO ()++-- | /_arb_poly_evaluate2_acb/ /y/ /z/ /f/ /len/ /x/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate2_acb"+ _arb_poly_evaluate2_acb :: Ptr CAcb -> Ptr CAcb -> Ptr CArb -> CLong -> Ptr CAcb -> CLong -> IO ()++-- | /arb_poly_evaluate2_acb/ /y/ /z/ /f/ /x/ /prec/ +--+-- Sets \(y = f(x), z = f'(x)\), evaluated respectively using Horner\'s+-- rule, rectangular splitting, and an automatic algorithm choice.+foreign import ccall "arb_poly.h arb_poly_evaluate2_acb"+ arb_poly_evaluate2_acb :: Ptr CAcb -> Ptr CAcb -> Ptr CArbPoly -> Ptr CAcb -> CLong -> IO ()++-- Product trees ---------------------------------------------------------------++-- | /_arb_poly_product_roots/ /poly/ /xs/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_product_roots"+ _arb_poly_product_roots :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_product_roots/ /poly/ /xs/ /n/ /prec/ +--+-- Generates the polynomial \((x-x_0)(x-x_1)\cdots(x-x_{n-1})\).+foreign import ccall "arb_poly.h arb_poly_product_roots"+ arb_poly_product_roots :: Ptr CArbPoly -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_poly_product_roots_complex/ /poly/ /r/ /rn/ /c/ /cn/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_product_roots_complex"+ _arb_poly_product_roots_complex :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /arb_poly_product_roots_complex/ /poly/ /r/ /rn/ /c/ /cn/ /prec/ +--+-- Generates the polynomial+-- +-- \[`\]+-- \[\left(\prod_{i=0}^{rn-1} (x-r_i)\right) \left(\prod_{i=0}^{cn-1} (x-c_i)(x-\bar{c_i})\right)\]+-- +-- having /rn/ real roots given by the array /r/ and having \(2cn\) complex+-- roots in conjugate pairs given by the length-/cn/ array /c/. Either /rn/+-- or /cn/ or both may be zero.+-- +-- Note that only one representative from each complex conjugate pair is+-- supplied (unless a pair is supposed to be repeated with higher+-- multiplicity). To construct a polynomial from complex roots where the+-- conjugate pairs have not been distinguished, use+-- @acb_poly_product_roots@ instead.+foreign import ccall "arb_poly.h arb_poly_product_roots_complex"+ arb_poly_product_roots_complex :: Ptr CArbPoly -> Ptr CArb -> CLong -> Ptr CAcb -> CLong -> CLong -> IO ()++-- | /_arb_poly_tree_alloc/ /len/ +--+-- Returns an initialized data structured capable of representing a+-- remainder tree (product tree) of /len/ roots.+foreign import ccall "arb_poly.h _arb_poly_tree_alloc"+ _arb_poly_tree_alloc :: CLong -> IO (Ptr (Ptr CArb))++-- | /_arb_poly_tree_free/ /tree/ /len/ +--+-- Deallocates a tree structure as allocated using /_arb_poly_tree_alloc/.+foreign import ccall "arb_poly.h _arb_poly_tree_free"+ _arb_poly_tree_free :: Ptr (Ptr CArb) -> CLong -> IO ()++-- | /_arb_poly_tree_build/ /tree/ /roots/ /len/ /prec/ +--+-- Constructs a product tree from a given array of /len/ roots. The tree+-- structure must be pre-allocated to the specified length using+-- @_arb_poly_tree_alloc@.+foreign import ccall "arb_poly.h _arb_poly_tree_build"+ _arb_poly_tree_build :: Ptr (Ptr CArb) -> Ptr CArb -> CLong -> CLong -> IO ()++-- Multipoint evaluation -------------------------------------------------------++-- | /_arb_poly_evaluate_vec_iter/ /ys/ /poly/ /plen/ /xs/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate_vec_iter"+ _arb_poly_evaluate_vec_iter :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_evaluate_vec_iter/ /ys/ /poly/ /xs/ /n/ /prec/ +--+-- Evaluates the polynomial simultaneously at /n/ given points, calling+-- @_arb_poly_evaluate@ repeatedly.+foreign import ccall "arb_poly.h arb_poly_evaluate_vec_iter"+ arb_poly_evaluate_vec_iter :: Ptr CArb -> Ptr CArbPoly -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_poly_evaluate_vec_fast_precomp/ /vs/ /poly/ /plen/ /tree/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate_vec_fast_precomp"+ _arb_poly_evaluate_vec_fast_precomp :: Ptr CArb -> Ptr CArb -> CLong -> Ptr (Ptr CArb) -> CLong -> CLong -> IO ()++-- | /_arb_poly_evaluate_vec_fast/ /ys/ /poly/ /plen/ /xs/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_evaluate_vec_fast"+ _arb_poly_evaluate_vec_fast :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_evaluate_vec_fast/ /ys/ /poly/ /xs/ /n/ /prec/ +--+-- Evaluates the polynomial simultaneously at /n/ given points, using fast+-- multipoint evaluation.+foreign import ccall "arb_poly.h arb_poly_evaluate_vec_fast"+ arb_poly_evaluate_vec_fast :: Ptr CArb -> Ptr CArbPoly -> Ptr CArb -> CLong -> CLong -> IO ()++-- Interpolation ---------------------------------------------------------------++-- | /_arb_poly_interpolate_newton/ /poly/ /xs/ /ys/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_interpolate_newton"+ _arb_poly_interpolate_newton :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_interpolate_newton/ /poly/ /xs/ /ys/ /n/ /prec/ +--+-- Recovers the unique polynomial of length at most /n/ that interpolates+-- the given /x/ and /y/ values. This implementation first interpolates in+-- the Newton basis and then converts back to the monomial basis.+foreign import ccall "arb_poly.h arb_poly_interpolate_newton"+ arb_poly_interpolate_newton :: Ptr CArbPoly -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_poly_interpolate_barycentric/ /poly/ /xs/ /ys/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_interpolate_barycentric"+ _arb_poly_interpolate_barycentric :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_interpolate_barycentric/ /poly/ /xs/ /ys/ /n/ /prec/ +--+-- Recovers the unique polynomial of length at most /n/ that interpolates+-- the given /x/ and /y/ values. This implementation uses the barycentric+-- form of Lagrange interpolation.+foreign import ccall "arb_poly.h arb_poly_interpolate_barycentric"+ arb_poly_interpolate_barycentric :: Ptr CArbPoly -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_poly_interpolation_weights/ /w/ /tree/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_interpolation_weights"+ _arb_poly_interpolation_weights :: Ptr CArb -> Ptr (Ptr CArb) -> CLong -> CLong -> IO ()++-- | /_arb_poly_interpolate_fast_precomp/ /poly/ /ys/ /tree/ /weights/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_interpolate_fast_precomp"+ _arb_poly_interpolate_fast_precomp :: Ptr CArb -> Ptr CArb -> Ptr (Ptr CArb) -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_poly_interpolate_fast/ /poly/ /xs/ /ys/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_interpolate_fast"+ _arb_poly_interpolate_fast :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_interpolate_fast/ /poly/ /xs/ /ys/ /n/ /prec/ +--+-- Recovers the unique polynomial of length at most /n/ that interpolates+-- the given /x/ and /y/ values, using fast Lagrange interpolation. The+-- precomp function takes a precomputed product tree over the /x/ values+-- and a vector of interpolation weights as additional inputs.+foreign import ccall "arb_poly.h arb_poly_interpolate_fast"+ arb_poly_interpolate_fast :: Ptr CArbPoly -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- Differentiation -------------------------------------------------------------++-- | /_arb_poly_derivative/ /res/ /poly/ /len/ /prec/ +--+-- Sets /{res, len - 1}/ to the derivative of /{poly, len}/. Allows+-- aliasing of the input and output.+foreign import ccall "arb_poly.h _arb_poly_derivative"+ _arb_poly_derivative :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_derivative/ /res/ /poly/ /prec/ +--+-- Sets /res/ to the derivative of /poly/.+foreign import ccall "arb_poly.h arb_poly_derivative"+ arb_poly_derivative :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /_arb_poly_nth_derivative/ /res/ /poly/ /n/ /len/ /prec/ +--+-- Sets /{res, len - n}/ to the nth derivative of /{poly, len}/. Does+-- nothing if /len \<= n/. Allows aliasing of the input and output.+foreign import ccall "arb_poly.h _arb_poly_nth_derivative"+ _arb_poly_nth_derivative :: Ptr CArb -> Ptr CArb -> CULong -> CLong -> CLong -> IO ()++-- | /arb_poly_nth_derivative/ /res/ /poly/ /prec/ +--+-- Sets /res/ to the nth derivative of /poly/.+foreign import ccall "arb_poly.h arb_poly_nth_derivative"+ arb_poly_nth_derivative :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /_arb_poly_integral/ /res/ /poly/ /len/ /prec/ +--+-- Sets /{res, len}/ to the integral of /{poly, len - 1}/. Allows aliasing+-- of the input and output.+foreign import ccall "arb_poly.h _arb_poly_integral"+ _arb_poly_integral :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_integral/ /res/ /poly/ /prec/ +--+-- Sets /res/ to the integral of /poly/.+foreign import ccall "arb_poly.h arb_poly_integral"+ arb_poly_integral :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- Transforms ------------------------------------------------------------------++-- | /_arb_poly_borel_transform/ /res/ /poly/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_borel_transform"+ _arb_poly_borel_transform :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_borel_transform/ /res/ /poly/ /prec/ +--+-- Computes the Borel transform of the input polynomial, mapping+-- \(\sum_k a_k x^k\) to \(\sum_k (a_k / k!) x^k\). The underscore method+-- allows aliasing.+foreign import ccall "arb_poly.h arb_poly_borel_transform"+ arb_poly_borel_transform :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /_arb_poly_inv_borel_transform/ /res/ /poly/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_inv_borel_transform"+ _arb_poly_inv_borel_transform :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_inv_borel_transform/ /res/ /poly/ /prec/ +--+-- Computes the inverse Borel transform of the input polynomial, mapping+-- \(\sum_k a_k x^k\) to \(\sum_k a_k k! x^k\). The underscore method+-- allows aliasing.+foreign import ccall "arb_poly.h arb_poly_inv_borel_transform"+ arb_poly_inv_borel_transform :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- | /_arb_poly_binomial_transform_basecase/ /b/ /a/ /alen/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_binomial_transform_basecase"+ _arb_poly_binomial_transform_basecase :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_binomial_transform_basecase/ /b/ /a/ /len/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_binomial_transform_basecase"+ arb_poly_binomial_transform_basecase :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_binomial_transform_convolution/ /b/ /a/ /alen/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_binomial_transform_convolution"+ _arb_poly_binomial_transform_convolution :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_binomial_transform_convolution/ /b/ /a/ /len/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_binomial_transform_convolution"+ arb_poly_binomial_transform_convolution :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_binomial_transform/ /b/ /a/ /alen/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_binomial_transform"+ _arb_poly_binomial_transform :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_binomial_transform/ /b/ /a/ /len/ /prec/ +--+-- Computes the binomial transform of the input polynomial, truncating the+-- output to length /len/. The binomial transform maps the coefficients+-- \(a_k\) in the input polynomial to the coefficients \(b_k\) in the+-- output polynomial via \(b_n = \sum_{k=0}^n (-1)^k {n \choose k} a_k\).+-- The binomial transform is equivalent to the power series composition+-- \(f(x) \to (1-x)^{-1} f(x/(x-1))\), and is its own inverse.+-- +-- The /basecase/ version evaluates coefficients one by one from the+-- definition, generating the binomial coefficients by a recurrence+-- relation.+-- +-- The /convolution/ version uses the identity+-- \(T(f(x)) = B^{-1}(e^x B(f(-x)))\) where \(T\) denotes the binomial+-- transform operator and \(B\) denotes the Borel transform operator. This+-- only costs a single polynomial multiplication, plus some scalar+-- operations.+-- +-- The default version automatically chooses an algorithm.+-- +-- The underscore methods do not support aliasing, and assume that the+-- lengths are nonzero.+foreign import ccall "arb_poly.h arb_poly_binomial_transform"+ arb_poly_binomial_transform :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_graeffe_transform/ /b/ /a/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_graeffe_transform"+ _arb_poly_graeffe_transform :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_graeffe_transform/ /b/ /a/ /prec/ +--+-- Computes the Graeffe transform of input polynomial.+-- +-- The Graeffe transform \(G\) of a polynomial \(P\) is defined through the+-- equation \(G(x^2) = \pm P(x)P(-x)\). The sign is given by \((-1)^d\),+-- where \(d = deg(P)\). The Graeffe transform has the property that its+-- roots are exactly the squares of the roots of P.+-- +-- The underscore method assumes that /a/ and /b/ are initialized, /a/ is+-- of length /len/, and /b/ is of length at least /len/. Both methods allow+-- aliasing.+foreign import ccall "arb_poly.h arb_poly_graeffe_transform"+ arb_poly_graeffe_transform :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> IO ()++-- Powers and elementary functions ---------------------------------------------++-- | /_arb_poly_pow_ui_trunc_binexp/ /res/ /f/ /flen/ /exp/ /len/ /prec/ +--+-- Sets /{res, len}/ to /{f, flen}/ raised to the power /exp/, truncated to+-- length /len/. Requires that /len/ is no longer than the length of the+-- power as computed without truncation (i.e. no zero-padding is+-- performed). Does not support aliasing of the input and output, and+-- requires that /flen/ and /len/ are positive. Uses binary exponentiation.+foreign import ccall "arb_poly.h _arb_poly_pow_ui_trunc_binexp"+ _arb_poly_pow_ui_trunc_binexp :: Ptr CArb -> Ptr CArb -> CLong -> CULong -> CLong -> CLong -> IO ()++-- | /arb_poly_pow_ui_trunc_binexp/ /res/ /poly/ /exp/ /len/ /prec/ +--+-- Sets /res/ to /poly/ raised to the power /exp/, truncated to length+-- /len/. Uses binary exponentiation.+foreign import ccall "arb_poly.h arb_poly_pow_ui_trunc_binexp"+ arb_poly_pow_ui_trunc_binexp :: Ptr CArbPoly -> Ptr CArbPoly -> CULong -> CLong -> CLong -> IO ()++-- | /_arb_poly_pow_ui/ /res/ /f/ /flen/ /exp/ /prec/ +--+-- Sets /res/ to /{f, flen}/ raised to the power /exp/. Does not support+-- aliasing of the input and output, and requires that /flen/ is positive.+foreign import ccall "arb_poly.h _arb_poly_pow_ui"+ _arb_poly_pow_ui :: Ptr CArb -> Ptr CArb -> CLong -> CULong -> CLong -> IO ()++-- | /arb_poly_pow_ui/ /res/ /poly/ /exp/ /prec/ +--+-- Sets /res/ to /poly/ raised to the power /exp/.+foreign import ccall "arb_poly.h arb_poly_pow_ui"+ arb_poly_pow_ui :: Ptr CArbPoly -> Ptr CArbPoly -> CULong -> CLong -> IO ()++-- | /_arb_poly_pow_series/ /h/ /f/ /flen/ /g/ /glen/ /len/ /prec/ +--+-- Sets /{h, len}/ to the power series+-- \(f(x)^{g(x)} = \exp(g(x) \log f(x))\) truncated to length /len/. This+-- function detects special cases such as /g/ being an exact small integer+-- or \(\pm 1/2\), and computes such powers more efficiently. This function+-- does not support aliasing of the output with either of the input+-- operands. It requires that all lengths are positive, and assumes that+-- /flen/ and /glen/ do not exceed /len/.+foreign import ccall "arb_poly.h _arb_poly_pow_series"+ _arb_poly_pow_series :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_pow_series/ /h/ /f/ /g/ /len/ /prec/ +--+-- Sets /h/ to the power series \(f(x)^{g(x)} = \exp(g(x) \log f(x))\)+-- truncated to length /len/. This function detects special cases such as+-- /g/ being an exact small integer or \(\pm 1/2\), and computes such+-- powers more efficiently.+foreign import ccall "arb_poly.h arb_poly_pow_series"+ arb_poly_pow_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_pow_arb_series/ /h/ /f/ /flen/ /g/ /len/ /prec/ +--+-- Sets /{h, len}/ to the power series \(f(x)^g = \exp(g \log f(x))\)+-- truncated to length /len/. This function detects special cases such as+-- /g/ being an exact small integer or \(\pm 1/2\), and computes such+-- powers more efficiently. This function does not support aliasing of the+-- output with either of the input operands. It requires that all lengths+-- are positive, and assumes that /flen/ does not exceed /len/.+foreign import ccall "arb_poly.h _arb_poly_pow_arb_series"+ _arb_poly_pow_arb_series :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /arb_poly_pow_arb_series/ /h/ /f/ /g/ /len/ /prec/ +--+-- Sets /h/ to the power series \(f(x)^g = \exp(g \log f(x))\) truncated to+-- length /len/.+foreign import ccall "arb_poly.h arb_poly_pow_arb_series"+ arb_poly_pow_arb_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArb -> CLong -> CLong -> IO ()++-- | /_arb_poly_sqrt_series/ /g/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_sqrt_series"+ _arb_poly_sqrt_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_sqrt_series/ /g/ /h/ /n/ /prec/ +--+-- Sets /g/ to the power series square root of /h/, truncated to length+-- /n/. Uses division-free Newton iteration for the reciprocal square root,+-- followed by a multiplication.+-- +-- The underscore method does not support aliasing of the input and output+-- arrays. It requires that /hlen/ and /n/ are greater than zero.+foreign import ccall "arb_poly.h arb_poly_sqrt_series"+ arb_poly_sqrt_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_rsqrt_series/ /g/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_rsqrt_series"+ _arb_poly_rsqrt_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_rsqrt_series/ /g/ /h/ /n/ /prec/ +--+-- Sets /g/ to the reciprocal power series square root of /h/, truncated to+-- length /n/. Uses division-free Newton iteration.+-- +-- The underscore method does not support aliasing of the input and output+-- arrays. It requires that /hlen/ and /n/ are greater than zero.+foreign import ccall "arb_poly.h arb_poly_rsqrt_series"+ arb_poly_rsqrt_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_log_series/ /res/ /f/ /flen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_log_series"+ _arb_poly_log_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_log_series/ /res/ /f/ /n/ /prec/ +--+-- Sets /res/ to the power series logarithm of /f/, truncated to length+-- /n/. Uses the formula \(\log(f(x)) = \int f'(x) / f(x) dx\), adding the+-- logarithm of the constant term in /f/ as the constant of integration.+-- +-- The underscore method supports aliasing of the input and output arrays.+-- It requires that /flen/ and /n/ are greater than zero.+foreign import ccall "arb_poly.h arb_poly_log_series"+ arb_poly_log_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_log1p_series/ /res/ /f/ /flen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_log1p_series"+ _arb_poly_log1p_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_log1p_series/ /res/ /f/ /n/ /prec/ +--+-- Computes the power series \(\log(1+f)\), with better accuracy when the+-- constant term of /f/ is small.+foreign import ccall "arb_poly.h arb_poly_log1p_series"+ arb_poly_log1p_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_atan_series/ /res/ /f/ /flen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_atan_series"+ _arb_poly_atan_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_atan_series/ /res/ /f/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_atan_series"+ arb_poly_atan_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_asin_series/ /res/ /f/ /flen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_asin_series"+ _arb_poly_asin_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_asin_series/ /res/ /f/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_asin_series"+ arb_poly_asin_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_acos_series/ /res/ /f/ /flen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_acos_series"+ _arb_poly_acos_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_acos_series/ /res/ /f/ /n/ /prec/ +--+-- Sets /res/ respectively to the power series inverse tangent, inverse+-- sine and inverse cosine of /f/, truncated to length /n/.+-- +-- Uses the formulas+-- +-- \[`\]+-- \[\tan^{-1}(f(x)) = \int f'(x) / (1+f(x)^2) dx,\]+-- \[\sin^{-1}(f(x)) = \int f'(x) / (1-f(x)^2)^{1/2} dx,\]+-- \[\cos^{-1}(f(x)) = -\int f'(x) / (1-f(x)^2)^{1/2} dx,\]+-- +-- adding the inverse function of the constant term in /f/ as the constant+-- of integration.+-- +-- The underscore methods supports aliasing of the input and output arrays.+-- They require that /flen/ and /n/ are greater than zero.+foreign import ccall "arb_poly.h arb_poly_acos_series"+ arb_poly_acos_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_exp_series_basecase/ /f/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_exp_series_basecase"+ _arb_poly_exp_series_basecase :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_exp_series_basecase/ /f/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_exp_series_basecase"+ arb_poly_exp_series_basecase :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_exp_series/ /f/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_exp_series"+ _arb_poly_exp_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_exp_series/ /f/ /h/ /n/ /prec/ +--+-- Sets \(f\) to the power series exponential of \(h\), truncated to length+-- \(n\).+-- +-- The basecase version uses a simple recurrence for the coefficients,+-- requiring \(O(nm)\) operations where \(m\) is the length of \(h\).+-- +-- The main implementation uses Newton iteration, starting from a small+-- number of terms given by the basecase algorithm. The complexity is+-- \(O(M(n))\). Redundant operations in the Newton iteration are avoided by+-- using the scheme described in < [HZ2004]>.+-- +-- The underscore methods support aliasing and allow the input to be+-- shorter than the output, but require the lengths to be nonzero.+foreign import ccall "arb_poly.h arb_poly_exp_series"+ arb_poly_exp_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_sin_cos_series/ /s/ /c/ /h/ /hlen/ /n/ /prec/ +foreign import ccall "arb_poly.h _arb_poly_sin_cos_series"+ _arb_poly_sin_cos_series :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()+-- | /arb_poly_sin_cos_series/ /s/ /c/ /h/ /n/ /prec/ +--+-- Sets /s/ and /c/ to the power series sine and cosine of /h/, computed+-- simultaneously. The underscore method supports aliasing and requires the+-- lengths to be nonzero.+foreign import ccall "arb_poly.h arb_poly_sin_cos_series"+ arb_poly_sin_cos_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_sin_series/ /s/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_sin_series"+ _arb_poly_sin_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_sin_series/ /s/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_sin_series"+ arb_poly_sin_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_cos_series/ /c/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_cos_series"+ _arb_poly_cos_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_cos_series/ /c/ /h/ /n/ /prec/ +--+-- Respectively evaluates the power series sine or cosine. These functions+-- simply wrap @_arb_poly_sin_cos_series@. The underscore methods support+-- aliasing and require the lengths to be nonzero.+foreign import ccall "arb_poly.h arb_poly_cos_series"+ arb_poly_cos_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_tan_series/ /g/ /h/ /hlen/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_tan_series"+ _arb_poly_tan_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_tan_series/ /g/ /h/ /n/ /prec/ +--+-- Sets /g/ to the power series tangent of /h/.+-- +-- For small /n/ takes the quotient of the sine and cosine as computed+-- using the basecase algorithm. For large /n/, uses Newton iteration to+-- invert the inverse tangent series. The complexity is \(O(M(n))\).+-- +-- The underscore version does not support aliasing, and requires the+-- lengths to be nonzero.+foreign import ccall "arb_poly.h arb_poly_tan_series"+ arb_poly_tan_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_sin_cos_pi_series/ /s/ /c/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_sin_cos_pi_series"+ _arb_poly_sin_cos_pi_series :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_sin_cos_pi_series/ /s/ /c/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_sin_cos_pi_series"+ arb_poly_sin_cos_pi_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_sin_pi_series/ /s/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_sin_pi_series"+ _arb_poly_sin_pi_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_sin_pi_series/ /s/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_sin_pi_series"+ arb_poly_sin_pi_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_cos_pi_series/ /c/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_cos_pi_series"+ _arb_poly_cos_pi_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_cos_pi_series/ /c/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_cos_pi_series"+ arb_poly_cos_pi_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_cot_pi_series/ /c/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_cot_pi_series"+ _arb_poly_cot_pi_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_cot_pi_series/ /c/ /h/ /n/ /prec/ +--+-- Compute the respective trigonometric functions of the input multiplied+-- by \(\pi\).+foreign import ccall "arb_poly.h arb_poly_cot_pi_series"+ arb_poly_cot_pi_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_sinh_cosh_series_basecase/ /s/ /c/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_sinh_cosh_series_basecase"+ _arb_poly_sinh_cosh_series_basecase :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_sinh_cosh_series_basecase/ /s/ /c/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_sinh_cosh_series_basecase"+ arb_poly_sinh_cosh_series_basecase :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_sinh_cosh_series_exponential/ /s/ /c/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_sinh_cosh_series_exponential"+ _arb_poly_sinh_cosh_series_exponential :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_sinh_cosh_series_exponential/ /s/ /c/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_sinh_cosh_series_exponential"+ arb_poly_sinh_cosh_series_exponential :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_sinh_cosh_series/ /s/ /c/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_sinh_cosh_series"+ _arb_poly_sinh_cosh_series :: Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_sinh_cosh_series/ /s/ /c/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_sinh_cosh_series"+ arb_poly_sinh_cosh_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_sinh_series/ /s/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_sinh_series"+ _arb_poly_sinh_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_sinh_series/ /s/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_sinh_series"+ arb_poly_sinh_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_cosh_series/ /c/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_cosh_series"+ _arb_poly_cosh_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_cosh_series/ /c/ /h/ /n/ /prec/ +--+-- Sets /s/ and /c/ respectively to the hyperbolic sine and cosine of the+-- power series /h/, truncated to length /n/.+-- +-- The implementations mirror those for sine and cosine, except that the+-- /exponential/ version computes both functions using the exponential+-- function instead of the hyperbolic tangent.+foreign import ccall "arb_poly.h arb_poly_cosh_series"+ arb_poly_cosh_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_sinc_series/ /s/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_sinc_series"+ _arb_poly_sinc_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_sinc_series/ /s/ /h/ /n/ /prec/ +--+-- Sets /c/ to the sinc function of the power series /h/, truncated to+-- length /n/.+foreign import ccall "arb_poly.h arb_poly_sinc_series"+ arb_poly_sinc_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_sinc_pi_series/ /s/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_sinc_pi_series"+ _arb_poly_sinc_pi_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_sinc_pi_series/ /s/ /h/ /n/ /prec/ +--+-- Compute the sinc function of the input multiplied by \(\pi\).+foreign import ccall "arb_poly.h arb_poly_sinc_pi_series"+ arb_poly_sinc_pi_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- Lambert W function ----------------------------------------------------------++-- | /_arb_poly_lambertw_series/ /res/ /z/ /zlen/ /flags/ /len/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_lambertw_series"+ _arb_poly_lambertw_series :: Ptr CArb -> Ptr CArb -> CLong -> CInt -> CLong -> CLong -> IO ()++-- | /arb_poly_lambertw_series/ /res/ /z/ /flags/ /len/ /prec/ +--+-- Sets /res/ to the Lambert W function of the power series /z/. If /flags/+-- is 0, the principal branch is computed; if /flags/ is 1, the second real+-- branch \(W_{-1}(z)\) is computed. The underscore method allows aliasing,+-- but assumes that the lengths are nonzero.+foreign import ccall "arb_poly.h arb_poly_lambertw_series"+ arb_poly_lambertw_series :: Ptr CArbPoly -> Ptr CArbPoly -> CInt -> CLong -> CLong -> IO ()++-- Gamma function and factorials -----------------------------------------------++-- | /_arb_poly_gamma_series/ /res/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_gamma_series"+ _arb_poly_gamma_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_gamma_series/ /res/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_gamma_series"+ arb_poly_gamma_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_rgamma_series/ /res/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_rgamma_series"+ _arb_poly_rgamma_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_rgamma_series/ /res/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_rgamma_series"+ arb_poly_rgamma_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_lgamma_series/ /res/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_lgamma_series"+ _arb_poly_lgamma_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_lgamma_series/ /res/ /h/ /n/ /prec/ +--+foreign import ccall "arb_poly.h arb_poly_lgamma_series"+ arb_poly_lgamma_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_digamma_series/ /res/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_digamma_series"+ _arb_poly_digamma_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_digamma_series/ /res/ /h/ /n/ /prec/ +--+-- Sets /res/ to the series expansion of \(\Gamma(h(x))\),+-- \(1/\Gamma(h(x))\), or \(\log \Gamma(h(x))\), \(\psi(h(x))\), truncated+-- to length /n/.+-- +-- These functions first generate the Taylor series at the constant term of+-- /h/, and then call @_arb_poly_compose_series@. The Taylor coefficients+-- are generated using the Riemann zeta function if the constant term of+-- /h/ is a small integer, and with Stirling\'s series otherwise.+-- +-- The underscore methods support aliasing of the input and output arrays,+-- and require that /hlen/ and /n/ are greater than zero.+foreign import ccall "arb_poly.h arb_poly_digamma_series"+ arb_poly_digamma_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_rising_ui_series/ /res/ /f/ /flen/ /r/ /trunc/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_rising_ui_series"+ _arb_poly_rising_ui_series :: Ptr CArb -> Ptr CArb -> CLong -> CULong -> CLong -> CLong -> IO ()++-- | /arb_poly_rising_ui_series/ /res/ /f/ /r/ /trunc/ /prec/ +--+-- Sets /res/ to the rising factorial \((f) (f+1) (f+2) \cdots (f+r-1)\),+-- truncated to length /trunc/. The underscore method assumes that /flen/,+-- /r/ and /trunc/ are at least 1, and does not support aliasing. Uses+-- binary splitting.+foreign import ccall "arb_poly.h arb_poly_rising_ui_series"+ arb_poly_rising_ui_series :: Ptr CArbPoly -> Ptr CArbPoly -> CULong -> CLong -> CLong -> IO ()++-- Zeta function ---------------------------------------------------------------++-- | /arb_poly_zeta_series/ /res/ /s/ /a/ /deflate/ /n/ /prec/ +--+-- Sets /res/ to the Hurwitz zeta function \(\zeta(s,a)\) where \(s\) a+-- power series and \(a\) is a constant, truncated to length /n/. To+-- evaluate the usual Riemann zeta function, set \(a = 1\).+-- +-- If /deflate/ is nonzero, evaluates \(\zeta(s,a) + 1/(1-s)\), which is+-- well-defined as a limit when the constant term of \(s\) is 1. In+-- particular, expanding \(\zeta(s,a) + 1/(1-s)\) with \(s = 1+x\) gives+-- the Stieltjes constants+-- +-- \[`\]+-- \[\sum_{k=0}^{n-1} \frac{(-1)^k}{k!} \gamma_k(a) x^k.\]+-- +-- If \(a = 1\), this implementation uses the reflection formula if the+-- midpoint of the constant term of \(s\) is negative.+foreign import ccall "arb_poly.h arb_poly_zeta_series"+ arb_poly_zeta_series :: Ptr CArbPoly -> Ptr CArbPoly -> Ptr CArb -> CInt -> CLong -> CLong -> IO ()++-- | /_arb_poly_riemann_siegel_theta_series/ /res/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_riemann_siegel_theta_series"+ _arb_poly_riemann_siegel_theta_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_riemann_siegel_theta_series/ /res/ /h/ /n/ /prec/ +--+-- Sets /res/ to the series expansion of the Riemann-Siegel theta function+-- +-- \[`\]+-- \[\theta(h) = \arg \left(\Gamma\left(\frac{2ih+1}{4}\right)\right) - \frac{\log \pi}{2} h\]+-- +-- where the argument of the gamma function is chosen continuously as the+-- imaginary part of the log gamma function.+-- +-- The underscore method does not support aliasing of the input and output+-- arrays, and requires that the lengths are greater than zero.+foreign import ccall "arb_poly.h arb_poly_riemann_siegel_theta_series"+ arb_poly_riemann_siegel_theta_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- | /_arb_poly_riemann_siegel_z_series/ /res/ /h/ /hlen/ /n/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_riemann_siegel_z_series"+ _arb_poly_riemann_siegel_z_series :: Ptr CArb -> Ptr CArb -> CLong -> CLong -> CLong -> IO ()++-- | /arb_poly_riemann_siegel_z_series/ /res/ /h/ /n/ /prec/ +--+-- Sets /res/ to the series expansion of the Riemann-Siegel Z-function+-- +-- \[`\]+-- \[Z(h) = e^{i\theta(h)} \zeta(1/2+ih).\]+-- +-- The zeros of the Z-function on the real line precisely correspond to the+-- imaginary parts of the zeros of the Riemann zeta function on the+-- critical line.+-- +-- The underscore method supports aliasing of the input and output arrays,+-- and requires that the lengths are greater than zero.+foreign import ccall "arb_poly.h arb_poly_riemann_siegel_z_series"+ arb_poly_riemann_siegel_z_series :: Ptr CArbPoly -> Ptr CArbPoly -> CLong -> CLong -> IO ()++-- Root-finding ----------------------------------------------------------------++-- | /_arb_poly_root_bound_fujiwara/ /bound/ /poly/ /len/ +--+foreign import ccall "arb_poly.h _arb_poly_root_bound_fujiwara"+ _arb_poly_root_bound_fujiwara :: Ptr CMag -> Ptr CArb -> CLong -> IO ()++-- | /arb_poly_root_bound_fujiwara/ /bound/ /poly/ +--+-- Sets /bound/ to an upper bound for the magnitude of all the complex+-- roots of /poly/. Uses Fujiwara\'s bound+-- +-- \[`\]+-- \[2 \max \left\{\left|\frac{a_{n-1}}{a_n}\right|,+-- \left|\frac{a_{n-2}}{a_n}\right|^{1/2},+-- \cdots,+-- \left|\frac{a_1}{a_n}\right|^{1/(n-1)},+-- \left|\frac{a_0}{2a_n}\right|^{1/n}+-- \right\}\]+-- +-- where \(a_0, \ldots, a_n\) are the coefficients of /poly/.+foreign import ccall "arb_poly.h arb_poly_root_bound_fujiwara"+ arb_poly_root_bound_fujiwara :: Ptr CMag -> Ptr CArbPoly -> IO ()++-- | /_arb_poly_newton_convergence_factor/ /convergence_factor/ /poly/ /len/ /convergence_interval/ /prec/ +--+-- Given an interval \(I\) specified by /convergence_interval/, evaluates a+-- bound for \(C = \sup_{t,u \in I} \frac{1}{2} |f''(t)| / |f'(u)|\), where+-- \(f\) is the polynomial defined by the coefficients /{poly, len}/. The+-- bound is obtained by evaluating \(f'(I)\) and \(f''(I)\) directly. If+-- \(f\) has large coefficients, \(I\) must be extremely precise in order+-- to get a finite factor.+foreign import ccall "arb_poly.h _arb_poly_newton_convergence_factor"+ _arb_poly_newton_convergence_factor :: Ptr CArf -> Ptr CArb -> CLong -> Ptr CArb -> CLong -> IO ()++-- | /_arb_poly_newton_step/ /xnew/ /poly/ /len/ /x/ /convergence_interval/ /convergence_factor/ /prec/ +--+-- Performs a single step with Newton\'s method.+-- +-- The input consists of the polynomial \(f\) specified by the coefficients+-- /{poly, len}/, an interval \(x = [m-r, m+r]\) known to contain a single+-- root of \(f\), an interval \(I\) (/convergence_interval/) containing+-- \(x\) with an associated bound (/convergence_factor/) for+-- \(C = \sup_{t,u \in I} \frac{1}{2} |f''(t)| / |f'(u)|\), and a working+-- precision /prec/.+-- +-- The Newton update consists of setting \(x' = [m'-r', m'+r']\) where+-- \(m' = m - f(m) / f'(m)\) and \(r' = C r^2\). The expression+-- \(m - f(m) / f'(m)\) is evaluated using ball arithmetic at a working+-- precision of /prec/ bits, and the rounding error during this evaluation+-- is accounted for in the output. We now check that \(x' \in I\) and+-- \(m' < m\). If both conditions are satisfied, we set /xnew/ to \(x'\)+-- and return nonzero. If either condition fails, we set /xnew/ to \(x\)+-- and return zero, indicating that no progress was made.+foreign import ccall "arb_poly.h _arb_poly_newton_step"+ _arb_poly_newton_step :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> Ptr CArb -> Ptr CArf -> CLong -> IO CInt++-- | /_arb_poly_newton_refine_root/ /r/ /poly/ /len/ /start/ /convergence_interval/ /convergence_factor/ /eval_extra_prec/ /prec/ +--+-- Refines a precise estimate of a polynomial root to high precision by+-- performing several Newton steps, using nearly optimally chosen doubling+-- precision steps.+-- +-- The inputs are defined as for /_arb_poly_newton_step/, except for the+-- precision parameters: /prec/ is the target accuracy and+-- /eval_extra_prec/ is the estimated number of guard bits that need to be+-- added to evaluate the polynomial accurately close to the root+-- (typically, if the polynomial has large coefficients of alternating+-- signs, this needs to be approximately the bit size of the coefficients).+foreign import ccall "arb_poly.h _arb_poly_newton_refine_root"+ _arb_poly_newton_refine_root :: Ptr CArb -> Ptr CArb -> CLong -> Ptr CArb -> Ptr CArb -> Ptr CArf -> CLong -> CLong -> IO ()++-- Other special polynomials ---------------------------------------------------++-- | /_arb_poly_swinnerton_dyer_ui/ /poly/ /n/ /trunc/ /prec/ +--+foreign import ccall "arb_poly.h _arb_poly_swinnerton_dyer_ui"+ _arb_poly_swinnerton_dyer_ui :: Ptr CArb -> CULong -> CLong -> CLong -> IO ()++-- | /arb_poly_swinnerton_dyer_ui/ /poly/ /n/ /prec/ +--+-- Computes the Swinnerton-Dyer polynomial \(S_n\), which has degree+-- \(2^n\) and is the rational minimal polynomial of the sum of the square+-- roots of the first /n/ prime numbers.+-- +-- If /prec/ is set to zero, a precision is chosen automatically such that+-- @arb_poly_get_unique_fmpz_poly@ should be successful. Otherwise a+-- working precision of /prec/ bits is used.+-- +-- The underscore version accepts an additional /trunc/ parameter. Even+-- when computing a truncated polynomial, the array /poly/ must have room+-- for \(2^n + 1\) coefficients, used as temporary space.+foreign import ccall "arb_poly.h arb_poly_swinnerton_dyer_ui"+ arb_poly_swinnerton_dyer_ui :: Ptr CArbPoly -> CULong -> CLong -> IO ()+
+ src/Data/Number/Flint/Arb/Poly/Instances.hs view
@@ -0,0 +1,64 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Arb.Poly.Instances (+ ArbPoly (..)+ , module GHC.Exts+) where++import Test.QuickCheck++import GHC.Exts++import System.IO.Unsafe+import Control.Monad++import Foreign.Ptr+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Alloc (free)+import Foreign.Marshal.Array (advancePtr)++import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.Instances+import Data.Number.Flint.Arb.Poly++import Data.Number.Flint.UFD++instance Show ArbPoly where+ show p = snd $ unsafePerformIO $ do+ withArbPoly p $ \p -> do+ cs <- arb_poly_get_strd p 16+ s <- peekCString cs+ free cs+ return s++instance IsList ArbPoly where+ type Item ArbPoly = Arb+ fromList c = unsafePerformIO $ do+ p <- newArbPoly+ withArbPoly p $ \p -> + forM_ [0..length c-1] $ \j ->+ withArb (c!!j) $ \a -> + arb_poly_set_coeff_arb p (fromIntegral j) a+ return p+ toList p = snd $ unsafePerformIO $ + withArbPoly p $ \p -> do+ d <- arb_poly_degree p+ forM [0..d] $ \j -> do+ c <- newArb+ withArb c $ \c -> arb_poly_get_coeff_arb c p j+ return c++lift2 f x y = unsafePerformIO $ do+ result <- newArbPoly+ withArbPoly result $ \result -> do+ withArbPoly x $ \x -> do+ withArbPoly y $ \y -> do+ f result x y+ return result++lift1 f x = unsafePerformIO $ do+ result <- newArbPoly+ withArbPoly result $ \result ->+ withArbPoly x $ \x ->+ f result x+ return result
+ src/Data/Number/Flint/Arb/RealField.hs view
@@ -0,0 +1,327 @@+module Data.Number.Flint.Arb.RealField (+ RF(..)+, RF'(..)+, Special (..)+, fromDouble+, toDouble+) where++import GHC.TypeLits+import Data.Proxy++import GHC.Read +import qualified Text.Read.Lex as Lex+import Text.ParserCombinators.ReadPrec hiding (prec)++import Data.Ratio++import System.IO.Unsafe+import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr )+import Foreign.Storable+import Foreign.Marshal (free)++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Instances+import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.Arf+import Data.Number.Flint.Arb.Mag+import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Arb.Hypgeom+import Data.Number.Flint.Support.D.Interval++newtype RF (n :: Nat) = RF Arb++instance forall n. KnownNat n => Eq (RF n) where+ {-# INLINE (==) #-}+ (==) = liftCmp arb_eq+ {-# INLINE (/=) #-}+ (/=) = liftCmp arb_ne++instance forall n. KnownNat n => Ord (RF n) where+ {-# INLINE (<) #-}+ (<) = liftCmp arb_lt+ {-# INLINE (<=) #-}+ (<=) = liftCmp arb_le+ {-# INLINE (>) #-}+ (>) = liftCmp arb_gt+ {-# INLINE (>=) #-}+ (>=) = liftCmp arb_ge+ {-# INLINE max #-}+ max = lift2 arb_max+ {-# INLINE min #-}+ min = lift2 arb_min+ +instance forall n. KnownNat n => Num (RF n) where+ {-# INLINE (+) #-}+ (+) = lift2 arb_add+ {-# INLINE (-) #-}+ (-) = lift2 arb_sub+ {-# INLINE (*) #-}+ (*) = lift2 arb_mul+ {-# INLINE negate #-}+ negate = lift1 arb_neg+ {-# INLINE abs #-}+ abs = lift1 arb_abs+ {-# INLINE fromInteger #-}+ fromInteger x = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ result <- newArb+ withArb result $ \result -> do+ withCString (show x) $ \s -> do+ flag <- arb_set_str result s prec+ when (flag /= 0) $+ error $ "Could not create RF " ++ show prec ++ " from " ++ show x+ return (RF result)+ {-# INLINE signum #-}+ signum = lift1 arb_sgn+ +instance forall n. KnownNat n => Fractional (RF n) where+ {-# INLINE (/) #-}+ (/) = lift2 arb_div+ fromRational x = p / q where+ p = fromIntegral (numerator x) :: RF n+ q = fromIntegral (denominator x) :: RF n++instance forall n. KnownNat n => RealFloat (RF n) where+ isNaN = not . liftProp arb_is_finite+ isInfinite = not . liftProp arb_is_finite+ floatRadix _ = 2+ floatDigits _ = fromIntegral $ natVal (Proxy :: Proxy n)+ floatRange _ = (minBound :: Int, maxBound :: Int)+ decodeFloat (RF x) = unsafePerformIO $ do+ man <- newFmpz+ exp <- newFmpz + withArb x $ \a -> do+ arf <- arb_midref a+ withFmpz man $ \man -> do+ withFmpz exp $ \exp -> do+ arf_get_fmpz_2exp man exp arf+ return (toInteger man, fromIntegral exp)+ encodeFloat man exp = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ m = fromIntegral man :: Fmpz+ e = fromIntegral exp :: Fmpz+ res <- newArb+ withArb res $ \res -> do + withFmpz m $ \m -> do+ withFmpz e $ \e -> do+ withNewArf $ \ arf -> do+ arf_set_round_fmpz_2exp arf m e prec arf_rnd_near+ arb_set_arf res arf+ return $ RF res+ isDenormalized = error "isDenormalized: not defined"+ isNegativeZero = error "isNegativeZero: not defined"+ isIEEE _ = False+ atan2 = lift2 arb_atan2++instance forall n. KnownNat n => Real (RF n) where+ toRational x =+ case decodeFloat x of+ (m, n) -> if n >= 0 then (m*2^n)%1 else m % (2^(-n))++instance forall n. KnownNat n => RealFrac (RF n) where+ properFraction x+ = case (decodeFloat x) of { (m,n) ->+ if n >= 0 then+ (fromInteger m * 2 ^ n, 0.0)+ else+ case (quotRem m (2^(negate n))) of { (w,r) ->+ (fromInteger w, encodeFloat r n)+ }+ }++instance forall n. KnownNat n => Floating (RF n) where+ pi = liftConstant arb_const_pi+ exp = liftF1 arb_exp+ log = liftF1 arb_log+ sqrt = liftF1 arb_sqrt+ sin = liftF1 arb_sin+ cos = liftF1 arb_cos+ tan = liftF1 arb_tan+ asin = liftF1 arb_asin+ acos = liftF1 arb_acos+ atan = liftF1 arb_atan+ sinh = liftF1 arb_sinh+ cosh = liftF1 arb_cosh+ tanh = liftF1 arb_tanh+ asinh = liftF1 arb_asinh+ acosh = liftF1 arb_acosh+ atanh = liftF1 arb_atanh+ +instance forall n. KnownNat n => Show (RF n) where+ show (RF x) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ digits = floor (fromIntegral prec * logBase 10 2)+ (_, cstr) <- withArb x $ \p ->+ arb_get_str p (fromIntegral digits) arb_str_no_radius+ str <- peekCString cstr+ return str++instance forall n. KnownNat n => Read (RF n) where+ readPrec = readNumber convertFrac+ readListPrec = readListPrecDefault+ readList = readListDefault++convertFrac :: RealFloat a => Lex.Lexeme -> ReadPrec a+convertFrac (Lex.Ident "NaN") = return (0 / 0)+convertFrac (Lex.Ident "Infinity") = return (1 / 0)+convertFrac (Lex.Number n) = let resRange = floatRange (undefined :: a)+ in case Lex.numberToRangedRational resRange n of+ Nothing -> return (1 / 0)+ Just rat -> return $ fromRational rat+convertFrac _ = pfail++------------------------------------------------------------------------++instance forall n. KnownNat n => Special (RF n) where+ gamma = liftF1 arb_gamma+ digamma = liftF1 arb_digamma+ lgamma = liftF1 arb_hypgeom_lgamma+ zeta = liftF1 arb_zeta+ erf = liftF1 arb_hypgeom_erf+ airy (RF x) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ ai <- newArb+ ai' <- newArb+ bi <- newArb+ bi' <- newArb+ withArb x $ \x -> + withArb ai $ \ai -> + withArb ai' $ \ai' ->+ withArb bi $ \bi ->+ withArb bi' $ \bi' ->+ arb_hypgeom_airy ai ai' bi bi' x prec+ return $ (RF ai, RF ai', RF bi, RF bi')+ airyZeros k = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ ai <- newArb+ ai' <- newArb+ bi <- newArb+ bi' <- newArb+ withFmpz k $ \k -> + withArb ai $ \ai -> + withArb ai' $ \ai' ->+ withArb bi $ \bi ->+ withArb bi' $ \bi' ->+ arb_hypgeom_airy_zero ai ai' bi bi' k prec+ return $ (RF ai, RF ai', RF bi, RF bi')+ besselJ = lift2 arb_hypgeom_bessel_j+ besselY = lift2 arb_hypgeom_bessel_y+ besselI = lift2 arb_hypgeom_bessel_i+ besselK = lift2 arb_hypgeom_bessel_k+ modj = undefined+ modjq = undefined+ modeta = undefined+ modetaq = undefined+ modlambda = undefined+ modlambdaq = undefined+ ellipp = undefined+ ellipzeta = undefined+ ellipsigma = undefined+ barnesg = undefined+ agm = undefined+ fresnels = undefined+ fresnelc = undefined+ +class RF' a where+ euler :: a+ glaisher :: a+ catalan :: a+ khinchin :: a+ polylog :: a -> a -> a+ midPoint :: a -> a+ +instance forall n. KnownNat n => RF' (RF n) where+ euler = liftConstant arb_const_euler+ glaisher = liftConstant arb_const_glaisher+ catalan = liftConstant arb_const_catalan+ khinchin = liftConstant arb_const_khinchin+ polylog = lift2 arb_polylog+ midPoint = lift1 arb_get_mid_arb++fromDouble :: forall n. KnownNat n => Double -> RF n+fromDouble x = unsafePerformIO $ do+ res <- newArb+ withArb res $ \res -> arb_set_d res (realToFrac x)+ return $ RF res+ +toDouble :: forall n. KnownNat n => RF n -> Double+toDouble x = fromRational $ toRational x+ +-- lifting -------------------------------------------------------------++type Binary = Ptr CArb -> Ptr CArb -> Ptr CArb -> CLong -> IO ()+type Cmp = Ptr CArb -> Ptr CArb -> IO CInt+type Function = Ptr CArb -> Ptr CArb -> IO ()++lift2 :: forall n. KnownNat n => Binary -> RF n -> RF n -> RF n+lift2 f (RF a) (RF b) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ c <- newArb+ withArb a $ \a ->+ withArb b $ \b ->+ withArb c $ \c ->+ f c a b (CLong prec)+ return (RF c)++lift1 :: forall n. KnownNat n => Function -> RF n -> RF n+lift1 f (RF x) = unsafePerformIO $ do+ y <- newArb+ withArb x $ \x -> withArb y $ \y -> f y x+ return (RF y)+ +lift0 f x = RF $ unsafePerformIO $ fst <$> withNewArb (`f` x)+ +liftF1 :: forall n. KnownNat n =>+ (Ptr CArb -> Ptr CArb -> CLong -> IO ()) -> RF n -> RF n+liftF1 f (RF x) = unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ y <- newArb+ withArb x $ \x -> withArb y $ \y -> f y x (CLong prec)+ return (RF y)++liftCmp :: forall n. KnownNat n => Cmp -> RF n -> RF n -> Bool+liftCmp f (RF x) (RF y) = unsafePerformIO $ do+ (_, (_, cmp)) <- withArb x $ \x -> withArb y $ \y -> f x y+ return (cmp == 1)++liftProp :: forall n. KnownNat n => (Ptr CArb -> IO CInt) -> RF n -> Bool+liftProp f (RF x) = unsafePerformIO $ do+ (_, prop) <- withArb x $ \x -> f x+ return (prop == 1)++liftConstant :: forall n. KnownNat n => (Ptr CArb -> CLong -> IO ()) -> RF n+liftConstant f = RF $ unsafePerformIO $ do+ let prec = fromInteger $ natVal (Proxy :: Proxy n)+ fst <$> withNewArb (`f` CLong prec)++class Special a where+ gamma :: a -> a+ digamma :: a -> a+ lgamma :: a -> a+ zeta :: a -> a+ erf :: a -> a+ airy :: a -> (a, a, a, a)+ airyZeros :: Fmpz -> (a, a, a, a)+ besselJ :: a -> a -> a+ besselY :: a -> a -> a+ besselI :: a -> a -> a+ besselK :: a -> a -> a+ modj :: a -> a+ modjq :: a -> a+ modeta :: a -> a+ modetaq :: a -> a+ modlambda :: a -> a+ modlambdaq :: a -> a+ ellipp :: a -> a -> a+ ellipzeta :: a -> a -> a+ ellipsigma :: a -> a -> a+ barnesg :: a -> a+ agm :: a -> a -> a+ fresnels :: a -> a+ fresnelc :: a -> a
+ src/Data/Number/Flint/Arb/Types.hs view
@@ -0,0 +1,6 @@+-- {-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Arb.Types (+ module Data.Number.Flint.Arb.Types.FFI+ ) where++import Data.Number.Flint.Arb.Types.FFI
+ src/Data/Number/Flint/Arb/Types/FFI.hsc view
@@ -0,0 +1,141 @@+{-|+module : Data.Number.Flint.Arb.Types.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Arb.Types.FFI where++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint.Internal+import Data.Number.Flint.Flint.External+import Data.Number.Flint.Fmpz++#include <flint/arf.h>+#include <flint/mag.h>+#include <flint/arb.h>++-- | Data structure containing the CMag pointer+data Mag = Mag {-# UNPACK #-} !(ForeignPtr CMag)+data CMag = CMag CFmpz CMpLimb++instance Storable CMag where+ sizeOf _ = #{size mag_t}+ alignment _ = #{alignment mag_t}+ peek ptr = CMag+ <$> #{peek mag_struct, exp} ptr+ <*> #{peek mag_struct, man} ptr+ poke = undefined++-- arf_t -----------------------------------------------------------------------++-- | Data structure containing the CArb pointer+data Arf = Arf {-# UNPACK #-} !(ForeignPtr CArf) +data CArf = CFlint CArf ++instance Storable CArf where+ sizeOf _ = #{size arf_t}+ alignment _ = #{alignment arf_t}+ peek = error "CArf.peek undefined."+ poke = error "CArf.poke undefined."++-- >>> Arf depends on a c-union which cannot be converted to a Haskell type++-- | Arf rounding+newtype ArfRnd = ArfRnd {_ArfRnd :: CInt}+ deriving (Show, Eq)++-- | Specifies that the result of an operation should be rounded to+-- the nearest representable number in the direction towards zero.+arf_rnd_up = ArfRnd #const ARF_RND_UP+-- | Specifies that the result of an operation should be rounded to+-- the nearest representable number in the direction away from zero.+arf_rnd_down = ArfRnd #const ARF_RND_DOWN+-- | Specifies that the result of an operation should be rounded to+-- the nearest representable number in the direction towards minus+-- infinity.+arf_rnd_floor = ArfRnd #const ARF_RND_FLOOR+-- | Specifies that the result of an operation should be rounded to+-- the nearest representable number in the direction towards plus+-- infinity.+arf_rnd_ceil = ArfRnd #const ARF_RND_CEIL+-- | Specifies that the result of an operation should be rounded to+-- the nearest representable number, rounding to even if there is a+-- tie between two values.+arf_rnd_near = ArfRnd #const ARF_RND_NEAR+-- | If passed as the precision parameter to a function, indicates+-- that no rounding is to be performed. __Warning__: use of this value+-- is unsafe in general. It must only be passed as input under the+-- following two conditions:+-- +-- * The operation in question can inherently be viewed as an exact operation+-- in \(\mathbb{Z}[\tfrac{1}{2}]\) for all possible inputs, provided that+-- the precision is large enough. Examples include addition,+-- multiplication, conversion from integer types to arbitrary-precision+-- floating-point types, and evaluation of some integer-valued functions.+--+-- * The exact result of the operation will certainly fit in memory.+-- Note that, for example, adding two numbers whose exponents are far+-- apart can easily produce an exact result that is far too large to+-- store in memory.+--+-- The typical use case is to work with small integer values, double+-- precision constants, and the like. It is also useful when writing+-- test code. If in doubt, simply try with some convenient high precision+-- instead of using this special value, and check that the result is exact.+arf_prec_exact = ArfRnd #const ARF_PREC_EXACT++-- arb_t -----------------------------------------------------------------------++-- | Data structure containing the CArb pointer+data Arb = Arb {-# UNPACK #-} !(ForeignPtr CArb) +data CArb = CArb CMag CArf++instance Storable CArb where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size arb_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment arb_t}+ peek = error "CArb.peek undefined."+ poke = error "CArb.poke undefined."+ +-- | string options+newtype ArbStrOption = ArbStrOption {_ArbStrOption :: CULong}+ deriving (Show, Eq)++instance Num ArbStrOption where+ (+) (ArbStrOption x) (ArbStrOption y) = ArbStrOption (x + y)+ (*) = undefined+ abs = undefined+ signum = undefined+ fromInteger = undefined+ negate = undefined++-- | Default print option+arb_str_none = ArbStrOption 0+-- | If /arb_str_more/ is added to flags, more (possibly incorrect)+-- digits may be printed+arb_str_more = ArbStrOption #const ARB_STR_MORE+-- | If /arb_str_no_radius/ is added to /flags/, the radius is not+-- included in the output if at least 1 digit of the midpoint can be+-- printed.+arb_str_no_radius = ArbStrOption #const ARB_STR_NO_RADIUS+-- | By adding a multiple m of /arb_str_condense/ to /flags/, strings of+-- more than three times m consecutive digits are condensed, only+-- printing the leading and trailing m digits along with brackets+-- indicating the number of digits omitted (useful when computing+-- values to extremely high precision).+arb_str_condense = ArbStrOption #const ARB_STR_CONDENSE++-- arb_poly_t ------------------------------------------------------------------++-- | Data structure containing the CArb pointer+data ArbPoly = ArbPoly {-# UNPACK #-} !(ForeignPtr CArbPoly) +type CArbPoly = CFlint ArbPoly
+ src/Data/Number/Flint/Bernoulli.hs view
@@ -0,0 +1,25 @@+{-|+module : Data.Number.Flint.Bernoulli+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++This module provides helper functions for exact or approximate+calculation of the Bernoulli numbers, which are defined by the+exponential generating function++\[\frac{x}{e^x-1} = \sum_{n=0}^{\infty} B_n \frac{x^n}{n!}.\]++Efficient algorithms are implemented for both multi-evaluation and+calculation of isolated Bernoulli numbers. A global (or thread-local)+cache is also provided, to support fast repeated evaluation of various+special functions that depend on the Bernoulli numbers (including the+gamma function and the Riemann zeta function).+-}++module Data.Number.Flint.Bernoulli (+ module Data.Number.Flint.Bernoulli.FFI+) where++import Data.Number.Flint.Bernoulli.FFI+
+ src/Data/Number/Flint/Bernoulli/FFI.hsc view
@@ -0,0 +1,179 @@+{-|+module : Data.Number.Flint.Bernoulli.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Bernoulli.FFI (+ -- * Support for Bernoulli numbers+ -- * Generation of Bernoulli numbers+ BernoulliRev (..)+ , CBernoulliRev (..)+ , newBernoulliRev+ , withBernoulliRev+ , withNewBernoulliRev+ , bernoulli_rev_init+ , bernoulli_rev_next+ , bernoulli_rev_clear+ , bernoulli_fmpq_vec_no_cache+ -- * Caching+ , bernoulli_cache_compute+ -- * Bounding+ , bernoulli_bound_2exp_si+ -- * Isolated Bernoulli numbers+ , bernoulli_mod_p_harvey+ , _bernoulli_fmpq_ui_zeta+ , _bernoulli_fmpq_ui+) where++-- Support for Bernoulli numbers -----------------------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.Storable++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb.Types++#include <flint/bernoulli.h>++-- bernoulli_rev_t -------------------------------------------------------------++data BernoulliRev = BernoulliRev {-# UNPACK #-} !(ForeignPtr CBernoulliRev)+type CBernoulliRev = CFlint BernoulliRev++instance Storable CBernoulliRev where+ sizeOf _ = #{size bernoulli_rev_t}+ alignment _ = #{alignment bernoulli_rev_t}+ peek = error "CBernoulliRev.peek: not implemented."+ poke = error "CBernoulliRev.poke: not implemented."+ +newBernoulliRev n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ bernoulli_rev_init x n+ addForeignPtrFinalizer p_bernoulli_rev_clear x+ return $ BernoulliRev x++withBernoulliRev (BernoulliRev x) f = do+ withForeignPtr x $ \xp -> (BernoulliRev x,) <$> f xp++withNewBernoulliRev n f = do+ x <- newBernoulliRev n+ withBernoulliRev x f+ +-- Generation of Bernoulli numbers ---------------------------------------------++-- | /bernoulli_rev_init/ /iter/ /n/ +-- +-- Initializes the iterator /iter/. The first Bernoulli number to be+-- generated by calling @bernoulli_rev_next@ is \(B_n\). It is assumed that+-- \(n\) is even.+foreign import ccall "bernoulli.h bernoulli_rev_init"+ bernoulli_rev_init :: Ptr CBernoulliRev -> CULong -> IO ()++-- | /bernoulli_rev_next/ /numer/ /denom/ /iter/ +-- +-- Sets /numer/ and /denom/ to the exact, reduced numerator and denominator+-- of the Bernoulli number \(B_k\) and advances the state of /iter/ so that+-- the next invocation generates \(B_{k-2}\).+foreign import ccall "bernoulli.h bernoulli_rev_next"+ bernoulli_rev_next :: Ptr CFmpz -> Ptr CFmpz -> Ptr CBernoulliRev -> IO ()++-- | /bernoulli_rev_clear/ /iter/ +-- +-- Frees all memory allocated internally by /iter/.+foreign import ccall "bernoulli.h bernoulli_rev_clear"+ bernoulli_rev_clear :: Ptr CBernoulliRev -> IO ()++foreign import ccall "bernoulli.h &bernoulli_rev_clear"+ p_bernoulli_rev_clear :: FunPtr (Ptr CBernoulliRev -> IO ())++-- | /bernoulli_fmpq_vec_no_cache/ /res/ /a/ /num/ +-- +-- Writes /num/ consecutive Bernoulli numbers to /res/ starting with+-- \(B_a\). This function is not currently optimized for a small count+-- /num/. The entries are not read from or written to the Bernoulli number+-- cache; if retrieving a vector of Bernoulli numbers is needed more than+-- once, use @bernoulli_cache_compute@ followed by @bernoulli_fmpq_ui@+-- instead.+-- +-- This function is a wrapper for the /rev/ iterators. It can use multiple+-- threads internally.+foreign import ccall "bernoulli.h bernoulli_fmpq_vec_no_cache"+ bernoulli_fmpq_vec_no_cache :: Ptr CFmpq -> CULong -> CLong -> IO ()++-- Caching ---------------------------------------------------------------------++-- | /bernoulli_cache_compute/ /n/ +-- +-- Makes sure that the Bernoulli numbers up to at least \(B_{n-1}\) are+-- cached. Calling @flint_cleanup()@ frees the cache.+-- +-- The cache is extended by calling @bernoulli_fmpq_vec_no_cache@+-- internally.+foreign import ccall "bernoulli.h bernoulli_cache_compute"+ bernoulli_cache_compute :: CLong -> IO ()++-- Bounding --------------------------------------------------------------------++-- | /bernoulli_bound_2exp_si/ /n/ +-- +-- Returns an integer \(b\) such that \(|B_n| \le 2^b\). Uses a lookup+-- table for small \(n\), and for larger \(n\) uses the inequality+-- \(|B_n| < 4 n! / (2 \pi)^n < 4 (n+1)^{n+1} e^{-n} / (2 \pi)^n\). Uses+-- integer arithmetic throughout, with the bound for the logarithm being+-- looked up from a table. If \(|B_n| = 0\), returns /LONG_MIN/. Otherwise,+-- the returned exponent \(b\) is never more than one percent larger than+-- the true magnitude.+-- +-- This function is intended for use when \(n\) small enough that one might+-- comfortably compute \(B_n\) exactly. It aborts if \(n\) is so large that+-- internal overflow occurs.+foreign import ccall "bernoulli.h bernoulli_bound_2exp_si"+ bernoulli_bound_2exp_si :: CULong -> IO CLong++-- Isolated Bernoulli numbers --------------------------------------------------++-- | /bernoulli_mod_p_harvey/ /n/ /p/ +-- +-- Returns the \(B_n\) modulo the prime number /p/, computed using+-- Harvey\'s algorithm < [Har2010]>. The running time is linear in /p/. If+-- /p/ divides the numerator of \(B_n\), /UWORD_MAX/ is returned as an+-- error code.+foreign import ccall "bernoulli.h bernoulli_mod_p_harvey"+ bernoulli_mod_p_harvey :: CULong -> CULong -> IO CULong++-- | /_bernoulli_fmpq_ui_zeta/ /num/ /den/ /n/ +-- +-- Sets /num/ and /den/ to the reduced numerator and denominator of the+-- Bernoulli number \(B_n\).+-- +-- The /zeta/ version computes the denominator \(d\) using the von+-- Staudt-Clausen theorem, numerically approximates \(B_n\) using+-- @arb_bernoulli_ui_zeta@, and then rounds \(d B_n\) to the correct+-- numerator.+-- +-- The /multi_mod/ version reconstructs \(B_n\) by computing the high bits+-- via the Riemann zeta function and the low bits via Harvey\'s+-- multimodular algorithm. The tuning parameter /alpha/ should be a+-- fraction between 0 and 1 controlling the number of bits to compute by+-- the multimodular algorithm. If set to a negative number, a default value+-- will be used.+foreign import ccall "bernoulli.h _bernoulli_fmpq_ui_zeta"+ _bernoulli_fmpq_ui_zeta :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /_bernoulli_fmpq_ui/ /num/ /den/ /n/ +-- +-- Computes the Bernoulli number \(B_n\) as an exact fraction, for an+-- isolated integer \(n\). This function reads \(B_n\) from the global+-- cache if the number is already cached, but does not automatically extend+-- the cache by itself.+foreign import ccall "bernoulli.h _bernoulli_fmpq_ui"+ _bernoulli_fmpq_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()+
+ src/Data/Number/Flint/FFT.hs view
@@ -0,0 +1,12 @@+{-|+module : Data.Number.Flint.FFT+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.FFT (+ module Data.Number.Flint.FFT.FFI+) where++import Data.Number.Flint.FFT.FFI+
+ src/Data/Number/Flint/FFT/FFI.hsc view
@@ -0,0 +1,711 @@+{-|+module : Data.Number.Flint.FFT.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.FFT.FFI (+ -- * Schoenhage-Strassen FFT+ -- * Split\/combine FFT coefficients+ fft_split_limbs+ , fft_split_bits+ , fft_combine_limbs+ , fft_combine_bits+ -- * Test helper functions+ , fermat_to_mpz+ -- * Arithmetic modulo a generalised Fermat number+ , mpn_negmod_2expp1+ , mpn_addmod_2expp1_1+ , mpn_normmod_2expp1+ , mpn_mul_2expmod_2expp1+ , mpn_div_2expmod_2expp1+ -- * Generic butterflies+ , fft_adjust+ , fft_adjust_sqrt2+ , butterfly_lshB+ , butterfly_rshB+ -- * Radix 2 transforms+ , fft_butterfly+ , ifft_butterfly+ , fft_radix2+ , fft_truncate+ , fft_truncate1+ , ifft_radix2+ , ifft_truncate+ , ifft_truncate1+ , fft_butterfly_sqrt2+ , ifft_butterfly_sqrt2+ , fft_truncate_sqrt2+ , ifft_truncate_sqrt2+ -- * Matrix Fourier Transforms+ , fft_butterfly_twiddle+ , ifft_butterfly_twiddle+ , fft_radix2_twiddle+ , ifft_radix2_twiddle+ , fft_truncate1_twiddle+ , ifft_truncate1_twiddle+ , fft_mfa_truncate_sqrt2+ , ifft_mfa_truncate_sqrt2+ , fft_mfa_truncate_sqrt2_outer+ , fft_mfa_truncate_sqrt2_inner+ , ifft_mfa_truncate_sqrt2_outer+ -- * Negacyclic multiplication+ , fft_negacyclic+ , ifft_negacyclic+ , fft_naive_convolution_1+ , _fft_mulmod_2expp1+ , fft_adjust_limbs+ , fft_mulmod_2expp1+ -- * Integer multiplication+ , mul_truncate_sqrt2+ , mul_mfa_truncate_sqrt2+ , flint_mpn_mul_fft_main+ -- * Convolution+ , fft_convolution+ -- * FFT Precaching+ , fft_precache+ , fft_convolution_precache+) where++-- Schoenhage-Strassen FFT -----------------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint++#include <flint/flint.h>+#include <flint/fft.h>++-- Split\/combine FFT coefficients ---------------------------------------------++-- | /fft_split_limbs/ /poly/ /limbs/ /total_limbs/ /coeff_limbs/ /output_limbs/ +--+-- Split an integer @(limbs, total_limbs)@ into coefficients of length+-- @coeff_limbs@ limbs and store as the coefficients of @poly@ which are+-- assumed to have space for @output_limbs + 1@ limbs per coefficient. The+-- coefficients of the polynomial do not need to be zeroed before calling+-- this function, however the number of coefficients written is returned by+-- the function and any coefficients beyond this point are not touched.+foreign import ccall "fft.h fft_split_limbs"+ fft_split_limbs :: Ptr (Ptr CMpLimb) -> Ptr CMp -> CMpSize -> CMpSize -> CMpSize -> IO CMpSize++-- | /fft_split_bits/ /poly/ /limbs/ /total_limbs/ /bits/ /output_limbs/ +--+-- Split an integer @(limbs, total_limbs)@ into coefficients of the given+-- number of @bits@ and store as the coefficients of @poly@ which are+-- assumed to have space for @output_limbs + 1@ limbs per coefficient. The+-- coefficients of the polynomial do not need to be zeroed before calling+-- this function, however the number of coefficients written is returned by+-- the function and any coefficients beyond this point are not touched.+foreign import ccall "fft.h fft_split_bits"+ fft_split_bits :: Ptr (Ptr CMpLimb) -> Ptr CMp -> CMpSize -> CFBitCnt -> CMpSize -> IO CMpSize++-- | /fft_combine_limbs/ /res/ /poly/ /length/ /coeff_limbs/ /output_limbs/ /total_limbs/ +--+-- Evaluate the polynomial @poly@ of the given @length@ at @B^coeff_limbs@,+-- where @B = 2^FLINT_BITS@, and add the result to the integer+-- @(res, total_limbs)@ throwing away any bits that exceed the given number+-- of limbs. The polynomial coefficients are assumed to have at least+-- @output_limbs@ limbs each, however any additional limbs are ignored.+-- +-- If the integer is initially zero the result will just be the evaluation+-- of the polynomial.+foreign import ccall "fft.h fft_combine_limbs"+ fft_combine_limbs :: Ptr CMpLimb -> Ptr (Ptr CMpLimb) -> CLong -> CMpSize -> CMpSize -> CMpSize -> IO ()++-- | /fft_combine_bits/ /res/ /poly/ /length/ /bits/ /output_limbs/ /total_limbs/ +--+-- Evaluate the polynomial @poly@ of the given @length@ at @2^bits@ and add+-- the result to the integer @(res, total_limbs)@ throwing away any bits+-- that exceed the given number of limbs. The polynomial coefficients are+-- assumed to have at least @output_limbs@ limbs each, however any+-- additional limbs are ignored. If the integer is initially zero the+-- result will just be the evaluation of the polynomial.+foreign import ccall "fft.h fft_combine_bits"+ fft_combine_bits :: Ptr CMpLimb -> Ptr (Ptr CMpLimb) -> CLong -> CFBitCnt -> CMpSize -> CMpSize -> IO ()++-- Test helper functions -------------------------------------------------------++-- | /fermat_to_mpz/ /m/ /i/ /limbs/ +--+-- Convert the Fermat number @(i, limbs)@ modulo @B^limbs + 1@ to an+-- @mpz_t m@. Assumes @m@ has been initialised. This function is used only+-- in test code.+foreign import ccall "fft.h fermat_to_mpz"+ fermat_to_mpz :: Ptr CMpz -> Ptr CMpLimb -> CMpSize -> IO ()++-- Arithmetic modulo a generalised Fermat number -------------------------------++-- | /mpn_negmod_2expp1/ /z/ /a/ /limbs/ +--+-- Set @z@ to the negation of the Fermat number \(a\) modulo @B^limbs + 1@.+-- The input @a@ is expected to be fully reduced, and the output is fully+-- reduced. Aliasing is permitted.+foreign import ccall "fft.h mpn_negmod_2expp1"+ mpn_negmod_2expp1 :: Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> IO ()++-- | /mpn_addmod_2expp1_1/ /r/ /limbs/ /c/ +--+-- Adds the signed limb @c@ to the generalised Fermat number @r@ modulo+-- @B^limbs + 1@. The compiler should be able to inline this for the case+-- that there is no overflow from the first limb.+foreign import ccall "fft.h mpn_addmod_2expp1_1"+ mpn_addmod_2expp1_1 :: Ptr CMpLimb -> CMpSize -> Ptr CMpSLimb-> IO ()++-- | /mpn_normmod_2expp1/ /t/ /limbs/ +--+-- Given @t@ a signed integer of @limbs + 1@ limbs in two\'s complement+-- format, reduce @t@ to the corresponding value modulo the generalised+-- Fermat number @B^limbs + 1@, where @B = 2^FLINT_BITS@.+foreign import ccall "fft.h mpn_normmod_2expp1"+ mpn_normmod_2expp1 :: Ptr CMpLimb -> CMpSize -> IO ()++-- | /mpn_mul_2expmod_2expp1/ /t/ /i1/ /limbs/ /d/ +--+-- Given @i1@ a signed integer of @limbs + 1@ limbs in two\'s complement+-- format reduced modulo @B^limbs + 1@ up to some overflow, compute+-- @t = i1*2^d@ modulo \(p\). The result will not necessarily be fully+-- reduced. The number of bits @d@ must be nonnegative and less than+-- @FLINT_BITS@. Aliasing is permitted.+foreign import ccall "fft.h mpn_mul_2expmod_2expp1"+ mpn_mul_2expmod_2expp1 :: Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CFBitCnt -> IO ()++-- | /mpn_div_2expmod_2expp1/ /t/ /i1/ /limbs/ /d/ +--+-- Given @i1@ a signed integer of @limbs + 1@ limbs in two\'s complement+-- format reduced modulo @B^limbs + 1@ up to some overflow, compute+-- @t = i1\/2^d@ modulo \(p\). The result will not necessarily be fully+-- reduced. The number of bits @d@ must be nonnegative and less than+-- @FLINT_BITS@. Aliasing is permitted.+foreign import ccall "fft.h mpn_div_2expmod_2expp1"+ mpn_div_2expmod_2expp1 :: Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CFBitCnt -> IO ()++-- Generic butterflies ---------------------------------------------------------++-- | /fft_adjust/ /r/ /i1/ /i/ /limbs/ /w/ +--+-- Set @r@ to @i1@ times \(z^i\) modulo @B^limbs + 1@ where \(z\)+-- corresponds to multiplication by \(2^w\). This can be thought of as part+-- of a butterfly operation. We require \(0 \leq i < n\) where \(nw =\)+-- @limbs*FLINT_BITS@. Aliasing is not supported.+foreign import ccall "fft.h fft_adjust"+ fft_adjust :: Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CMpSize -> CFBitCnt -> IO ()++-- | /fft_adjust_sqrt2/ /r/ /i1/ /i/ /limbs/ /w/ /temp/ +--+-- Set @r@ to @i1@ times \(z^i\) modulo @B^limbs + 1@ where \(z\)+-- corresponds to multiplication by \(\sqrt{2}^w\). This can be thought of+-- as part of a butterfly operation. We require \(0 \leq i < 2\cdot n\) and+-- odd where \(nw =\) @limbs*FLINT_BITS@.+foreign import ccall "fft.h fft_adjust_sqrt2"+ fft_adjust_sqrt2 :: Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CMpSize -> CFBitCnt -> Ptr CMpLimb -> IO ()++-- | /butterfly_lshB/ /t/ /u/ /i1/ /i2/ /limbs/ /x/ /y/ +--+-- We are given two integers @i1@ and @i2@ modulo @B^limbs + 1@ which are+-- not necessarily normalised. We compute @t = (i1 + i2)*B^x@ and+-- @u = (i1 - i2)*B^y@ modulo \(p\). Aliasing between inputs and outputs is+-- not permitted. We require @x@ and @y@ to be less than @limbs@ and+-- nonnegative.+foreign import ccall "fft.h butterfly_lshB"+ butterfly_lshB :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CMpSize -> CMpSize -> IO ()++-- | /butterfly_rshB/ /t/ /u/ /i1/ /i2/ /limbs/ /x/ /y/ +--+-- We are given two integers @i1@ and @i2@ modulo @B^limbs + 1@ which are+-- not necessarily normalised. We compute @t = (i1 + i2)\/B^x@ and+-- @u = (i1 - i2)\/B^y@ modulo \(p\). Aliasing between inputs and outputs+-- is not permitted. We require @x@ and @y@ to be less than @limbs@ and+-- nonnegative.+foreign import ccall "fft.h butterfly_rshB"+ butterfly_rshB :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CMpSize -> CMpSize -> IO ()++-- Radix 2 transforms ----------------------------------------------------------++-- | /fft_butterfly/ /s/ /t/ /i1/ /i2/ /i/ /limbs/ /w/ +--+-- Set @s = i1 + i2@, @t = z1^i*(i1 - i2)@ modulo @B^limbs + 1@ where+-- @z1 = exp(Pi*I\/n)@ corresponds to multiplication by \(2^w\). Requires+-- \(0 \leq i < n\) where \(nw =\) @limbs*FLINT_BITS@.+foreign import ccall "fft.h fft_butterfly"+ fft_butterfly :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CMpSize -> CFBitCnt -> IO ()++-- | /ifft_butterfly/ /s/ /t/ /i1/ /i2/ /i/ /limbs/ /w/ +--+-- Set @s = i1 + z1^i*i2@, @t = i1 - z1^i*i2@ modulo @B^limbs + 1@ where+-- @z1 = exp(-Pi*I\/n)@ corresponds to division by \(2^w\). Requires+-- \(0 \leq i < 2n\) where \(nw =\) @limbs*FLINT_BITS@.+foreign import ccall "fft.h ifft_butterfly"+ ifft_butterfly :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CMpSize -> CFBitCnt -> IO ()++-- | /fft_radix2/ /ii/ /n/ /w/ /t1/ /t2/ +--+-- The radix 2 DIF FFT works as follows:+-- +-- Input: @[i0, i1, ..., i(m-1)]@, for \(m = 2n\) a power of \(2\).+-- +-- Output: @[r0, r1, ..., r(m-1)]@ @= FFT[i0, i1, ..., i(m-1)]@.+-- +-- Algorithm:+-- +-- \(\bullet\) Recursively compute @[r0, r2, r4, ...., r(m-2)]@+-- @= FFT[i0+i(m\/2), i1+i(m\/2+1), ..., i(m\/2-1)+i(m-1)]@+-- \(\bullet\) Let @[t0, t1, ..., t(m\/2-1)]@+-- @= [i0-i(m\/2), i1-i(m\/2+1), ..., i(m\/2-1)-i(m-1)]@+-- \(\bullet\) Let @[u0, u1, ..., u(m\/2-1)]@+-- @= [z1^0*t0, z1^1*t1, ..., z1^(m\/2-1)*t(m\/2-1)]@+-- where @z1 = exp(2*Pi*I\/m)@ corresponds to multiplication by+-- \(2^w\).+-- \(\bullet\) Recursively compute @[r1, r3, ..., r(m-1)]@+-- @= FFT[u0, u1, ..., u(m\/2-1)]@+-- +-- The parameters are as follows:+-- +-- \(\bullet\) @2*n@ is the length of the input and output arrays+-- +-- [\(\bullet\) \(w\) is such that \(2^w\) is an \(2n\)-th root of unity in the ring \(\mathbf{Z}/p\mathbf{Z}\) that we are working in, i.e. \(p = 2^{wn} + 1\) (here \(n\) is divisible by]+-- @GMP_LIMB_BITS@)+-- +-- [\(\bullet\) @ii@ is the array of inputs (each input is an]+-- array of limbs of length @wn\/GMP_LIMB_BITS + 1@ (the extra limbs+-- being a \"carry limb\"). Outputs are written in-place.+-- +-- We require \(nw\) to be at least 64 and the two temporary space pointers+-- to point to blocks of size @n*w + FLINT_BITS@ bits.+foreign import ccall "fft.h fft_radix2"+ fft_radix2 :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> IO ()++-- | /fft_truncate/ /ii/ /n/ /w/ /t1/ /t2/ /trunc/ +--+-- As for @fft_radix2@ except that only the first @trunc@ coefficients of+-- the output are computed and the input is regarded as having (implied)+-- zero coefficients from coefficient @trunc@ onwards. The coefficients+-- must exist as the algorithm needs to use this extra space, but their+-- value is irrelevant. The value of @trunc@ must be divisible by 2.+foreign import ccall "fft.h fft_truncate"+ fft_truncate :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> IO ()++-- | /fft_truncate1/ /ii/ /n/ /w/ /t1/ /t2/ /trunc/ +--+-- As for @fft_radix2@ except that only the first @trunc@ coefficients of+-- the output are computed. The transform still needs all \(2n\) input+-- coefficients to be specified.+foreign import ccall "fft.h fft_truncate1"+ fft_truncate1 :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> IO ()++-- | /ifft_radix2/ /ii/ /n/ /w/ /t1/ /t2/ +--+-- The radix 2 DIF IFFT works as follows:+-- +-- Input: @[i0, i1, ..., i(m-1)]@, for \(m = 2n\) a power of \(2\).+-- +-- [Output: @[r0, r1, ..., r(m-1)]@]+-- @= IFFT[i0, i1, ..., i(m-1)]@.+-- +-- Algorithm:+-- +-- [\(\bullet\) Recursively compute @[s0, s1, ...., s(m\/2-1)]@]+-- @= IFFT[i0, i2, ..., i(m-2)]@+-- +-- [\(\bullet\) Recursively compute @[t(m\/2), t(m\/2+1), ..., t(m-1)]@]+-- @= IFFT[i1, i3, ..., i(m-1)]@+-- +-- [\(\bullet\) Let @[r0, r1, ..., r(m\/2-1)]@]+-- @= [s0+z1^0*t0, s1+z1^1*t1, ..., s(m\/2-1)+z1^(m\/2-1)*t(m\/2-1)]@+-- where @z1 = exp(-2*Pi*I\/m)@ corresponds to division by \(2^w\).+-- +-- [\(\bullet\) Let @[r(m\/2), r(m\/2+1), ..., r(m-1)]@]+-- @= [s0-z1^0*t0, s1-z1^1*t1, ..., s(m\/2-1)-z1^(m\/2-1)*t(m\/2-1)]@+-- +-- The parameters are as follows:+-- +-- [\(\bullet\) @2*n@ is the length of the input and output]+-- arrays+-- +-- [\(\bullet\) \(w\) is such that \(2^w\) is an \(2n\)-th root of unity in the ring \(\mathbf{Z}/p\mathbf{Z}\) that we are working in, i.e. \(p = 2^{wn} + 1\) (here \(n\) is divisible by]+-- @GMP_LIMB_BITS@)+-- +-- \(\bullet\) @ii@ is the array of inputs (each input is an array of limbs+-- of length @wn\/GMP_LIMB_BITS + 1@ (the extra limbs being a \"carry+-- limb\"). Outputs are written in-place.+-- +-- We require \(nw\) to be at least 64 and the two temporary space pointers+-- to point to blocks of size @n*w + FLINT_BITS@ bits.+foreign import ccall "fft.h ifft_radix2"+ ifft_radix2 :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> IO ()++-- | /ifft_truncate/ /ii/ /n/ /w/ /t1/ /t2/ /trunc/ +--+-- As for @ifft_radix2@ except that the output is assumed to have zeros+-- from coefficient trunc onwards and only the first trunc coefficients of+-- the input are specified. The remaining coefficients need to exist as the+-- extra space is needed, but their value is irrelevant. The value of+-- @trunc@ must be divisible by 2.+-- +-- Although the implementation does not require it, we assume for+-- simplicity that @trunc@ is greater than \(n\). The algorithm begins by+-- computing the inverse transform of the first \(n\) coefficients of the+-- input array. The unspecified coefficients of the second half of the+-- array are then written: coefficient @trunc + i@ is computed as a twist+-- of coefficient @i@ by a root of unity. The values of these coefficients+-- are then equal to what they would have been if the inverse transform of+-- the right hand side of the input array had been computed with full data+-- from the start. The function @ifft_truncate1@ is then called on the+-- entire right half of the input array with this auxiliary data filled in.+-- Finally a single layer of the IFFT is completed on all the coefficients+-- up to @trunc@ being careful to note that this involves doubling the+-- coefficients from @trunc - n@ up to @n@.+foreign import ccall "fft.h ifft_truncate"+ ifft_truncate :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> IO ()++-- | /ifft_truncate1/ /ii/ /n/ /w/ /t1/ /t2/ /trunc/ +--+-- Computes the first @trunc@ coefficients of the radix 2 inverse transform+-- assuming the first @trunc@ coefficients are given and that the remaining+-- coefficients have been set to the value they would have if an inverse+-- transform had already been applied with full data.+-- +-- The algorithm is the same as for @ifft_truncate@ except that the+-- coefficients from @trunc@ onwards after the inverse transform are not+-- inferred to be zero but the supplied values.+foreign import ccall "fft.h ifft_truncate1"+ ifft_truncate1 :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> IO ()++-- | /fft_butterfly_sqrt2/ /s/ /t/ /i1/ /i2/ /i/ /limbs/ /w/ /temp/ +--+-- Let \(w = 2k + 1\), \(i = 2j + 1\). Set @s = i1 + i2@,+-- @t = z1^i*(i1 - i2)@ modulo @B^limbs + 1@ where @z1^2 = exp(Pi*I\/n)@+-- corresponds to multiplication by \(2^w\). Requires \(0 \leq i < 2n\)+-- where \(nw =\) @limbs*FLINT_BITS@.+-- +-- Here @z1@ corresponds to multiplication by \(2^k\) then multiplication+-- by @(2^(3nw\/4) - 2^(nw\/4))@. We see @z1^i@ corresponds to+-- multiplication by @(2^(3nw\/4) - 2^(nw\/4))*2^(j+ik)@.+-- +-- We first multiply by @2^(j + ik + wn\/4)@ then multiply by an additional+-- @2^(nw\/2)@ and subtract.+foreign import ccall "fft.h fft_butterfly_sqrt2"+ fft_butterfly_sqrt2 :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CMpSize -> CFBitCnt -> Ptr CMpLimb -> IO ()++-- | /ifft_butterfly_sqrt2/ /s/ /t/ /i1/ /i2/ /i/ /limbs/ /w/ /temp/ +--+-- Let \(w = 2k + 1\), \(i = 2j + 1\). Set @s = i1 + z1^i*i2@,+-- @t = i1 - z1^i*i2@ modulo @B^limbs + 1@ where @z1^2 = exp(-Pi*I\/n)@+-- corresponds to division by \(2^w\). Requires \(0 \leq i < 2n\) where+-- \(nw =\) @limbs*FLINT_BITS@.+-- +-- Here @z1@ corresponds to division by \(2^k\) then division by+-- @(2^(3nw\/4) - 2^(nw\/4))@. We see @z1^i@ corresponds to division by+-- @(2^(3nw\/4) - 2^(nw\/4))*2^(j+ik)@ which is the same as division by+-- @2^(j+ik + 1)@ then multiplication by @(2^(3nw\/4) - 2^(nw\/4))@.+-- +-- Of course, division by @2^(j+ik + 1)@ is the same as multiplication by+-- @2^(2*wn - j - ik - 1)@. The exponent is positive as+-- \(i \leq 2\cdot n\), \(j < n\), \(k < w/2\).+-- +-- We first multiply by @2^(2*wn - j - ik - 1 + wn\/4)@ then multiply by an+-- additional @2^(nw\/2)@ and subtract.+foreign import ccall "fft.h ifft_butterfly_sqrt2"+ ifft_butterfly_sqrt2 :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CMpSize -> CFBitCnt -> Ptr CMpLimb -> IO ()++-- | /fft_truncate_sqrt2/ /ii/ /n/ /w/ /t1/ /t2/ /temp/ /trunc/ +--+-- As per @fft_truncate@ except that the transform is twice the usual+-- length, i.e. length \(4n\) rather than \(2n\). This is achieved by+-- making use of twiddles by powers of a square root of 2, not powers of 2+-- in the first layer of the transform.+-- +-- We require \(nw\) to be at least 64 and the three temporary space+-- pointers to point to blocks of size @n*w + FLINT_BITS@ bits.+foreign import ccall "fft.h fft_truncate_sqrt2"+ fft_truncate_sqrt2 :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> IO ()++-- | /ifft_truncate_sqrt2/ /ii/ /n/ /w/ /t1/ /t2/ /temp/ /trunc/ +--+-- As per @ifft_truncate@ except that the transform is twice the usual+-- length, i.e. length \(4n\) instead of \(2n\). This is achieved by making+-- use of twiddles by powers of a square root of 2, not powers of 2 in the+-- final layer of the transform.+-- +-- We require \(nw\) to be at least 64 and the three temporary space+-- pointers to point to blocks of size @n*w + FLINT_BITS@ bits.+foreign import ccall "fft.h ifft_truncate_sqrt2"+ ifft_truncate_sqrt2 :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> IO ()++-- Matrix Fourier Transforms ---------------------------------------------------++-- | /fft_butterfly_twiddle/ /u/ /v/ /s/ /t/ /limbs/ /b1/ /b2/ +--+-- Set @u = 2^b1*(s + t)@, @v = 2^b2*(s - t)@ modulo @B^limbs + 1@. This is+-- used to compute @u = 2^(ws*tw1)*(s + t)@, @v = 2^(w+ws*tw2)*(s - t)@ in+-- the matrix Fourier algorithm, i.e. effectively computing an ordinary+-- butterfly with additional twiddles by @z1^rc@ for row \(r\) and column+-- \(c\) of the matrix of coefficients. Aliasing is not allowed.+foreign import ccall "fft.h fft_butterfly_twiddle"+ fft_butterfly_twiddle :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CFBitCnt -> CFBitCnt -> IO ()++-- | /ifft_butterfly_twiddle/ /u/ /v/ /s/ /t/ /limbs/ /b1/ /b2/ +--+-- Set @u = s\/2^b1 + t\/2^b1)@, @v = s\/2^b1 - t\/2^b1@ modulo+-- @B^limbs + 1@. This is used to compute+-- @u = 2^(-ws*tw1)*s + 2^(-ws*tw2)*t)@,+-- @v = 2^(-ws*tw1)*s + 2^(-ws*tw2)*t)@ in the matrix Fourier algorithm,+-- i.e. effectively computing an ordinary butterfly with additional+-- twiddles by @z1^(-rc)@ for row \(r\) and column \(c\) of the matrix of+-- coefficients. Aliasing is not allowed.+foreign import ccall "fft.h ifft_butterfly_twiddle"+ ifft_butterfly_twiddle :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CFBitCnt -> CFBitCnt -> IO ()++-- | /fft_radix2_twiddle/ /ii/ /is/ /n/ /w/ /t1/ /t2/ /ws/ /r/ /c/ /rs/ +--+-- As for @fft_radix2@ except that the coefficients are spaced by @is@ in+-- the array @ii@ and an additional twist by @z^c*i@ is applied to each+-- coefficient where \(i\) starts at \(r\) and increases by @rs@ as one+-- moves from one coefficient to the next. Here @z@ corresponds to+-- multiplication by @2^ws@.+foreign import ccall "fft.h fft_radix2_twiddle"+ fft_radix2_twiddle :: Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> CMpSize -> CMpSize -> IO ()++-- | /ifft_radix2_twiddle/ /ii/ /is/ /n/ /w/ /t1/ /t2/ /ws/ /r/ /c/ /rs/ +--+-- As for @ifft_radix2@ except that the coefficients are spaced by @is@ in+-- the array @ii@ and an additional twist by @z^(-c*i)@ is applied to each+-- coefficient where \(i\) starts at \(r\) and increases by @rs@ as one+-- moves from one coefficient to the next. Here @z@ corresponds to+-- multiplication by @2^ws@.+foreign import ccall "fft.h ifft_radix2_twiddle"+ ifft_radix2_twiddle :: Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> CMpSize -> CMpSize -> IO ()++-- | /fft_truncate1_twiddle/ /ii/ /is/ /n/ /w/ /t1/ /t2/ /ws/ /r/ /c/ /rs/ /trunc/ +--+-- As per @fft_radix2_twiddle@ except that the transform is truncated as+-- per @fft_truncate1@.+foreign import ccall "fft.h fft_truncate1_twiddle"+ fft_truncate1_twiddle :: Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> CMpSize -> CMpSize -> CMpSize -> IO ()++-- | /ifft_truncate1_twiddle/ /ii/ /is/ /n/ /w/ /t1/ /t2/ /ws/ /r/ /c/ /rs/ /trunc/ +--+-- As per @ifft_radix2_twiddle@ except that the transform is truncated as+-- per @ifft_truncate1@.+foreign import ccall "fft.h ifft_truncate1_twiddle"+ ifft_truncate1_twiddle :: Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> CMpSize -> CMpSize -> CMpSize -> IO ()++-- | /fft_mfa_truncate_sqrt2/ /ii/ /n/ /w/ /t1/ /t2/ /temp/ /n1/ /trunc/ +--+-- This is as per the @fft_truncate_sqrt2@ function except that the matrix+-- Fourier algorithm is used for the left and right FFTs. The total+-- transform length is \(4n\) where @n = 2^depth@ so that the left and+-- right transforms are both length \(2n\). We require @trunc > 2*n@ and+-- that @trunc@ is divisible by @2*n1@ (explained below). The coefficients+-- are produced in an order different from @fft_truncate_sqrt2@.+-- +-- The matrix Fourier algorithm, which is applied to each transform of+-- length \(2n\), works as follows. We set @n1@ to a power of 2 about the+-- square root of \(n\). The data is then thought of as a set of @n2@ rows+-- each with @n1@ columns (so that @n1*n2 = 2n@).+-- +-- The length \(2n\) transform is then computed using a whole pile of short+-- transforms. These comprise @n1@ column transforms of length @n2@+-- followed by some twiddles by roots of unity (namely @z^rc@ where \(r\)+-- is the row and \(c\) the column within the data) followed by @n2@ row+-- transforms of length @n1@. Along the way the data needs to be rearranged+-- due to the fact that the short transforms output the data in binary+-- reversed order compared with what is needed.+-- +-- The matrix Fourier algorithm provides better cache locality by+-- decomposing the long length \(2n\) transforms into many transforms of+-- about the square root of the original length.+-- +-- For better cache locality the sqrt2 layer of the full length \(4n\)+-- transform is folded in with the column FFTs performed as part of the+-- first matrix Fourier algorithm on the left half of the data.+-- +-- The second half of the data requires a truncated version of the matrix+-- Fourier algorithm. This is achieved by truncating to an exact multiple+-- of the row length so that the row transforms are full length. Moreover,+-- the column transforms will then be truncated transforms and their+-- truncated length needs to be a multiple of 2. This explains the+-- condition on @trunc@ given above.+-- +-- To improve performance, the extra twiddles by roots of unity are+-- combined with the butterflies performed at the last layer of the column+-- transforms.+-- +-- We require \(nw\) to be at least 64 and the three temporary space+-- pointers to point to blocks of size @n*w + FLINT_BITS@ bits.+foreign import ccall "fft.h fft_mfa_truncate_sqrt2"+ fft_mfa_truncate_sqrt2 :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> IO ()++-- | /ifft_mfa_truncate_sqrt2/ /ii/ /n/ /w/ /t1/ /t2/ /temp/ /n1/ /trunc/ +--+-- This is as per the @ifft_truncate_sqrt2@ function except that the matrix+-- Fourier algorithm is used for the left and right IFFTs. The total+-- transform length is \(4n\) where @n = 2^depth@ so that the left and+-- right transforms are both length \(2n\). We require @trunc > 2*n@ and+-- that @trunc@ is divisible by @2*n1@.+-- +-- We set @n1@ to a power of 2 about the square root of \(n\).+-- +-- As per the matrix fourier FFT the sqrt2 layer is folded into the final+-- column IFFTs for better cache locality and the extra twiddles that occur+-- in the matrix Fourier algorithm are combined with the butterflied+-- performed at the first layer of the final column transforms.+-- +-- We require \(nw\) to be at least 64 and the three temporary space+-- pointers to point to blocks of size @n*w + FLINT_BITS@ bits.+foreign import ccall "fft.h ifft_mfa_truncate_sqrt2"+ ifft_mfa_truncate_sqrt2 :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> IO ()++-- | /fft_mfa_truncate_sqrt2_outer/ /ii/ /n/ /w/ /t1/ /t2/ /temp/ /n1/ /trunc/ +--+-- Just the outer layers of @fft_mfa_truncate_sqrt2@.+foreign import ccall "fft.h fft_mfa_truncate_sqrt2_outer"+ fft_mfa_truncate_sqrt2_outer :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> IO ()++-- | /fft_mfa_truncate_sqrt2_inner/ /ii/ /jj/ /n/ /w/ /t1/ /t2/ /temp/ /n1/ /trunc/ /tt/ +--+-- The inner layers of @fft_mfa_truncate_sqrt2@ and+-- @ifft_mfa_truncate_sqrt2@ combined with pointwise mults.+foreign import ccall "fft.h fft_mfa_truncate_sqrt2_inner"+ fft_mfa_truncate_sqrt2_inner :: Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> Ptr CMpLimb -> IO ()++-- | /ifft_mfa_truncate_sqrt2_outer/ /ii/ /n/ /w/ /t1/ /t2/ /temp/ /n1/ /trunc/ +--+-- The outer layers of @ifft_mfa_truncate_sqrt2@ combined with+-- normalisation.+foreign import ccall "fft.h ifft_mfa_truncate_sqrt2_outer"+ ifft_mfa_truncate_sqrt2_outer :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CMpSize -> CMpSize -> IO ()++-- Negacyclic multiplication ---------------------------------------------------++-- | /fft_negacyclic/ /ii/ /n/ /w/ /t1/ /t2/ /temp/ +--+-- As per @fft_radix2@ except that it performs a sqrt2 negacyclic transform+-- of length \(2n\). This is the same as the radix 2 transform except that+-- the \(i\)-th coefficient of the input is first multiplied by+-- \(\sqrt{2}^{iw}\).+-- +-- We require \(nw\) to be at least 64 and the two temporary space pointers+-- to point to blocks of size @n*w + FLINT_BITS@ bits.+foreign import ccall "fft.h fft_negacyclic"+ fft_negacyclic :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> IO ()++-- | /ifft_negacyclic/ /ii/ /n/ /w/ /t1/ /t2/ /temp/ +--+-- As per @ifft_radix2@ except that it performs a sqrt2 negacyclic inverse+-- transform of length \(2n\). This is the same as the radix 2 inverse+-- transform except that the \(i\)-th coefficient of the output is finally+-- divided by \(\sqrt{2}^{iw}\).+-- +-- We require \(nw\) to be at least 64 and the two temporary space pointers+-- to point to blocks of size @n*w + FLINT_BITS@ bits.+foreign import ccall "fft.h ifft_negacyclic"+ ifft_negacyclic :: Ptr (Ptr CMpLimb) -> CMpSize -> CFBitCnt -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> IO ()++-- | /fft_naive_convolution_1/ /r/ /ii/ /jj/ /m/ +--+-- Performs a naive negacyclic convolution of @ii@ with @jj@, both of+-- length \(m\), and sets \(r\) to the result. This is essentially+-- multiplication of polynomials modulo \(x^m + 1\).+foreign import ccall "fft.h fft_naive_convolution_1"+ fft_naive_convolution_1 :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> IO ()++-- | /_fft_mulmod_2expp1/ /r1/ /i1/ /i2/ /r_limbs/ /depth/ /w/ +--+-- Multiply @i1@ by @i2@ modulo @B^r_limbs + 1@ where+-- @r_limbs = nw\/FLINT_BITS@ with @n = 2^depth@. Uses the negacyclic FFT+-- convolution CRT\'d with a 1 limb naive convolution. We require that+-- @depth@ and @w@ have been selected as per the wrapper+-- @fft_mulmod_2expp1@ below.+foreign import ccall "fft.h _fft_mulmod_2expp1"+ _fft_mulmod_2expp1 :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CFBitCnt -> CFBitCnt -> IO ()++-- | /fft_adjust_limbs/ /limbs/ +--+-- Given a number of limbs, returns a new number of limbs (no more than the+-- next power of 2) which will work with the Nussbaumer code. It is only+-- necessary to make this adjustment if @limbs > FFT_MULMOD_2EXPP1_CUTOFF@.+foreign import ccall "fft.h fft_adjust_limbs"+ fft_adjust_limbs :: CMpSize -> IO CLong++-- | /fft_mulmod_2expp1/ /r/ /i1/ /i2/ /n/ /w/ /tt/ +--+-- As per @_fft_mulmod_2expp1@ but with a tuned cutoff below which more+-- classical methods are used for the convolution. The temporary space is+-- required to fit @n*w + FLINT_BITS@ bits. There are no restrictions on+-- \(n\), but if @limbs = n*w\/FLINT_BITS@ then if @limbs@ exceeds+-- @FFT_MULMOD_2EXPP1_CUTOFF@ the function @fft_adjust_limbs@ must be+-- called to increase the number of limbs to an appropriate value.+foreign import ccall "fft.h fft_mulmod_2expp1"+ fft_mulmod_2expp1 :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CMpLimb -> CMpSize -> CMpSize -> Ptr CMpLimb -> IO ()++-- Integer multiplication ------------------------------------------------------++-- | /mul_truncate_sqrt2/ /r1/ /i1/ /n1/ /i2/ /n2/ /depth/ /w/ +--+-- Integer multiplication using the radix 2 truncated sqrt2 transforms.+-- +-- Set @(r1, n1 + n2)@ to the product of @(i1, n1)@ by @(i2, n2)@. This is+-- achieved through an FFT convolution of length at most @2^(depth + 2)@+-- with coefficients of size \(nw\) bits where @n = 2^depth@. We require+-- @depth >= 6@. The input data is broken into chunks of data not exceeding+-- @(nw - (depth + 1))\/2@ bits. If breaking the first integer into chunks+-- of this size results in @j1@ coefficients and breaking the second+-- integer results in @j2@ chunks then @j1 + j2 - 1 \<= 2^(depth + 2)@.+-- +-- If @n = 2^depth@ then we require \(nw\) to be at least 64.+foreign import ccall "fft.h mul_truncate_sqrt2"+ mul_truncate_sqrt2 :: Ptr CMp -> Ptr CMp -> CMpSize -> Ptr CMp -> CMpSize -> CFBitCnt -> CFBitCnt -> IO ()++-- | /mul_mfa_truncate_sqrt2/ /r1/ /i1/ /n1/ /i2/ /n2/ /depth/ /w/ +--+-- As for @mul_truncate_sqrt2@ except that the cache friendly matrix+-- Fourier algorithm is used.+-- +-- If @n = 2^depth@ then we require \(nw\) to be at least 64. Here we also+-- require \(w\) to be \(2^i\) for some \(i \geq 0\).+foreign import ccall "fft.h mul_mfa_truncate_sqrt2"+ mul_mfa_truncate_sqrt2 :: Ptr CMp -> Ptr CMp -> CMpSize -> Ptr CMp -> CMpSize -> CFBitCnt -> CFBitCnt -> IO ()++-- | /flint_mpn_mul_fft_main/ /r1/ /i1/ /n1/ /i2/ /n2/ +--+-- The main integer multiplication routine. Sets @(r1, n1 + n2)@ to+-- @(i1, n1)@ times @(i2, n2)@. We require @n1 >= n2 > 0@.+foreign import ccall "fft.h flint_mpn_mul_fft_main"+ flint_mpn_mul_fft_main :: Ptr CMp -> Ptr CMp -> CMpSize -> Ptr CMp -> CMpSize -> IO ()++-- Convolution -----------------------------------------------------------------++-- | /fft_convolution/ /ii/ /jj/ /depth/ /limbs/ /trunc/ /t1/ /t2/ /s1/ /tt/ +--+-- Perform an FFT convolution of @ii@ with @jj@, both of length @4*n@ where+-- @n = 2^depth@. Assume that all but the first @trunc@ coefficients of the+-- output (placed in @ii@) are zero. Each coefficient is taken modulo+-- @B^limbs + 1@. The temporary spaces @t1@, @t2@ and @s1@ must have+-- @limbs + 1@ limbs of space and @tt@ must have @2*(limbs + 1)@ of free+-- space.+foreign import ccall "fft.h fft_convolution"+ fft_convolution :: Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CLong -> CLong -> CLong -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr CMpLimb -> IO ()++-- FFT Precaching --------------------------------------------------------------++-- | /fft_precache/ /jj/ /depth/ /limbs/ /trunc/ /t1/ /t2/ /s1/ +--+-- Precompute the FFT of @jj@ for use with precache functions. The+-- parameters are as for @fft_convolution@.+foreign import ccall "fft.h fft_precache"+ fft_precache :: Ptr (Ptr CMpLimb) -> CLong -> CLong -> CLong -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> IO ()++-- | /fft_convolution_precache/ /ii/ /jj/ /depth/ /limbs/ /trunc/ /t1/ /t2/ /s1/ /tt/ +--+-- As per @fft_convolution@ except that it is assumed @fft_precache@ has+-- been called on @jj@ with the same parameters. This will then run faster+-- than if @fft_convolution@ had been run with the original @jj@.+foreign import ccall "fft.h fft_convolution_precache"+ fft_convolution_precache :: Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> CLong -> CLong -> CLong -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> Ptr (Ptr CMpLimb) -> IO ()+
+ src/Data/Number/Flint/Flint.hs view
@@ -0,0 +1,17 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+{-|+module : Data.Number.Flint.Flint+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Flint (+ module Data.Number.Flint.Flint.FFI+, module Data.Number.Flint.Flint.Internal+, module Data.Number.Flint.Flint.External+) where++import Data.Number.Flint.Flint.FFI+import Data.Number.Flint.Flint.Internal+import Data.Number.Flint.Flint.External
+ src/Data/Number/Flint/Flint/External.hs view
@@ -0,0 +1,9 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}++module Data.Number.Flint.Flint.External (+ module Data.Number.Flint.Flint.External.GMP.FFI+, module Data.Number.Flint.Flint.External.Mpfr.FFI +) where++import Data.Number.Flint.Flint.External.GMP.FFI+import Data.Number.Flint.Flint.External.Mpfr.FFI
+ src/Data/Number/Flint/Flint/External/GMP/FFI.hsc view
@@ -0,0 +1,54 @@+{-|+module : Data.Number.Flint.Flint.External.GMP.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Flint.External.GMP.FFI where++import Data.Int+import Data.Word+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.Storable++import Data.Number.Flint.Flint.Internal++#undef _LONG_LONG_LIMB++#include <gmp.h>++-- BUG: should be set by #type mp_limb_t+-- type MpLimb = CULong+type CMpLimb = #type mp_limb_t+type CMpSLimb = #type mp_limb_signed_t+type CMpSize = #type mp_size_t+type CMpBitCnt = #type mp_bitcnt_t++-- | Data structure containing the CMp pointer+data Mp = CMp {-# UNPACK #-} !(ForeignPtr CMp) +type CMp = CFlint Mp++-- | Data structure containing the CMpz pointer+data Mpz = CMpz {-# UNPACK #-} !(ForeignPtr CMpz) +type CMpz = CFlint Mpz++-- | Data structure containing the CMpq pointer+data Mpq = CMpq {-# UNPACK #-} !(ForeignPtr CMpq) +type CMpq = CFlint Mpq++-- | Data structure containing the CMpf pointer+data Mpf = CMpf {-# UNPACK #-} !(ForeignPtr CMpf) +type CMpf = CFlint Mpf++-- | Data structure containing the CGmpRandstate pointer+data GmpRandstate = GmpRandstate {-# UNPACK #-} !(ForeignPtr CGmpRandstate)+type CGmpRandstate = CFlint GmpRandstate++instance Storable CMpf where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size mpf_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment mpf_t}+ peek = undefined+ poke = undefined
+ src/Data/Number/Flint/Flint/External/Mpfr/FFI.hsc view
@@ -0,0 +1,33 @@+{-|+module : Data.Number.Flint.Flint.External.Mpfr.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Flint.External.Mpfr.FFI where++import Data.Word+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Storable++import Data.Number.Flint.Flint.Internal++#include <mpfr.h>++-- MPFR ------------------------------------------------------------------------++-- | Data structure containing the CMpfr pointer+data Mpfr = CMpfr {-# UNPACK #-} !(ForeignPtr CMpfr) +type CMpfr = CFlint Mpfr++newtype CMpfrRnd = CMpfrRnd {_MpfrRnd :: CInt} deriving (Show, Eq)+newtype CMpfrPrec = CMpfrPrec {_MpfrPrec :: CInt} deriving (Show, Eq)++instance Storable CMpfr where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size mpfr_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment mpfr_t}+ peek = undefined+ poke = undefined
+ src/Data/Number/Flint/Flint/FFI.hsc view
@@ -0,0 +1,191 @@+{-|+module : Data.Number.Flint.Flint.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Flint.FFI (+ -- * Allocation Functions+ flint_malloc+ , flint_realloc+ , flint_calloc+ -- * Constants+ , flint_bits+ -- * Random Numbers+ , FRandState (..)+ , CFRandState (..)+ , newFRandState+ , withFRandState+ , flint_rand_alloc+ , flint_rand_free+ , flint_randinit+ , flint_randclear+ -- * Thread functions+ , flint_set_num_threads+ , flint_get_num_threads+ , flint_set_num_workers+ , flint_reset_num_workers+) where ++-- global definitions ----------------------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint.Internal++#include <flint/flint.h>++-- Allocation Functions --------------------------------------------------------++-- | /flint_malloc/ /size/ +-- +-- Allocate @size@ bytes of memory.+foreign import ccall "flint.h flint_malloc"+ flint_malloc :: Ptr CSize -> IO ()++-- | /flint_realloc/ /ptr/ /size/ +-- +-- Reallocate an area of memory previously allocated by @flint_malloc@,+-- @flint_realloc@, or @flint_calloc@.+foreign import ccall "flint.h flint_realloc"+ flint_realloc :: Ptr () -> Ptr CSize -> IO ()++-- | /flint_calloc/ /num/ /size/ +-- +-- Allocate @num@ objects of @size@ bytes each, and zero the allocated+-- memory.+foreign import ccall "flint.h flint_calloc"+ flint_calloc :: Ptr CSize -> Ptr CSize -> IO ()++-- Constants -------------------------------------------------------------------++flint_release :: CULong+flint_release = #const __FLINT_RELEASE+flint_bits :: CULong+flint_bits = #const FLINT_BITS+flint_d_bits :: CULong+flint_d_bits = #const FLINT_D_BITS++-- Random Numbers --------------------------------------------------------------++data FRandState = FRandState {-# UNPACK #-} !(ForeignPtr CFRandState)+type CFRandState = CFlint FRandState++instance Storable CFRandState where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size flint_rand_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment flint_rand_t}+ peek = error "CFRandState.peek: Not defined"+ poke = error "CFRandState.poke: Not defined"++newFRandState = do+ p <- mallocForeignPtr+ withForeignPtr p flint_randinit+ addForeignPtrFinalizer p_flint_randclear p+ return $ FRandState p++{-# INLINE withFRandState #-}+withFRandState (FRandState p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FRandState p,)++--------------------------------------------------------------------------------++-- | /flint_rand_alloc/ +-- +-- Allocates a @flint_rand_t@ object to be used like a heap-allocated+-- @flint_rand_t@ in external libraries. The random state is not+-- initialised.+foreign import ccall "flint.h flint_rand_alloc"+ flint_rand_alloc :: IO (Ptr CFRandState)++-- | /flint_rand_free/ /state/ +-- +-- Frees a random state object as allocated using @flint_rand_alloc@.+foreign import ccall "flint.h flint_rand_free"+ flint_rand_free :: Ptr CFRandState -> IO ()++-- | /flint_randinit/ /state/ +-- +-- Initialize a @flint_rand_t@.+foreign import ccall "flint.h flint_randinit"+ flint_randinit :: Ptr CFRandState -> IO ()++-- | /flint_randclear/ /state/ +-- +-- Free all memory allocated by @flint_rand_init@.+foreign import ccall "flint.h flint_randclear"+ flint_randclear :: Ptr CFRandState -> IO ()++foreign import ccall "flint.h &flint_randclear"+ p_flint_randclear :: FunPtr (Ptr CFRandState -> IO ())++-- Thread functions ------------------------------------------------------------++-- | /flint_set_num_threads/ /num_threads/ +-- +-- Set up a thread pool of @num_threads - 1@ worker threads (in addition to+-- the master thread) and set the maximum number of worker threads the+-- master thread can start to @num_threads - 1@.+-- +-- This function may only be called globally from the master thread. It can+-- also be called at a global level to change the size of the thread pool,+-- but an exception is raised if the thread pool is in use (threads have+-- been woken but not given back). The function cannot be called from+-- inside worker threads.+foreign import ccall "flint.h flint_set_num_threads"+ flint_set_num_threads :: CInt -> IO ()++-- | /flint_get_num_threads/ +-- +-- When called at the global level, this function returns one more than the+-- number of worker threads in the Flint thread pool, i.e. it counts the+-- workers in the thread pool plus one more for the master thread.+-- +-- In general, this function returns one more than the number of additional+-- worker threads that can be started by the current thread.+-- +-- Use @thread_pool_wake@ to set this number for a given worker thread.+foreign import ccall "flint.h flint_get_num_threads"+ flint_get_num_threads :: IO ()++-- | /flint_set_num_workers/ /num_workers/ +-- +-- Restricts the number of worker threads that can be started by the+-- current thread to @num_workers@. This function can be called from any+-- thread.+-- +-- Assumes that the Flint thread pool is already set up.+-- +-- The function returns the old number of worker threads that can be+-- started.+-- +-- The function can only be used to reduce the number of workers that can+-- be started from a thread. It cannot be used to increase the number. If a+-- higher number is passed, the function has no effect.+-- +-- The number of workers must be restored to the original value by a call+-- to @flint_reset_num_workers@ before the thread is returned to the thread+-- pool.+-- +-- The main use of this function and @flint_reset_num_workers@ is to+-- cheaply and temporarily restrict the number of workers that can be+-- started, e.g. by a function that one wishes to call from a thread, and+-- cheaply restore the number of workers to its original value before+-- exiting the current thread.+foreign import ccall "flint.h flint_set_num_workers"+ flint_set_num_workers :: CInt -> IO CInt++-- | /flint_reset_num_workers/ /num_workers/ +-- +-- After a call to @flint_set_num_workers@ this function must be called to+-- set the number of workers that may be started by the current thread back+-- to its original value.+foreign import ccall "flint.h flint_reset_num_workers"+ flint_reset_num_workers :: CInt -> IO ()+
+ src/Data/Number/Flint/Flint/Internal.hs view
@@ -0,0 +1,7 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}++module Data.Number.Flint.Flint.Internal (+ module Data.Number.Flint.Flint.Internal.FFI+) where++import Data.Number.Flint.Flint.Internal.FFI
+ src/Data/Number/Flint/Flint/Internal/FFI.hsc view
@@ -0,0 +1,53 @@+{-|+module : Data.Number.Flint.Flint.Internal.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Flint.Internal.FFI (+ Flint (..)+ , CFlint (..)+ , printCStr+ , printCVec+ , CFBitCnt+) where++import Foreign.C.String (CString (..), peekCString)+import Foreign.C.Types+import Foreign.Marshal.Alloc (free)+import Foreign.Marshal.Array (advancePtr)+import Foreign.ForeignPtr +import Foreign.Ptr +import Foreign.Storable++import Control.Monad+import Data.Word++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_factor.h>++class Flint a where+ data CFlint a :: *++-- output ----------------------------------------------------------------------++printCStr :: (Ptr a -> IO CString) -> Ptr a -> IO CInt+printCStr f x = do+ cs <- f x+ s <- peekCString cs+ free cs+ putStr s+ return 1++printCVec :: Storable a => (Ptr a -> IO CInt) -> Ptr a -> CLong -> IO CInt+printCVec f vec len = do+ putStr $ show len ++ " "+ forM_ [0..fromIntegral len - 1] $ \j -> do+ f (vec `advancePtr` j)+ putStr " "+ return 1++--------------------------------------------------------------------------------++type CFBitCnt = #type flint_bitcnt_t
+ src/Data/Number/Flint/Fmpq.hs view
@@ -0,0 +1,12 @@+{-|+module : Data.Number.Flint.Fmpq+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpq (+ module Data.Number.Flint.Fmpq.FFI+) where++import Data.Number.Flint.Fmpq.FFI+
+ src/Data/Number/Flint/Fmpq/FFI.hsc view
@@ -0,0 +1,1189 @@+{-|+module : Data.Number.Flint.Fmpq.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpq.FFI (+ -- * Rational numbers @Fmpq@+ Fmpq+ , CFmpq (..)+ -- * Constructors+ , newFmpq+ , withFmpq+ , withFmpqNum+ , withFmpqDen+ , withNewFmpq+ -- * Memory management+ , fmpq_init+ , fmpq_clear+ -- * Canonicalisation+ , fmpq_canonicalise+ , _fmpq_canonicalise+ , fmpq_is_canonical+ , _fmpq_is_canonical+ -- * Basic assignment+ , fmpq_set+ , fmpq_swap+ , fmpq_neg+ , fmpq_abs+ , fmpq_zero+ , fmpq_one+ -- * Comparison+ , fmpq_is_zero+ , fmpq_is_one+ , fmpq_is_pm1+ , fmpq_equal+ , fmpq_sgn+ , fmpq_cmp+ , fmpq_cmp_fmpz+ , fmpq_cmp_si+ , fmpq_equal_ui+ , fmpq_equal_si+ , fmpq_height+ , fmpq_height_bits+ -- * Conversion+ , fmpq_set_fmpz_frac+ , fmpq_get_fmpz_frac+ , fmpq_get_mpz_frac+ , fmpq_set_si+ , _fmpq_set_si+ , fmpq_set_ui+ , _fmpq_set_ui+ , fmpq_set_mpq+ , fmpq_set_str+ , fmpq_init_set_mpz_frac_readonly+ , fmpq_get_d+ , fmpq_get_mpq+ , fmpq_get_mpfr+ , fmpq_get_str+ , _fmpq_get_str+ , flint_mpq_init_set_readonly+ , flint_mpq_clear_readonly+ , fmpq_init_set_readonly+ , fmpq_clear_readonly+ -- * Input and output+ , fmpq_fprint+ , _fmpq_fprint+ , fmpq_print+ , _fmpq_print+ -- * Random number generation+ , fmpq_randtest+ , _fmpq_randtest+ , fmpq_randtest_not_zero+ , fmpq_randbits+ , _fmpq_randbits+ -- * Arithmetic+ , fmpq_add+ , fmpq_sub+ , fmpq_mul+ , fmpq_div+ , _fmpq_add+ , _fmpq_sub+ , _fmpq_mul+ , _fmpq_div + , _fmpq_add_si+ , _fmpq_sub_si+ , _fmpq_add_ui+ , _fmpq_sub_ui+ , _fmpq_add_fmpz+ , _fmpq_sub_fmpz+ , _fmpq_mul_si+ , fmpq_add_si+ , fmpq_sub_si+ , fmpq_add_ui+ , fmpq_sub_ui+ , fmpq_add_fmpz+ , fmpq_sub_fmpz+ , _fmpq_mul_ui+ , fmpq_mul_ui+ , fmpq_addmul+ , fmpq_submul+ , _fmpq_addmul+ , fmpq_inv+ , _fmpq_pow_si+ , fmpq_pow_si+ , fmpq_pow_fmpz+ , fmpq_mul_fmpz+ , fmpq_div_fmpz+ , fmpq_mul_2exp+ , fmpq_div_2exp+ , _fmpq_gcd+ , fmpq_gcd+ , _fmpq_gcd_cofactors+ , fmpq_gcd_cofactors+ , _fmpq_add_small+ , _fmpq_mul_small+ -- * Modular reduction and rational reconstruction+ , _fmpq_mod_fmpz+ , _fmpq_reconstruct_fmpz_2_naive+ , _fmpq_reconstruct_fmpz+ -- * Rational enumeration+ , _fmpq_next_minimal+ , _fmpq_next_signed_minimal+ , _fmpq_next_calkin_wilf+ , _fmpq_next_signed_calkin_wilf+ , fmpq_farey_neighbors+ , fmpq_mediant+ , fmpq_simplest_between+ -- * Continued fractions+ , fmpq_get_cfrac+ , fmpq_set_cfrac+ , fmpq_cfrac_bound+ , fmpq_get_cfrac_st+ , fmpq_set_cfrac_st+ -- * Special functions+ , _fmpq_harmonic_ui+ , fmpq_harmonic_ui+ -- * Dedekind sums+ , fmpq_dedekind_sum+ , fmpq_dedekind_sum_naive+) where ++-- rational numbers ------------------------------------------------------------++import System.IO.Unsafe++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, nullPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Functor ((<&>))++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Quotient++#include <flint/flint.h>+#include <flint/fmpq.h>++-- fmpq_t ----------------------------------------------------------------------++-- | Rational numbers (opaque pointer)+data Fmpq = Fmpq {-# UNPACK #-} !(ForeignPtr CFmpq)+data CFmpq = CFmpq (Ptr CFmpz) (Ptr CFmpz)++instance Storable CFmpq where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpq_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpq_t}+ peek ptr = CFmpq+ <$> (return $ castPtr ptr)+ <*> (return $ castPtr ptr `advancePtr` 1)+ poke = error "CFmpz.poke: Not defined"++-- Fmpq ------------------------------------------------------------------------++-- | /newFmpq/+--+-- Construct a `Fmpq`.+newFmpq = do+ x <- mallocForeignPtr+ withForeignPtr x fmpq_init+ addForeignPtrFinalizer p_fmpq_clear x+ return $ Fmpq x++-- | /withFmpq/ /x/ /f/+--+-- Execute /f/ with /x/.+{-# INLINE withFmpq #-}+withFmpq (Fmpq x) f = withForeignPtr x $ \xp -> f xp <&> (Fmpq x,)++-- | /withNewFmpq/ /f/+--+-- Execture /f/ with a new `Fmpq`.+{-# INLINE withNewFmpq #-}+withNewFmpq f = newFmpq >>= flip withFmpq f++-- | /withFmpqNum/ /x/ /f/+--+-- Execute /f/ on the numerator of /x/.+withFmpqNum x f = do+ withFmpq x $ \x -> do + f $ castPtr x++-- | /withFmpqDen/ /x/ /f/+--+-- Execute /f/ on the denominator of /x/.+withFmpqDen x f = do+ withFmpq x $ \x -> do + f $ flip advancePtr 1 $ castPtr x++-- Fmpz <-> Fmpq --------------------------------------------------------------++instance Quotient Fmpq Fmpz where++ (//) x y = unsafePerformIO $ do+ result <- newFmpq+ withFmpq result $ \result -> do+ withFmpz x $ \x -> do+ withFmpz y $ \y -> do+ fmpq_set_fmpz_frac result x y+ return result++ numerator x = unsafePerformIO $ do+ result <- newFmpz+ withFmpz result $ \result -> do+ withFmpq x $ \x -> do+ withNewFmpz $ \tmp -> do+ fmpq_get_fmpz_frac result tmp x+ return result++ denominator x = unsafePerformIO $ do+ result <- newFmpz+ withFmpz result $ \result -> do+ withFmpq x $ \x -> do+ withNewFmpz $ \tmp -> do+ fmpq_get_fmpz_frac tmp result x+ return result++-- Memory management -----------------------------------------------------------++-- | /fmpq_init/ /x/ +-- +-- Initialises the @fmpq_t@ variable @x@ for use. Its value is set to 0.+foreign import ccall "fmpq.h fmpq_init"+ fmpq_init :: Ptr CFmpq -> IO ()++-- | /fmpq_clear/ /x/ +-- +-- Clears the @fmpq_t@ variable @x@. To use the variable again, it must be+-- re-initialised with @fmpq_init@.+foreign import ccall "fmpq.h fmpq_clear"+ fmpq_clear :: Ptr CFmpq -> IO ()++foreign import ccall "fmpq.h &fmpq_clear"+ p_fmpq_clear :: FunPtr (Ptr CFmpq -> IO ())++-- Canonicalisation ------------------------------------------------------------++-- | /fmpq_canonicalise/ /res/ +-- +-- Puts @res@ in canonical form: the numerator and denominator are reduced+-- to lowest terms, and the denominator is made positive. If the numerator+-- is zero, the denominator is set to one.+-- +-- If the denominator is zero, the outcome of calling this function is+-- undefined, regardless of the value of the numerator.+foreign import ccall "fmpq.h fmpq_canonicalise"+ fmpq_canonicalise :: Ptr CFmpq -> IO ()++-- | /_fmpq_canonicalise/ /num/ /den/ +-- +-- Does the same thing as @fmpq_canonicalise@, but for numerator and+-- denominator given explicitly as @fmpz_t@ variables. Aliasing of @num@+-- and @den@ is not allowed.+foreign import ccall "fmpq.h _fmpq_canonicalise"+ _fmpq_canonicalise :: Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpq_is_canonical/ /x/ +-- +-- Returns nonzero if @fmpq_t@ x is in canonical form (as produced by+-- @fmpq_canonicalise@), and zero otherwise.+foreign import ccall "fmpq.h fmpq_is_canonical"+ fmpq_is_canonical :: Ptr CFmpq -> IO CInt++-- | /_fmpq_is_canonical/ /num/ /den/ +-- +-- Does the same thing as @fmpq_is_canonical@, but for numerator and+-- denominator given explicitly as @fmpz_t@ variables.+foreign import ccall "fmpq.h _fmpq_is_canonical"+ _fmpq_is_canonical :: Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- Basic assignment ------------------------------------------------------------++-- | /fmpq_set/ /dest/ /src/ +-- +-- Sets @dest@ to a copy of @src@. No canonicalisation is performed.+foreign import ccall "fmpq.h fmpq_set"+ fmpq_set :: Ptr CFmpq -> Ptr CFmpq -> IO ()++-- | /fmpq_swap/ /op1/ /op2/ +-- +-- Swaps the two rational numbers @op1@ and @op2@.+foreign import ccall "fmpq.h fmpq_swap"+ fmpq_swap :: Ptr CFmpq -> Ptr CFmpq -> IO ()++-- | /fmpq_neg/ /dest/ /src/ +-- +-- Sets @dest@ to the additive inverse of @src@.+foreign import ccall "fmpq.h fmpq_neg"+ fmpq_neg :: Ptr CFmpq -> Ptr CFmpq -> IO ()++-- | /fmpq_abs/ /dest/ /src/ +-- +-- Sets @dest@ to the absolute value of @src@.+foreign import ccall "fmpq.h fmpq_abs"+ fmpq_abs :: Ptr CFmpq -> Ptr CFmpq -> IO ()++-- | /fmpq_zero/ /res/ +-- +-- Sets the value of @res@ to 0.+foreign import ccall "fmpq.h fmpq_zero"+ fmpq_zero :: Ptr CFmpq -> IO ()++-- | /fmpq_one/ /res/ +-- +-- Sets the value of @res@ to \(1\).+foreign import ccall "fmpq.h fmpq_one"+ fmpq_one :: Ptr CFmpq -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fmpq_is_zero/ /res/ +-- +-- Returns nonzero if @res@ has value 0, and returns zero otherwise.+foreign import ccall "fmpq.h fmpq_is_zero"+ fmpq_is_zero :: Ptr CFmpq -> IO CInt++-- | /fmpq_is_one/ /res/ +-- +-- Returns nonzero if @res@ has value \(1\), and returns zero otherwise.+foreign import ccall "fmpq.h fmpq_is_one"+ fmpq_is_one :: Ptr CFmpq -> IO CInt++-- | /fmpq_is_pm1/ /res/ +-- +-- Returns nonzero if @res@ has value \(\pm{1}\) and zero otherwise.+foreign import ccall "fmpq.h fmpq_is_pm1"+ fmpq_is_pm1 :: Ptr CFmpq -> IO CInt++-- | /fmpq_equal/ /x/ /y/ +-- +-- Returns nonzero if @x@ and @y@ are equal, and zero otherwise. Assumes+-- that @x@ and @y@ are both in canonical form.+foreign import ccall "fmpq.h fmpq_equal"+ fmpq_equal :: Ptr CFmpq -> Ptr CFmpq -> IO CInt++-- | /fmpq_sgn/ /x/ +-- +-- Returns the sign of the rational number \(x\).+foreign import ccall "fmpq.h fmpq_sgn"+ fmpq_sgn :: Ptr CFmpq -> IO CInt++-- | /fmpq_cmp/ /x/ /y/ +-- +-- Returns negative if \(x < y\), zero if \(x = y\), and positive if+-- \(x > y\).+foreign import ccall "fmpq.h fmpq_cmp"+ fmpq_cmp :: Ptr CFmpq -> Ptr CFmpq -> IO CInt++foreign import ccall "fmpq.h fmpq_cmp_fmpz"+ fmpq_cmp_fmpz :: Ptr CFmpq -> Ptr CFmpz -> IO CInt++foreign import ccall "fmpq.h fmpq_cmp_ui"+ fmpq_cmp_ui :: Ptr CFmpq -> Ptr CULong -> IO CInt++-- | /fmpq_cmp_si/ /x/ /y/ +-- +-- Returns negative if \(x < y\), zero if \(x = y\), and positive if+-- \(x > y\).+foreign import ccall "fmpq.h fmpq_cmp_si"+ fmpq_cmp_si :: Ptr CFmpq -> CLong -> IO CInt++-- | /fmpq_equal_ui/ /x/ /y/ +-- +-- Returns \(1\) if \(x = y\), otherwise returns \(0\).+foreign import ccall "fmpq.h fmpq_equal_ui"+ fmpq_equal_ui :: Ptr CFmpq -> CULong -> IO CInt++-- | /fmpq_equal_si/ /x/ /y/ +-- +-- Returns \(1\) if \(x = y\), otherwise returns \(0\).+foreign import ccall "fmpq.h fmpq_equal_si"+ fmpq_equal_si :: Ptr CFmpq -> CLong -> IO CInt++-- | /fmpq_height/ /height/ /x/ +-- +-- Sets @height@ to the height of \(x\), defined as the larger of the+-- absolute values of the numerator and denominator of \(x\).+foreign import ccall "fmpq.h fmpq_height"+ fmpq_height :: Ptr CFmpz -> Ptr CFmpq -> IO ()++-- | /fmpq_height_bits/ /x/ +-- +-- Returns the number of bits in the height of \(x\).+foreign import ccall "fmpq.h fmpq_height_bits"+ fmpq_height_bits :: Ptr CFmpq -> IO CFBitCnt++-- Conversion ------------------------------------------------------------------++-- | /fmpq_set_fmpz_frac/ /res/ /p/ /q/ +-- +-- Sets @res@ to the canonical form of the fraction @p \/ q@. This is+-- equivalent to assigning the numerator and denominator separately and+-- calling @fmpq_canonicalise@.+foreign import ccall "fmpq.h fmpq_set_fmpz_frac"+ fmpq_set_fmpz_frac :: Ptr CFmpq -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpq.h fmpq_get_fmpz_frac"+ fmpq_get_fmpz_frac :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpq -> IO ()++-- | /fmpq_get_mpz_frac/ /a/ /b/ /c/ +-- +-- Sets @a@, @b@ to the numerator and denominator of @c@ respectively.+foreign import ccall "fmpq.h fmpq_get_mpz_frac"+ fmpq_get_mpz_frac :: Ptr CMpz -> Ptr CMpz -> Ptr CFmpq -> IO ()++-- | /fmpq_set_si/ /res/ /p/ /q/ +-- +-- Sets @res@ to the canonical form of the fraction @p \/ q@.+foreign import ccall "fmpq.h fmpq_set_si"+ fmpq_set_si :: Ptr CFmpq -> CLong -> CULong -> IO ()++-- | /_fmpq_set_si/ /rnum/ /rden/ /p/ /q/ +-- +-- Sets @(rnum, rden)@ to the canonical form of the fraction @p \/ q@.+-- @rnum@ and @rden@ may not be aliased.+foreign import ccall "fmpq.h _fmpq_set_si"+ _fmpq_set_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /fmpq_set_ui/ /res/ /p/ /q/ +-- +-- Sets @res@ to the canonical form of the fraction @p \/ q@.+foreign import ccall "fmpq.h fmpq_set_ui"+ fmpq_set_ui :: Ptr CFmpq -> CULong -> CULong -> IO ()++-- | /_fmpq_set_ui/ /rnum/ /rden/ /p/ /q/ +-- +-- Sets @(rnum, rden)@ to the canonical form of the fraction @p \/ q@.+-- @rnum@ and @rden@ may not be aliased.+foreign import ccall "fmpq.h _fmpq_set_ui"+ _fmpq_set_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CULong -> IO ()++-- | /fmpq_set_mpq/ /dest/ /src/ +-- +-- Sets the value of @dest@ to that of the @mpq_t@ variable @src@.+foreign import ccall "fmpq.h fmpq_set_mpq"+ fmpq_set_mpq :: Ptr CFmpq -> Ptr CMpq -> IO ()++-- | /fmpq_set_str/ /dest/ /s/ /base/ +-- +-- Sets the value of @dest@ to the value represented in the string @s@ in+-- base @base@.+-- +-- Returns 0 if no error occurs. Otherwise returns -1 and @dest@ is set to+-- zero.+foreign import ccall "fmpq.h fmpq_set_str"+ fmpq_set_str :: Ptr CFmpq -> CString -> CInt -> IO CInt++-- | /fmpq_init_set_mpz_frac_readonly/ /z/ /p/ /q/ +-- +-- Assuming @z@ is an @fmpz_t@ which will not be cleaned up, this+-- temporarily copies @p@ and @q@ into the numerator and denominator of @z@+-- for read only operations only. The user must not run @fmpq_clear@ on+-- @z@.+foreign import ccall "fmpq.h fmpq_init_set_mpz_frac_readonly"+ fmpq_init_set_mpz_frac_readonly :: Ptr CFmpq -> Ptr CMpz -> Ptr CMpz -> IO ()++-- | /fmpq_get_d/ /f/ +-- +-- Returns \(f\) as a @double@, rounding towards zero if @f@ cannot be+-- represented exactly. The return is system dependent if @f@ is too large+-- or too small to fit in a @double@.+foreign import ccall "fmpq.h fmpq_get_d"+ fmpq_get_d :: Ptr CFmpq -> IO CDouble++-- | /fmpq_get_mpq/ /dest/ /src/ +-- +-- Sets the value of @dest@+foreign import ccall "fmpq.h fmpq_get_mpq"+ fmpq_get_mpq :: Ptr CMpq -> Ptr CFmpq -> IO ()++-- | /fmpq_get_mpfr/ /dest/ /src/ /rnd/ +-- +-- Sets the MPFR variable @dest@ to the value of @src@, rounded to the+-- nearest representable binary floating-point value in direction @rnd@.+-- Returns the sign of the rounding, according to MPFR conventions.+foreign import ccall "fmpq.h fmpq_get_mpfr"+ fmpq_get_mpfr :: Ptr CMpfr -> Ptr CFmpq -> CMpfrRnd -> IO CInt++-- | /_fmpq_get_str/ /str/ /b/ /num/ /den/ +-- +-- Prints the string representation of \(x\) in base \(b \in [2, 36]\) to a+-- suitable buffer.+-- +-- If @str@ is not @NULL@, this is used as the buffer and also the return+-- value. If @str@ is @NULL@, allocates sufficient space and returns a+-- pointer to the string.+foreign import ccall "fmpq.h fmpq_get_str"+ fmpq_get_str :: CString -> CInt -> Ptr CFmpq -> IO CString++foreign import ccall "fmpq.h _fmpq_get_str"+ _fmpq_get_str :: CString -> CInt -> Ptr CFmpz -> Ptr CFmpz -> IO CString++-- | /flint_mpq_init_set_readonly/ /z/ /f/ +-- +-- Sets the uninitialised @mpq_t@ \(z\) to the value of the readonly+-- @fmpq_t@ \(f\).+-- +-- Note that it is assumed that \(f\) does not change during the lifetime+-- of \(z\).+-- +-- The rational \(z\) has to be cleared by a call to+-- @flint_mpq_clear_readonly@.+-- +-- The suggested use of the two functions is as follows:+-- +-- > fmpq_t f;+-- > ...+-- > {+-- > mpq_t z;+-- >+-- > flint_mpq_init_set_readonly(z, f);+-- > foo(..., z);+-- > flint_mpq_clear_readonly(z);+-- > }+-- +-- This provides a convenient function for user code, only requiring to+-- work with the types @fmpq_t@ and @mpq_t@.+foreign import ccall "fmpq.h flint_mpq_init_set_readonly"+ flint_mpq_init_set_readonly :: Ptr CMpq -> Ptr CFmpq -> IO ()++-- | /flint_mpq_clear_readonly/ /z/ +-- +-- Clears the readonly @mpq_t@ \(z\).+foreign import ccall "fmpq.h flint_mpq_clear_readonly"+ flint_mpq_clear_readonly :: Ptr CMpq -> IO ()++-- | /fmpq_init_set_readonly/ /f/ /z/ +-- +-- Sets the uninitialised @fmpq_t@ \(f\) to a readonly version of the+-- rational \(z\).+-- +-- Note that the value of \(z\) is assumed to remain constant throughout+-- the lifetime of \(f\).+-- +-- The @fmpq_t@ \(f\) has to be cleared by calling the function+-- @fmpq_clear_readonly@.+-- +-- The suggested use of the two functions is as follows:+-- +-- > mpq_t z;+-- > ...+-- > {+-- > fmpq_t f;+-- >+-- > fmpq_init_set_readonly(f, z);+-- > foo(..., f);+-- > fmpq_clear_readonly(f);+-- > }+foreign import ccall "fmpq.h fmpq_init_set_readonly"+ fmpq_init_set_readonly :: Ptr CFmpq -> Ptr CMpq -> IO ()++-- | /fmpq_clear_readonly/ /f/ +-- +-- Clears the readonly @fmpq_t@ \(f\).+foreign import ccall "fmpq.h fmpq_clear_readonly"+ fmpq_clear_readonly :: Ptr CFmpq -> IO ()++-- Input and output ------------------------------------------------------------++-- | /fmpq_fprint/ /file/ /x/ +-- +-- Prints @x@ as a fraction to the stream @file@. The numerator and+-- denominator are printed verbatim as integers, with a forward slash (\/)+-- printed in between.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive number.+foreign import ccall "fmpq.h fmpq_fprint"+ fmpq_fprint :: Ptr CFile -> Ptr CFmpq -> IO CInt++-- | /_fmpq_fprint/ /file/ /num/ /den/ +-- +-- Does the same thing as @fmpq_fprint@, but for numerator and denominator+-- given explicitly as @fmpz_t@ variables.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive number.+foreign import ccall "fmpq.h _fmpq_fprint"+ _fmpq_fprint :: Ptr CFile -> Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- | /fmpq_print/ /x/ +-- +-- Prints @x@ as a fraction. The numerator and denominator are printed+-- verbatim as integers, with a forward slash (\/) printed in between.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive number.+fmpq_print :: Ptr CFmpq -> IO CInt+fmpq_print x = printCStr (fmpq_get_str nullPtr 10) x++-- | /_fmpq_print/ /num/ /den/ +-- +-- Does the same thing as @fmpq_print@, but for numerator and denominator+-- given explicitly as @fmpz_t@ variables.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive number.+foreign import ccall "fmpq.h _fmpq_print"+ _fmpq_print :: Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- Random number generation ----------------------------------------------------++-- | /fmpq_randtest/ /res/ /state/ /bits/ +-- +-- Sets @res@ to a random value, with numerator and denominator having up+-- to @bits@ bits. The fraction will be in canonical form. This function+-- has an increased probability of generating special values which are+-- likely to trigger corner cases.+foreign import ccall "fmpq.h fmpq_randtest"+ fmpq_randtest :: Ptr CFmpq -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /_fmpq_randtest/ /num/ /den/ /state/ /bits/ +-- +-- Does the same thing as @fmpq_randtest@, but for numerator and+-- denominator given explicitly as @fmpz_t@ variables. Aliasing of @num@+-- and @den@ is not allowed.+foreign import ccall "fmpq.h _fmpq_randtest"+ _fmpq_randtest :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /fmpq_randtest_not_zero/ /res/ /state/ /bits/ +-- +-- As per @fmpq_randtest@, but the result will not be \(0\). If @bits@ is+-- set to \(0\), an exception will result.+foreign import ccall "fmpq.h fmpq_randtest_not_zero"+ fmpq_randtest_not_zero :: Ptr CFmpq -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /fmpq_randbits/ /res/ /state/ /bits/ +-- +-- Sets @res@ to a random value, with numerator and denominator both having+-- exactly @bits@ bits before canonicalisation, and then puts @res@ in+-- canonical form. Note that as a result of the canonicalisation, the+-- resulting numerator and denominator can be slightly smaller than @bits@+-- bits.+foreign import ccall "fmpq.h fmpq_randbits"+ fmpq_randbits :: Ptr CFmpq -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /_fmpq_randbits/ /num/ /den/ /state/ /bits/ +-- +-- Does the same thing as @fmpq_randbits@, but for numerator and+-- denominator given explicitly as @fmpz_t@ variables. Aliasing of @num@+-- and @den@ is not allowed.+foreign import ccall "fmpq.h _fmpq_randbits"+ _fmpq_randbits :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFRandState -> CFBitCnt -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- | /fmpq_add/ /res/ /op1/ /op2/ +-- +-- Sets @res@ respectively to @op1 + op2@, @op1 - op2@, @op1 * op2@, or+-- @op1 \/ op2@. Assumes that the inputs are in canonical form, and+-- produces output in canonical form. Division by zero results in an error.+-- Aliasing between any combination of the variables is allowed.+foreign import ccall "fmpq.h fmpq_add"+ fmpq_add :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpq -> IO ()++foreign import ccall "fmpq.h fmpq_sub"+ fmpq_sub :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpq -> IO ()++foreign import ccall "fmpq.h fmpq_mul"+ fmpq_mul :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpq -> IO ()++foreign import ccall "fmpq.h fmpq_div"+ fmpq_div :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpq -> IO ()++-- | /_fmpq_add/ /rnum/ /rden/ /op1num/ /op1den/ /op2num/ /op2den/ +-- +-- Sets @(rnum, rden)@ to the canonical form of the sum, difference,+-- product or quotient respectively of the fractions represented by+-- @(op1num, op1den)@ and @(op2num, op2den)@. Aliasing between any+-- combination of the variables is allowed, whilst no numerator is aliased+-- with a denominator.+foreign import ccall "fmpq.h _fmpq_add"+ _fmpq_add :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpq.h _fmpq_sub"+ _fmpq_sub :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpq.h _fmpq_mul"+ _fmpq_mul :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpq.h _fmpq_div"+ _fmpq_div :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /_fmpq_add_si/ /rnum/ /rden/ /p/ /q/ /r/ +-- +-- Sets @(rnum, rden)@ to the canonical form of the sum or difference+-- respectively of the fractions represented by @(p, q)@ and @(r, 1)@.+-- Numerators may not be aliased with denominators.+foreign import ccall "fmpq.h _fmpq_add_si"+ _fmpq_add_si :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "fmpq.h _fmpq_sub_si"+ _fmpq_sub_si :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "fmpq.h _fmpq_add_ui"+ _fmpq_add_ui :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "fmpq.h _fmpq_sub_ui"+ _fmpq_sub_ui :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "fmpq.h _fmpq_add_fmpz"+ _fmpq_add_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpq.h _fmpq_sub_fmpz"+ _fmpq_sub_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpq_add_si/ /res/ /op1/ /c/ +-- +-- Sets @res@ to the sum or difference respectively, of the fraction @op1@+-- and the integer \(c\).+foreign import ccall "fmpq.h fmpq_add_si"+ fmpq_add_si :: Ptr CFmpq -> Ptr CFmpq -> CLong -> IO ()++foreign import ccall "fmpq.h fmpq_sub_si"+ fmpq_sub_si :: Ptr CFmpq -> Ptr CFmpq -> CLong -> IO ()++foreign import ccall "fmpq.h fmpq_add_ui"+ fmpq_add_ui :: Ptr CFmpq -> Ptr CFmpq -> CLong -> IO ()++foreign import ccall "fmpq.h fmpq_sub_ui"+ fmpq_sub_ui :: Ptr CFmpq -> Ptr CFmpq -> CLong -> IO ()++foreign import ccall "fmpq.h fmpq_sub_fmpz"+ fmpq_add_fmpz :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpz -> IO ()++foreign import ccall "fmpq.h fmpq_sub_fmpz"+ fmpq_sub_fmpz :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpz -> IO ()++-- | /_fmpq_mul_si/ /rnum/ /rden/ /p/ /q/ /r/ +-- +-- Sets @(rnum, rden)@ to the product of @(p, q)@ and the integer \(r\).+foreign import ccall "fmpq.h _fmpq_mul_si"+ _fmpq_mul_si :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_mul_si/ /res/ /op1/ /c/ +-- +-- Sets @res@ to the product of @op1@ and the integer \(c\).+foreign import ccall "fmpq.h fmpq_mul_si"+ fmpq_mul_si :: Ptr CFmpq -> Ptr CFmpq -> CLong -> IO ()++-- | /_fmpq_mul_ui/ /rnum/ /rden/ /p/ /q/ /r/ +-- +-- Sets @(rnum, rden)@ to the product of @(p, q)@ and the integer \(r\).+foreign import ccall "fmpq.h _fmpq_mul_ui"+ _fmpq_mul_ui :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpq_mul_ui/ /res/ /op1/ /c/ +-- +-- Sets @res@ to the product of @op1@ and the integer \(c\).+foreign import ccall "fmpq.h fmpq_mul_ui"+ fmpq_mul_ui :: Ptr CFmpq -> Ptr CFmpq -> CULong -> IO ()++-- | /fmpq_addmul/ /res/ /op1/ /op2/ +-- +-- Sets @res@ to @res + op1 * op2@ or @res - op1 * op2@ respectively,+-- placing the result in canonical form. Aliasing between any combination+-- of the variables is allowed.+foreign import ccall "fmpq.h fmpq_addmul"+ fmpq_addmul :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpq -> IO ()++foreign import ccall "fmpq.h fmpq_submul"+ fmpq_submul :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpq -> IO ()++-- | /_fmpq_addmul/ /rnum/ /rden/ /op1num/ /op1den/ /op2num/ /op2den/ +-- +-- Sets @(rnum, rden)@ to the canonical form of the fraction @(rnum, rden)@+-- + @(op1num, op1den)@ * @(op2num, op2den)@ or @(rnum, rden)@ -+-- @(op1num, op1den)@ * @(op2num, op2den)@ respectively. Aliasing between+-- any combination of the variables is allowed, whilst no numerator is+-- aliased with a denominator.+foreign import ccall "fmpq.h _fmpq_addmul"+ _fmpq_addmul :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpq_inv/ /dest/ /src/ +-- +-- Sets @dest@ to @1 \/ src@. The result is placed in canonical form,+-- assuming that @src@ is already in canonical form.+foreign import ccall "fmpq.h fmpq_inv"+ fmpq_inv :: Ptr CFmpq -> Ptr CFmpq -> IO ()++-- | /_fmpq_pow_si/ /rnum/ /rden/ /opnum/ /opden/ /e/ +-- +-- Sets @res@ to @op@ raised to the power~\`e\`, where~\`e\` is a @slong@.+-- If \(e\) is \(0\) and @op@ is \(0\), then @res@ will be set to \(1\).+foreign import ccall "fmpq.h _fmpq_pow_si"+ _fmpq_pow_si :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "fmpq.h fmpq_pow_si"+ fmpq_pow_si :: Ptr CFmpq -> Ptr CFmpq -> CLong -> IO ()+ +-- | /fmpq_pow_fmpz/ /a/ /b/ /e/ +-- +-- Set @res@ to @op@ raised to the power~\`e\`. Return \(1\) for success+-- and \(0\) for failure.+foreign import ccall "fmpq.h fmpq_pow_fmpz"+ fmpq_pow_fmpz :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpz -> IO CInt++-- | /fmpq_mul_fmpz/ /res/ /op/ /x/ +-- +-- Sets @res@ to the product of the rational number @op@ and the integer+-- @x@.+foreign import ccall "fmpq.h fmpq_mul_fmpz"+ fmpq_mul_fmpz :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpz -> IO ()++-- | /fmpq_div_fmpz/ /res/ /op/ /x/ +-- +-- Sets @res@ to the quotient of the rational number @op@ and the integer+-- @x@.+foreign import ccall "fmpq.h fmpq_div_fmpz"+ fmpq_div_fmpz :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpz -> IO ()++-- | /fmpq_mul_2exp/ /res/ /x/ /exp/ +-- +-- Sets @res@ to @x@ multiplied by @2^exp@.+foreign import ccall "fmpq.h fmpq_mul_2exp"+ fmpq_mul_2exp :: Ptr CFmpq -> Ptr CFmpq -> CFBitCnt -> IO ()++-- | /fmpq_div_2exp/ /res/ /x/ /exp/ +-- +-- Sets @res@ to @x@ divided by @2^exp@.+foreign import ccall "fmpq.h fmpq_div_2exp"+ fmpq_div_2exp :: Ptr CFmpq -> Ptr CFmpq -> CFBitCnt -> IO ()++-- | /_fmpq_gcd/ /rnum/ /rden/ /p/ /q/ /r/ /s/ +-- +-- Set @(rnum, rden)@ to the gcd of @(p, q)@ and @(r, s)@ which we define+-- to be the canonicalisation of gcd\`(ps, qr)\/(qs). (This is apparently+-- Euclid\'s original definition and is stable under scaling of numerator+-- and denominator. It also agrees with the gcd on the integers. Note that+-- it does not agree with gcd as defined in fmpq_poly\`.) This definition+-- agrees with the result as output by Sage and Pari\/GP.+foreign import ccall "fmpq.h _fmpq_gcd"+ _fmpq_gcd :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpq_gcd/ /res/ /op1/ /op2/ +-- +-- Set @res@ to the gcd of @op1@ and @op2@. See the low level function+-- @_fmpq_gcd@ for our definition of gcd.+foreign import ccall "fmpq.h fmpq_gcd"+ fmpq_gcd :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpq -> IO ()++-- | /_fmpq_gcd_cofactors/ /gnum/ /gden/ /abar/ /bbar/ /anum/ /aden/ /bnum/ /bden/ +-- +-- Set \(g\) to \(\operatorname{gcd}(a,b)\) as per @fmpq_gcd@ and also+-- compute \(\overline{a} = a/g\) and \(\overline{b} = b/g\). Unlike+-- @fmpq_gcd@, this function requires canonical inputs.+foreign import ccall "fmpq.h _fmpq_gcd_cofactors"+ _fmpq_gcd_cofactors :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpq.h fmpq_gcd_cofactors"+ fmpq_gcd_cofactors :: Ptr CFmpq -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpq -> Ptr CFmpq -> IO ()+ +-- | /_fmpq_add_small/ /rnum/ /rden/ /p1/ /q1/ /p2/ /q2/ +-- +-- Sets @(rnum, rden)@ to the sum of @(p1, q1)@ and @(p2, q2)@. Assumes+-- that @(p1, q1)@ and @(p2, q2)@ are in canonical form and that all inputs+-- are between @COEFF_MIN@ and @COEFF_MAX@.+foreign import ccall "fmpq.h _fmpq_add_small"+ _fmpq_add_small :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> CLong -> CULong -> IO ()++-- | /_fmpq_mul_small/ /rnum/ /rden/ /p1/ /q1/ /p2/ /q2/ +-- +-- Sets @(rnum, rden)@ to the product of @(p1, q1)@ and @(p2, q2)@. Assumes+-- that @(p1, q1)@ and @(p2, q2)@ are in canonical form and that all inputs+-- are between @COEFF_MIN@ and @COEFF_MAX@.+foreign import ccall "fmpq.h _fmpq_mul_small"+ _fmpq_mul_small :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> CLong -> CULong -> IO ()++-- Modular reduction and rational reconstruction -------------------------------++-- | /_fmpq_mod_fmpz/ /res/ /num/ /den/ /mod/ +-- +-- Sets the integer @res@ to the residue \(a\) of \(x = n/d\) =+-- @(num, den)@ modulo the positive integer \(m\) = @mod@, defined as the+-- \(0 \le a < m\) satisfying \(n \equiv a d \pmod m\). If such an \(a\)+-- exists, 1 will be returned, otherwise 0 will be returned.+foreign import ccall "fmpq.h _fmpq_mod_fmpz"+ _fmpq_mod_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO CInt++foreign import ccall "fmpq.h fmpq_mod_fmpz"+ fmpq_mod_fmpz :: Ptr CFmpz -> Ptr CFmpq -> Ptr CFmpz -> IO CInt+ +-- | /_fmpq_reconstruct_fmpz_2_naive/ /n/ /d/ /a/ /m/ /N/ /D/ +-- +-- Reconstructs a rational number from its residue \(a\) modulo \(m\).+-- +-- Given a modulus \(m > 2\), a residue \(0 \le a < m\), and positive+-- \(N, D\) satisfying \(2ND < m\), this function attempts to find a+-- fraction \(n/d\) with \(0 \le |n| \le N\) and \(0 < d \le D\) such that+-- \(\gcd(n,d) = 1\) and \(n \equiv ad \pmod m\). If a solution exists,+-- then it is also unique. The function returns 1 if successful, and 0 to+-- indicate that no solution exists.+foreign import ccall "fmpq.h _fmpq_reconstruct_fmpz_2_naive"+ _fmpq_reconstruct_fmpz_2_naive :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO CInt++foreign import ccall "fmpq.h _fmpq_reconstruct_fmpz_2"+ _fmpq_reconstruct_fmpz_2 :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpq.h fmpq_reconstruct_fmpz_2"+ fmpq_reconstruct_fmpz_2 :: Ptr CFmpq -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()+ +-- | /_fmpq_reconstruct_fmpz/ /n/ /d/ /a/ /m/ +-- +-- Reconstructs a rational number from its residue \(a\) modulo \(m\),+-- returning 1 if successful and 0 if no solution exists. Uses the balanced+-- bounds \(N = D = \lfloor\sqrt{\frac{m-1}{2}}\rfloor\).+foreign import ccall "fmpq.h _fmpq_reconstruct_fmpz"+ _fmpq_reconstruct_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO CInt++foreign import ccall "fmpq fmpq_reconstruct_fmpz"+ fmpq_reconstruct_fmpz :: Ptr CFmpq -> Ptr CFmpz -> Ptr CFmpz -> IO ()+ +-- Rational enumeration --------------------------------------------------------++-- | /_fmpq_next_minimal/ /rnum/ /rden/ /num/ /den/ +-- +-- Given \(x\) which is assumed to be nonnegative and in canonical form,+-- sets @res@ to the next rational number in the sequence obtained by+-- enumerating all positive denominators \(q\), for each \(q\) enumerating+-- the numerators \(1 \le p < q\) in order and generating both \(p/q\) and+-- \(q/p\), but skipping all \(\gcd(p,q) \ne 1\). Starting with zero, this+-- generates every nonnegative rational number once and only once, with the+-- first few entries being:+-- +-- \(0, 1, 1/2, 2, 1/3, 3, 2/3, 3/2, 1/4, 4, 3/4, 4/3, 1/5, 5, 2/5, \ldots.\)+-- +-- This enumeration produces the rational numbers in order of minimal+-- height. It has the disadvantage of being somewhat slower to compute than+-- the Calkin-Wilf enumeration.+foreign import ccall "fmpq.h _fmpq_next_minimal"+ _fmpq_next_minimal :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /_fmpq_next_signed_minimal/ /rnum/ /rden/ /num/ /den/ +-- +-- Given a signed rational number \(x\) assumed to be in canonical form,+-- sets @res@ to the next element in the minimal-height sequence generated+-- by @fmpq_next_minimal@ but with negative numbers interleaved:+-- +-- \(0, 1, -1, 1/2, -1/2, 2, -2, 1/3, -1/3, \ldots.\)+-- +-- Starting with zero, this generates every rational number once and only+-- once, in order of minimal height.+foreign import ccall "fmpq.h _fmpq_next_signed_minimal"+ _fmpq_next_signed_minimal :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /_fmpq_next_calkin_wilf/ /rnum/ /rden/ /num/ /den/ +-- +-- Given \(x\) which is assumed to be nonnegative and in canonical form,+-- sets @res@ to the next number in the breadth-first traversal of the+-- Calkin-Wilf tree. Starting with zero, this generates every nonnegative+-- rational number once and only once, with the first few entries being:+-- +-- \(0, 1, 1/2, 2, 1/3, 3/2, 2/3, 3, 1/4, 4/3, 3/5, 5/2, 2/5, \ldots.\)+-- +-- Despite the appearance of the initial entries, the Calkin-Wilf+-- enumeration does not produce the rational numbers in order of height:+-- some small fractions will appear late in the sequence. This order has+-- the advantage of being faster to produce than the minimal-height order.+foreign import ccall "fmpq.h _fmpq_next_calkin_wilf"+ _fmpq_next_calkin_wilf :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /_fmpq_next_signed_calkin_wilf/ /rnum/ /rden/ /num/ /den/ +-- +-- Given a signed rational number \(x\) assumed to be in canonical form,+-- sets @res@ to the next element in the Calkin-Wilf sequence with negative+-- numbers interleaved:+-- +-- \(0, 1, -1, 1/2, -1/2, 2, -2, 1/3, -1/3, \ldots.\)+-- +-- Starting with zero, this generates every rational number once and only+-- once, but not in order of minimal height.+foreign import ccall "fmpq.h _fmpq_next_signed_calkin_wilf"+ _fmpq_next_signed_calkin_wilf :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpq_farey_neighbors/ /l/ /r/ /x/ /Q/ +-- +-- Set \(l\) and \(r\) to the fractions directly below and above \(x\) in+-- the Farey sequence of order \(Q\). This function will throw if \(x\) is+-- not canonical or \(Q\) is less than the denominator of \(x\).+foreign import ccall "fmpq.h fmpq_farey_neighbors"+ fmpq_farey_neighbors :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpz -> IO ()++-- | /fmpq_farey_mediant/ /x/ /l/ /r/+--+-- Set \(x\) to the mediant of \(l\) and \(r\)+foreign import ccall "fmpq.h fmpq_mediant"+ fmpq_mediant :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpq -> IO ()++-- | /fmpq_simplest_between/ /x/ /l/ /r/ +-- +-- Set \(x\) to the simplest fraction in the closed interval \([l, r]\).+-- The underscore version makes the additional assumption that \(l \le r\).+-- The endpoints \(l\) and \(r\) do not need to be reduced, but their+-- denominators do need to be positive. \(x\) will be always be returned in+-- canonical form. A canonical fraction \(a_1/b_1\) is defined to be+-- simpler than \(a_2/b_2\) iff \(b_1<b_2\) or \(b_1=b_2\) and \(a_1<a_2\).+foreign import ccall "fmpq.h fmpq_simplest_between"+ fmpq_simplest_between :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpq -> IO ()++-- Continued fractions ---------------------------------------------------------++-- | /fmpq_get_cfrac/ /c/ /rem/ /x/ /n/ +-- +-- Generates up to \(n\) terms of the (simple) continued fraction expansion+-- of \(x\), writing the coefficients to the vector \(c\) and the remainder+-- \(r\) to the @rem@ variable. The return value is the number \(k\) of+-- generated terms. The output satisfies+-- +-- \[x = c_0 + \cfrac{1}{c_1 + \cfrac{1}{c_2 ++-- \cfrac{1}{ \ddots + \cfrac{1}{c_{k-1} + r }}}}\]+-- \]+--+-- If \(r\) is zero, the continued fraction expansion is complete. If \(r\)+-- is nonzero, \(1/r\) can be passed back as input to generate+-- \(c_k, c_{k+1}, \ldots\). Calls to @fmpq_get_cfrac@ can therefore be+-- chained to generate the continued fraction incrementally, extracting any+-- desired number of coefficients at a time.+-- +-- In general, a rational number has exactly two continued fraction+-- expansions. By convention, we generate the shorter one. The longer+-- expansion can be obtained by replacing the last coefficient \(a_{k-1}\)+-- by the pair of coefficients \(a_{k-1} - 1, 1\).+-- +-- [The behaviour of this function in corner cases is as follows:]+-- - if \(x\) is infinite (anything over 0), @rem@ will be zero and+-- the return is \(k=0\) regardless of \(n\).+-- +-- - [else (if \(x\) is finite),]+-- - if \(n <= 0\), @rem@ will be \(1/x\) (allowing for+-- infinite in the case \(x=0\)) and the return is \(k=0\)+-- - else (if \(n > 0\)), @rem@ will finite and the return is+-- \(0 < k \le n\).+-- +-- Essentially, if this function is called with canonical \(x\) and+-- \(n > 0\), then @rem@ will be canonical. Therefore, applications relying+-- on canonical @fmpq_t@\'s should not call this function with \(n <= 0\).+foreign import ccall "fmpq.h fmpq_get_cfrac"+ fmpq_get_cfrac :: Ptr CFmpz -> Ptr CFmpq -> Ptr CFmpq -> CLong -> IO CLong++-- | /fmpq_set_cfrac/ /x/ /c/ /n/ +-- +-- Sets \(x\) to the value of the continued fraction+-- +-- \[`\]+-- \[x = c_0 + \cfrac{1}{c_1 + \cfrac{1}{c_2 ++-- \cfrac{1}{ \ddots + \cfrac{1}{c_{n-1}}}}}\]+-- +-- where all \(c_i\) except \(c_0\) should be nonnegative. It is assumed+-- that \(n > 0\).+-- +-- For large \(n\), this function implements a subquadratic algorithm. The+-- convergents are given by a chain product of 2 by 2 matrices. This+-- product is split in half recursively to balance the size of the+-- coefficients.+foreign import ccall "fmpq.h fmpq_set_cfrac"+ fmpq_set_cfrac :: Ptr CFmpq -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_cfrac_bound/ /x/ +-- +-- Returns an upper bound for the number of terms in the continued fraction+-- expansion of \(x\). The computed bound is not necessarily sharp.+-- +-- We use the fact that the smallest denominator that can give a continued+-- fraction of length \(n\) is the Fibonacci number \(F_{n+1}\).+foreign import ccall "fmpq.h fmpq_cfrac_bound"+ fmpq_cfrac_bound :: Ptr CFmpq -> IO CLong++-- | /fmpq_get_cfrac_st/ /c/ /rem/ /x/ /n/+--+-- Generates up to \(n\) terms of the continued fraction expansion+-- of \(x\), writing the coefficients to the vector \(c\) and the remainder+-- \(r\) to the @rem@ variable. The return value is the number \(k\) of+-- generated terms. The output satisfies+--+-- \[+-- x = c_0 - \cfrac{1}{c_1 - \cfrac{1}{c_2 -+-- \cfrac{1}{ \ddots - \cfrac{1}{c_{k-1} - r }}}}+-- \]+--+-- This expansion is closely related to the modular group. In terms of+-- the generators of the modular group \(S\) and \(T\) the expandion+-- of \(x=h/k\) satisfies:+--+-- \[+-- T^{c_0} S T^{c_1} \cdots T^{c_{k-1}} S+-- \begin{pmatrix} 1 \\ 0 \end{pmatrix}+-- = \begin{pmatrix} h \\ k \end{pmatrix}+-- \]+foreign import ccall "fmpq.h fmpq_get_cfrac_st"+ fmpq_get_cfrac_st :: Ptr CFmpz -> Ptr CFmpq -> Ptr CFmpq -> CLong -> IO CLong++-- | /fmpq_set_cfrac_st/ /x/ /c/ /n/+--+-- Returns the value \(x\) corresponding to the continued fraction \(c\).+foreign import ccall "fmpq.h fmpq_set_cfrac_st"+ fmpq_set_cfrac_st :: Ptr CFmpq -> Ptr CFmpz -> CLong -> IO ()++-- Special functions -----------------------------------------------------------++-- | /_fmpq_harmonic_ui/ /num/ /den/ /n/ +-- +-- Computes the harmonic number \(H_n = 1 + 1/2 + 1/3 + \dotsb + 1/n\).+-- Table lookup is used for \(H_n\) whose numerator and denominator fit in+-- single limb. For larger \(n\), a divide and conquer strategy is used.+foreign import ccall "fmpq.h _fmpq_harmonic_ui"+ _fmpq_harmonic_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpq.h fmpq_harmonic_ui"+ fmpq_harmonic_ui ::Ptr CFmpq -> CULong -> IO ()+ +-- Dedekind sums ---------------------------------------------------------------++-- Most of the definitions and relations used in the following section are+-- given by Apostol < [Apostol1997]>. The Dedekind sum \(s(h,k)\) is+-- defined for all integers \(h\) and \(k\) as+--+-- \[`\]+-- \[s(h,k) = \sum_{i=1}^{k-1} \left(\left(\frac{i}{k}\right)\right)+-- \left(\left(\frac{hi}{k}\right)\right)\]+--+-- where+--+-- \[`\]+-- \[\begin{aligned}+-- ((x))=\begin{cases}+-- x-\lfloor x\rfloor-1/2 &\mbox{if }+-- x\in\mathbf{Q}\setminus\mathbf{Z}\\+-- 0 &\mbox{if }x\in\mathbf{Z}.+-- \end{cases}+-- \end{aligned}\]+--+-- If \(0 < h < k\) and \((h,k) = 1\), this reduces to+--+-- \[`\]+-- \[s(h,k) = \sum_{i=1}^{k-1} \frac{i}{k}+-- \left(\frac{hi}{k}-\left\lfloor\frac{hi}{k}\right\rfloor+-- -\frac{1}{2}\right).\]+--+-- The main formula for evaluating the series above is the following.+-- Letting \(r_0 = k\), \(r_1 = h\), \(r_2, r_3, \ldots, r_n, r_{n+1} = 1\)+-- be the remainder sequence in the Euclidean algorithm for computing GCD+-- of \(h\) and \(k\),+--+-- \[`+-- s(h,k) = \frac{1-(-1)^n}{8} - \frac{1}{12} \sum_{i=1}^{n+1}+-- (-1)^i \left(\frac{1+r_i^2+r_{i-1}^2}{r_i r_{i-1}}\right).\]+--+-- Writing \(s(h,k) = p/q\), some useful properties employed are |s| \< k+-- \/ 12, \(q | 6k\) and \(2|p| < k^2\).+--+-- | /fmpq_dedekind_sum/ /s/ /h/ /k/ +-- +-- Computes \(s(h,k)\) for arbitrary \(h\) and \(k\). The naive version+-- uses a straightforward implementation of the defining sum using @fmpz@+-- arithmetic and is slow for large \(k\).+foreign import ccall "fmpq.h fmpq_dedekind_sum"+ fmpq_dedekind_sum :: Ptr CFmpq -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpq.h fmpq_dedekind_sum_naive"+ fmpq_dedekind_sum_naive :: Ptr CFmpq -> Ptr CFmpz -> Ptr CFmpz -> IO ()
+ src/Data/Number/Flint/Fmpq/Instances.hs view
@@ -0,0 +1,133 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Fmpq.Instances (+ Fmpq (..)+) where++import System.IO.Unsafe+import Control.Monad++import qualified Data.Ratio as Ratio+import Data.Ratio ((%))++import Foreign.Storable+import Foreign.C.Types+import Foreign.C.String+import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Marshal.Alloc++import Data.Char+import Text.Read+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Instances+import Data.Number.Flint.Fmpq++instance Show Fmpq where+ show x = snd $ unsafePerformIO $ do+ let base = 10 :: CInt+ withFmpq x $ \x -> do+ cs <- fmpq_get_str nullPtr 10 x+ s <- peekCString cs+ free cs+ return s++instance Read Fmpq where+ readsPrec _ r = unsafePerformIO $ do+ result <- newFmpq+ (_, flag) <- withFmpq result $ \result ->+ withCString r $ \r ->+ fmpq_set_str result r 10+ if flag == 0 then + return [(result, drop (length (show result)) r)]+ else+ return []+ +instance Eq Fmpq where+ (==) x y = snd $ snd $ unsafePerformIO $ + withFmpq x $ \x ->+ withFmpq y $ \y -> do+ result <- fmpq_equal x y+ return $ result == 1++instance Ord Fmpq where+ compare x y = snd $ snd $ unsafePerformIO $ + withFmpq x $ \x ->+ withFmpq y $ \y -> do+ ord <- fmpq_cmp x y+ return $ if ord > 0 then GT else (if ord < 0 then LT else EQ)+ +instance Num Fmpq where+ {-# INLINE (+) #-}+ (+) = lift2 fmpq_add+ {-# INLINE (-) #-}+ (-) = lift2 fmpq_sub+ {-# INLINE (*) #-}+ (*) = lift2 fmpq_mul+ negate = lift1 fmpq_neg+ abs = lift1 fmpq_abs+ fromInteger x = unsafePerformIO $ do+ let n = fromInteger x + d = 1 :: Fmpz+ result <- newFmpq+ withFmpz n $ \n ->+ withFmpz d $ \d ->+ withFmpq result $ \result -> do+ fmpz_one d+ fmpq_set_fmpz_frac result n d+ fmpq_canonicalise result+ return result+ signum = lift1 sgn where+ sgn result x = do+ s <- fmpq_sgn x+ fmpq_set_si result (fromIntegral s) 1++instance Fractional Fmpq where+ (/) = lift2 fmpq_div+ recip = lift1 fmpq_inv+ fromRational x = unsafePerformIO $ do+ result <- newFmpq+ let n = fromInteger $ Ratio.numerator x+ d = fromInteger $ Ratio.denominator x+ withFmpz n $ \n ->+ withFmpz d $ \d ->+ withFmpq result $ \result -> do+ fmpq_set_fmpz_frac result n d+ fmpq_canonicalise result+ return result++instance Real Fmpq where+ toRational x = unsafePerformIO $ do+ p <- newFmpz+ q <- newFmpz+ withFmpq x $ \x -> do+ withFmpz p $ \p -> do+ withFmpz q $ \q -> do+ fmpq_get_fmpz_frac p q x+ return $ (toInteger p) % (toInteger q)++instance RealFrac Fmpq where+ properFraction x = unsafePerformIO $ do+ p <- newFmpz+ q <- newFmpz+ r <- newFmpq+ withFmpq x $ \x -> do+ withFmpz p $ \p -> do+ withFmpz q $ \q -> do+ withFmpq r $ \r -> do+ withNewFmpz $ \tmp -> do+ fmpq_get_fmpz_frac p q x+ fmpz_tdiv_qr p tmp p q+ fmpq_set_fmpz_frac r tmp q+ return (fromIntegral p, r)+ +lift1 f x = fst $ unsafePerformIO $ + withNewFmpq $ \result -> + withFmpq x $ \x ->+ f result x+ +lift2 f x y = fst $ unsafePerformIO $ + withNewFmpq $ \result ->+ withFmpq x $ \x ->+ withFmpq y $ \y ->+ f result x y+
+ src/Data/Number/Flint/Fmpq/MPoly.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpq.MPoly (+ module Data.Number.Flint.Fmpq.MPoly.FFI+ ) where++import Data.Number.Flint.Fmpq.MPoly.FFI
+ src/Data/Number/Flint/Fmpq/MPoly/FFI.hsc view
@@ -0,0 +1,1207 @@+{-|+module : Data.Number.Flint.Fmpq.MPoly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpq.MPoly.FFI (+ -- * Multivariate polynomials over the rational numbers+ FmpqMPoly (..)+ , CFmpqMPoly (..)+ , newFmpqMPoly+ , withFmpqMPoly+ -- * Context object+ , FmpqMPolyCtx (..)+ , CFmpqMPolyCtx (..)+ , newFmpqMPolyCtx+ , withFmpqMPolyCtx+ -- * + , fmpq_mpoly_ctx_init+ , fmpq_mpoly_ctx_nvars+ , fmpq_mpoly_ctx_ord+ , fmpq_mpoly_ctx_clear+ -- * Memory management+ , fmpq_mpoly_init+ , fmpq_mpoly_init2+ , fmpq_mpoly_init3+ , fmpq_mpoly_fit_length+ , fmpq_mpoly_fit_bits+ , fmpq_mpoly_realloc+ , fmpq_mpoly_clear+ -- * Input\/Output+ , fmpq_mpoly_get_str_pretty+ , fmpq_mpoly_fprint_pretty+ , fmpq_mpoly_print_pretty+ , fmpq_mpoly_set_str_pretty+ -- * Basic manipulation+ , fmpq_mpoly_gen+ , fmpq_mpoly_is_gen+ , fmpq_mpoly_set+ , fmpq_mpoly_equal+ , fmpq_mpoly_swap+ -- * Constants+ , fmpq_mpoly_is_fmpq+ , fmpq_mpoly_get_fmpq+ , fmpq_mpoly_set_fmpq+ , fmpq_mpoly_set_fmpz+ , fmpq_mpoly_set_ui+ , fmpq_mpoly_set_si+ , fmpq_mpoly_zero+ , fmpq_mpoly_one+ , fmpq_mpoly_equal_fmpq+ , fmpq_mpoly_equal_fmpz+ , fmpq_mpoly_equal_ui+ , fmpq_mpoly_equal_si+ , fmpq_mpoly_is_zero+ , fmpq_mpoly_is_one+ -- * Degrees+ , fmpq_mpoly_degrees_fit_si+ , fmpq_mpoly_degrees_fmpz+ , fmpq_mpoly_degrees_si+ , fmpq_mpoly_degree_fmpz+ , fmpq_mpoly_degree_si+ , fmpq_mpoly_total_degree_fits_si+ , fmpq_mpoly_total_degree_fmpz+ , fmpq_mpoly_total_degree_si+ , fmpq_mpoly_used_vars+ -- * Coefficients+ , fmpq_mpoly_get_denominator+ , fmpq_mpoly_get_coeff_fmpq_monomial+ , fmpq_mpoly_set_coeff_fmpq_monomial+ , fmpq_mpoly_get_coeff_fmpq_fmpz+ , fmpq_mpoly_get_coeff_fmpq_ui+ , fmpq_mpoly_set_coeff_fmpq_fmpz+ , fmpq_mpoly_set_coeff_fmpq_ui+ , fmpq_mpoly_get_coeff_vars_ui+ -- * Comparison+ , fmpq_mpoly_cmp+ -- * Container operations+ , fmpq_mpoly_content_ref+ , fmpq_mpoly_zpoly_ref+ , fmpq_mpoly_zpoly_term_coeff_ref+ , fmpq_mpoly_is_canonical+ , fmpq_mpoly_length+ , fmpq_mpoly_resize+ , fmpq_mpoly_get_term_coeff_fmpq+ , fmpq_mpoly_set_term_coeff_fmpq+ , fmpq_mpoly_term_exp_fits_si+ , fmpq_mpoly_term_exp_fits_ui+ , fmpq_mpoly_get_term_exp_fmpz+ , fmpq_mpoly_get_term_exp_ui+ , fmpq_mpoly_get_term_exp_si+ , fmpq_mpoly_get_term_var_exp_ui+ , fmpq_mpoly_get_term_var_exp_si+ , fmpq_mpoly_set_term_exp_fmpz+ , fmpq_mpoly_set_term_exp_ui+ , fmpq_mpoly_get_term+ , fmpq_mpoly_get_term_monomial+ , fmpq_mpoly_push_term_fmpq_fmpz+ , fmpq_mpoly_push_term_fmpz_fmpz+ , fmpq_mpoly_push_term_ui_fmpz+ , fmpq_mpoly_push_term_si_fmpz+ , fmpq_mpoly_push_term_fmpq_ui+ , fmpq_mpoly_push_term_fmpz_ui+ , fmpq_mpoly_push_term_ui_ui+ , fmpq_mpoly_push_term_si_ui+ , fmpq_mpoly_reduce+ , fmpq_mpoly_sort_terms+ , fmpq_mpoly_combine_like_terms+ -- , fmpq_mpoly_reverse+ -- * Random generation+ , fmpq_mpoly_randtest_bound+ , fmpq_mpoly_randtest_bounds+ , fmpq_mpoly_randtest_bits+ -- * Addition\/Subtraction+ , fmpq_mpoly_add_fmpq+ , fmpq_mpoly_add_fmpz+ , fmpq_mpoly_add_ui+ , fmpq_mpoly_add_si+ , fmpq_mpoly_sub_fmpq+ , fmpq_mpoly_sub_fmpz+ , fmpq_mpoly_sub_ui+ , fmpq_mpoly_sub_si+ , fmpq_mpoly_add+ , fmpq_mpoly_sub+ -- * Scalar operations+ , fmpq_mpoly_neg+ , fmpq_mpoly_scalar_mul_fmpq+ , fmpq_mpoly_scalar_mul_fmpz+ , fmpq_mpoly_scalar_mul_ui+ , fmpq_mpoly_scalar_mul_si+ , fmpq_mpoly_scalar_div_fmpq+ , fmpq_mpoly_scalar_div_fmpz+ , fmpq_mpoly_scalar_div_ui+ , fmpq_mpoly_scalar_div_si+ , fmpq_mpoly_make_monic+ -- * Differentiation\/Integration+ , fmpq_mpoly_derivative+ , fmpq_mpoly_integral+ -- * Evaluation+ , fmpq_mpoly_evaluate_all_fmpq+ , fmpq_mpoly_evaluate_one_fmpq+ , fmpq_mpoly_compose_fmpq_poly+ , fmpq_mpoly_compose_fmpq_mpoly+ , fmpq_mpoly_compose_fmpq_mpoly_gen+ -- * Multiplication+ , fmpq_mpoly_mul+ -- * Powering+ , fmpq_mpoly_pow_fmpz+ , fmpq_mpoly_pow_ui+ -- * Division+ , fmpq_mpoly_divides+ , fmpq_mpoly_div+ , fmpq_mpoly_divrem+ , fmpq_mpoly_divrem_ideal+ -- * Greatest Common Divisor+ , fmpq_mpoly_content+ , fmpq_mpoly_term_content+ , fmpq_mpoly_content_vars+ , fmpq_mpoly_gcd+ , fmpq_mpoly_gcd_cofactors+ , fmpq_mpoly_gcd_brown+ , fmpq_mpoly_gcd_hensel+ , fmpq_mpoly_gcd_subresultant+ , fmpq_mpoly_gcd_zippel+ , fmpq_mpoly_gcd_zippel2+ , fmpq_mpoly_resultant+ , fmpq_mpoly_discriminant+ -- * Square Root+ , fmpq_mpoly_sqrt+ , fmpq_mpoly_is_square+ -- * Univariate Functions+ , fmpq_mpoly_univar_init+ , fmpq_mpoly_univar_clear+ , fmpq_mpoly_univar_swap+ , fmpq_mpoly_to_univar+ , fmpq_mpoly_from_univar+ , fmpq_mpoly_univar_degree_fits_si+ , fmpq_mpoly_univar_length+ , fmpq_mpoly_univar_get_term_exp_si+ , fmpq_mpoly_univar_get_term_coeff+ , fmpq_mpoly_univar_swap_term_coeff+) where++-- Multivariate polynomials over the rational numbers --------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.MPoly+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.MPoly+import Data.Number.Flint.Fmpz.MPoly.Q+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fmpq.Poly++#include <flint/fmpq.h>+#include <flint/fmpq_types.h>+#include <flint/fmpq_mpoly.h>+#include <flint/mpoly_types.h>++-- fmpq_mpoly_t ----------------------------------------------------------------++data FmpqMPoly = FmpqMPoly {-# UNPACK #-} !(ForeignPtr CFmpqMPoly)+data CFmpqMPoly = CFmpqMPoly (Ptr CFmpq) CFmpzMPoly++instance Storable CFmpqMPoly where+ sizeOf _ = #{size fmpq_mpoly_t}+ alignment _ = #{alignment fmpq_mpoly_t}+ peek ptr = CFmpqMPoly+ <$> #{peek fmpq_mpoly_struct, content} ptr+ <*> #{peek fmpq_mpoly_struct, zpoly } ptr+ poke ptr (CFmpqMPoly content zpoly) = do+ #{poke fmpq_mpoly_struct, content} ptr content+ #{poke fmpq_mpoly_struct, zpoly } ptr zpoly+ +newFmpqMPoly ctx@(FmpqMPolyCtx pctx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpqMPolyCtx ctx $ \ctx -> do+ fmpq_mpoly_init x ctx+ addForeignPtrFinalizerEnv p_fmpq_mpoly_clear x pctx+ return $ FmpqMPoly x++withFmpqMPoly (FmpqMPoly x) f = do+ withForeignPtr x $ \xp -> (FmpqMPoly x,) <$> f xp++-- fmpq_mpoly_univar_t ---------------------------------------------------------++data FmpqMPolyUniVar = FmpqMPolyUniVar {-# UNPACK #-} !(ForeignPtr CFmpqMPolyUniVar)+data CFmpqMPolyUniVar = CFmpqMPolyUniVar ++instance Storable CFmpqMPolyUniVar where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpq_mpoly_univar_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpq_mpoly_univar_t}+ peek = error "CFmpqMPolyUniVar.peek: Not defined"+ poke = error "CFmpqMPolyUniVar.poke: Not defined"++-- | Create a new `FmpqMPolyUniVar`+newFmpqMPolyUniVar ctx@(FmpqMPolyCtx pctx) = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withFmpqMPolyCtx ctx $ \ctx -> do + fmpq_mpoly_univar_init p ctx+ addForeignPtrFinalizerEnv p_fmpq_mpoly_univar_clear p pctx+ return $ FmpqMPolyUniVar p++{-# INLINE withFmpqMPolyUniVar #-}+withFmpqMPolyUniVar (FmpqMPolyUniVar p) f = do+ withForeignPtr p $ \fp -> (FmpqMPolyUniVar p,) <$> f fp+ +-- fmpz_mpoly_ctx_t ------------------------------------------------------------++data FmpqMPolyCtx = FmpqMPolyCtx {-# UNPACK #-} !(ForeignPtr CFmpqMPolyCtx)+data CFmpqMPolyCtx++instance Storable CFmpqMPolyCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpq_mpoly_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpq_mpoly_ctx_t}+ peek = error "CFmpqMPolyCtx.peek: Not defined"+ poke = error "CFmpqMPolyCtx.poke: Not defined"++-- | Create a new `FmpqMPolyCtx`+newFmpqMPolyCtx nvars ord = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ fmpq_mpoly_ctx_init p nvars ord+ addForeignPtrFinalizer p_fmpq_mpoly_ctx_clear p+ return $ FmpqMPolyCtx p++-- | Use a `FmpqMPolyCtx`+{-# INLINE withFmpqMPolyCtx #-}+withFmpqMPolyCtx (FmpqMPolyCtx p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpqMPolyCtx p,)++-- Context object --------------------------------------------------------------++-- | /fmpq_mpoly_ctx_init/ /ctx/ /nvars/ /ord/ +--+-- Initialise a context object for a polynomial ring with the given number+-- of variables and the given ordering. The possibilities for the ordering+-- are @ORD_LEX@, @ORD_DEGLEX@ and @ORD_DEGREVLEX@.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_ctx_init"+ fmpq_mpoly_ctx_init :: Ptr CFmpqMPolyCtx -> CLong -> Ptr COrdering -> IO ()++-- | /fmpq_mpoly_ctx_nvars/ /ctx/ +--+-- Return the number of variables used to initialize the context.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_ctx_nvars"+ fmpq_mpoly_ctx_nvars :: Ptr CFmpqMPolyCtx -> IO CLong++-- | /fmpq_mpoly_ctx_ord/ /ctx/ +--+-- Return the ordering used to initialize the context.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_ctx_ord"+ fmpq_mpoly_ctx_ord :: Ptr CFmpqMPolyCtx -> IO (Ptr COrdering)++-- | /fmpq_mpoly_ctx_clear/ /ctx/ +--+-- Release up any space allocated by /ctx/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_ctx_clear"+ fmpq_mpoly_ctx_clear :: Ptr CFmpqMPolyCtx -> IO ()++foreign import ccall "fmpq_mpoly.h &fmpq_mpoly_ctx_clear"+ p_fmpq_mpoly_ctx_clear :: FunPtr (Ptr CFmpqMPolyCtx -> IO ())++-- Memory management -----------------------------------------------------------++-- | /fmpq_mpoly_init/ /A/ /ctx/ +--+-- Initialise /A/ for use with the given and initialised context object.+-- Its value is set to zero.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_init"+ fmpq_mpoly_init :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_init2/ /A/ /alloc/ /ctx/ +--+-- Initialise /A/ for use with the given and initialised context object.+-- Its value is set to zero. It is allocated with space for /alloc/ terms+-- and at least @MPOLY_MIN_BITS@ bits for the exponents.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_init2"+ fmpq_mpoly_init2 :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_init3/ /A/ /alloc/ /bits/ /ctx/ +--+-- Initialise /A/ for use with the given and initialised context object.+-- Its value is set to zero. It is allocated with space for /alloc/ terms+-- and /bits/ bits for the exponents.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_init3"+ fmpq_mpoly_init3 :: Ptr CFmpqMPoly -> CLong -> CFBitCnt -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_fit_length/ /A/ /len/ /ctx/ +--+-- Ensure that /A/ has space for at least /len/ terms.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_fit_length"+ fmpq_mpoly_fit_length :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_fit_bits/ /A/ /bits/ /ctx/ +--+-- Ensure that the exponent fields of /A/ have at least /bits/ bits.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_fit_bits"+ fmpq_mpoly_fit_bits :: Ptr CFmpqMPoly -> CFBitCnt -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_realloc/ /A/ /alloc/ /ctx/ +--+-- Reallocate /A/ to have space for /alloc/ terms. Assumes the current+-- length of the polynomial is not greater than /alloc/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_realloc"+ fmpq_mpoly_realloc :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_clear/ /A/ /ctx/ +--+-- Release any space allocated for /A/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_clear"+ fmpq_mpoly_clear :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++foreign import ccall "fmpq_mpoly.h &fmpq_mpoly_clear"+ p_fmpq_mpoly_clear :: FunPtr (Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ())++-- Input\/Output ---------------------------------------------------------------++-- | /fmpq_mpoly_get_str_pretty/ /A/ /x/ /ctx/ +--+-- Return a string, which the user is responsible for cleaning up,+-- representing /A/, given an array of variable strings @x@.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_str_pretty"+ fmpq_mpoly_get_str_pretty :: Ptr CFmpqMPoly -> Ptr (Ptr CChar) -> Ptr CFmpqMPolyCtx -> IO CString++-- | /fmpq_mpoly_fprint_pretty/ /file/ /A/ /x/ /ctx/ +--+-- Print a string representing /A/ to /file/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_fprint_pretty"+ fmpq_mpoly_fprint_pretty :: Ptr CFile -> Ptr CFmpqMPoly -> Ptr (Ptr CChar) -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_print_pretty/ /A/ /x/ /ctx/ +--+-- Print a string representing /A/ to @stdout@.+-- foreign import ccall "fmpq_mpoly.h fmpq_mpoly_print_pretty"+fmpq_mpoly_print_pretty :: Ptr CFmpqMPoly+ -> Ptr (Ptr CChar)+ -> Ptr CFmpqMPolyCtx+ -> IO CInt+fmpq_mpoly_print_pretty a x ctx = + printCStr (\a -> fmpq_mpoly_get_str_pretty a x ctx) a++-- | /fmpq_mpoly_set_str_pretty/ /A/ /str/ /x/ /ctx/ +--+-- Set /A/ to the polynomial in the null-terminates string @str@ given an+-- array @x@ of variable strings. If parsing @str@ fails, /A/ is set to+-- zero, and \(-1\) is returned. Otherwise, \(0\) is returned. The+-- operations @+@, @-@, @*@, and @\/@ are permitted along with integers and+-- the variables in @x@. The character @^@ must be immediately followed by+-- the (integer) exponent. If any division is not exact, parsing fails.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set_str_pretty"+ fmpq_mpoly_set_str_pretty :: Ptr CFmpqMPoly -> CString -> Ptr (Ptr CChar) -> Ptr CFmpqMPolyCtx -> IO CInt++-- Basic manipulation ----------------------------------------------------------++-- | /fmpq_mpoly_gen/ /A/ /var/ /ctx/ +--+-- Set /A/ to the variable of index /var/, where @var = 0@ corresponds to+-- the variable with the most significance with respect to the ordering.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_gen"+ fmpq_mpoly_gen :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_is_gen/ /A/ /var/ /ctx/ +--+-- If \(var \ge 0\), return \(1\) if /A/ is equal to the \(var\)-th+-- generator, otherwise return \(0\). If \(var < 0\), return \(1\) if the+-- polynomial is equal to any generator, otherwise return \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_is_gen"+ fmpq_mpoly_is_gen :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_set/ /A/ /B/ /ctx/ +--+-- Set /A/ to /B/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set"+ fmpq_mpoly_set :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_equal/ /A/ /B/ /ctx/ +--+-- Return \(1\) if /A/ is equal to /B/, else return \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_equal"+ fmpq_mpoly_equal :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_swap/ /A/ /B/ /ctx/ +--+-- Efficiently swap /A/ and /B/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_swap"+ fmpq_mpoly_swap :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- Constants -------------------------------------------------------------------++-- | /fmpq_mpoly_is_fmpq/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is a constant, else return \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_is_fmpq"+ fmpq_mpoly_is_fmpq :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_get_fmpq/ /c/ /A/ /ctx/ +--+-- Assuming that /A/ is a constant, set /c/ to this constant. This function+-- throws if /A/ is not a constant.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_fmpq"+ fmpq_mpoly_get_fmpq :: Ptr CFmpq -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_set_fmpq/ /A/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set_fmpq"+ fmpq_mpoly_set_fmpq :: Ptr CFmpqMPoly -> Ptr CFmpq -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_set_fmpz/ /A/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set_fmpz"+ fmpq_mpoly_set_fmpz :: Ptr CFmpqMPoly -> Ptr CFmpz -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_set_ui/ /A/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set_ui"+ fmpq_mpoly_set_ui :: Ptr CFmpqMPoly -> CULong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_set_si/ /A/ /c/ /ctx/ +--+-- Set /A/ to the constant /c/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set_si"+ fmpq_mpoly_set_si :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_zero/ /A/ /ctx/ +--+-- Set /A/ to the constant \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_zero"+ fmpq_mpoly_zero :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_one/ /A/ /ctx/ +--+-- Set /A/ to the constant \(1\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_one"+ fmpq_mpoly_one :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_equal_fmpq/ /A/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_equal_fmpq"+ fmpq_mpoly_equal_fmpq :: Ptr CFmpqMPoly -> Ptr CFmpq -> Ptr CFmpqMPolyCtx -> IO CInt+-- | /fmpq_mpoly_equal_fmpz/ /A/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_equal_fmpz"+ fmpq_mpoly_equal_fmpz :: Ptr CFmpqMPoly -> Ptr CFmpz -> Ptr CFmpqMPolyCtx -> IO CInt+-- | /fmpq_mpoly_equal_ui/ /A/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_equal_ui"+ fmpq_mpoly_equal_ui :: Ptr CFmpqMPoly -> CULong -> Ptr CFmpqMPolyCtx -> IO CInt+-- | /fmpq_mpoly_equal_si/ /A/ /c/ /ctx/ +--+-- Return \(1\) if /A/ is equal to the constant /c/, else return \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_equal_si"+ fmpq_mpoly_equal_si :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_is_zero/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is equal to the constant \(0\), else return \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_is_zero"+ fmpq_mpoly_is_zero :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_is_one/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is equal to the constant \(1\), else return \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_is_one"+ fmpq_mpoly_is_one :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- Degrees ---------------------------------------------------------------------++-- | /fmpq_mpoly_degrees_fit_si/ /A/ /ctx/ +--+-- Return \(1\) if the degrees of /A/ with respect to each variable fit+-- into an @slong@, otherwise return \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_degrees_fit_si"+ fmpq_mpoly_degrees_fit_si :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_degrees_fmpz/ /degs/ /A/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_degrees_fmpz"+ fmpq_mpoly_degrees_fmpz :: Ptr (Ptr CFmpz) -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_degrees_si/ /degs/ /A/ /ctx/ +--+-- Set /degs/ to the degrees of /A/ with respect to each variable. If /A/+-- is zero, all degrees are set to \(-1\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_degrees_si"+ fmpq_mpoly_degrees_si :: Ptr CLong -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_degree_fmpz/ /deg/ /A/ /var/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_degree_fmpz"+ fmpq_mpoly_degree_fmpz :: Ptr CFmpz -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_degree_si/ /A/ /var/ /ctx/ +--+-- Either return or set /deg/ to the degree of /A/ with respect to the+-- variable of index /var/. If /A/ is zero, the degree is defined to be+-- \(-1\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_degree_si"+ fmpq_mpoly_degree_si :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO CLong++-- | /fmpq_mpoly_total_degree_fits_si/ /A/ /ctx/ +--+-- Return \(1\) if the total degree of /A/ fits into an @slong@, otherwise+-- return \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_total_degree_fits_si"+ fmpq_mpoly_total_degree_fits_si :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_total_degree_fmpz/ /tdeg/ /A/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_total_degree_fmpz"+ fmpq_mpoly_total_degree_fmpz :: Ptr CFmpz -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_total_degree_si/ /A/ /ctx/ +--+-- Either return or set /tdeg/ to the total degree of /A/. If /A/ is zero,+-- the total degree is defined to be \(-1\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_total_degree_si"+ fmpq_mpoly_total_degree_si :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CLong++-- | /fmpq_mpoly_used_vars/ /used/ /A/ /ctx/ +--+-- For each variable index /i/, set @used[i]@ to nonzero if the variable of+-- index /i/ appears in /A/ and to zero otherwise.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_used_vars"+ fmpq_mpoly_used_vars :: Ptr CInt -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- Coefficients ----------------------------------------------------------------++-- | /fmpq_mpoly_get_denominator/ /d/ /A/ /ctx/ +--+-- Set /d/ to the denominator of /A/, the smallest positive integer \(d\)+-- such that \(d \times A\) has integer coefficients.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_denominator"+ fmpq_mpoly_get_denominator :: Ptr CFmpz -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_get_coeff_fmpq_monomial/ /c/ /A/ /M/ /ctx/ +--+-- Assuming that /M/ is a monomial, set /c/ to the coefficient of the+-- corresponding monomial in /A/. This function throws if /M/ is not a+-- monomial.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_coeff_fmpq_monomial"+ fmpq_mpoly_get_coeff_fmpq_monomial :: Ptr CFmpq -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_set_coeff_fmpq_monomial/ /A/ /c/ /M/ /ctx/ +--+-- Assuming that /M/ is a monomial, set the coefficient of the+-- corresponding monomial in /A/ to /c/. This function throws if /M/ is not+-- a monomial.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set_coeff_fmpq_monomial"+ fmpq_mpoly_set_coeff_fmpq_monomial :: Ptr CFmpqMPoly -> Ptr CFmpq -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_get_coeff_fmpq_fmpz/ /c/ /A/ /exp/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_coeff_fmpq_fmpz"+ fmpq_mpoly_get_coeff_fmpq_fmpz :: Ptr CFmpq -> Ptr CFmpqMPoly -> Ptr (Ptr CFmpz) -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_get_coeff_fmpq_ui/ /c/ /A/ /exp/ /ctx/ +--+-- Set /c/ to the coefficient of the monomial with exponent /exp/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_coeff_fmpq_ui"+ fmpq_mpoly_get_coeff_fmpq_ui :: Ptr CFmpq -> Ptr CFmpqMPoly -> Ptr CULong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_set_coeff_fmpq_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set_coeff_fmpq_fmpz"+ fmpq_mpoly_set_coeff_fmpq_fmpz :: Ptr CFmpqMPoly -> Ptr CFmpq -> Ptr (Ptr CFmpz) -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_set_coeff_fmpq_ui/ /A/ /c/ /exp/ /ctx/ +--+-- Set the coefficient of the monomial with exponent /exp/ to /c/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set_coeff_fmpq_ui"+ fmpq_mpoly_set_coeff_fmpq_ui :: Ptr CFmpqMPoly -> Ptr CFmpq -> Ptr CULong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_get_coeff_vars_ui/ /C/ /A/ /vars/ /exps/ /length/ /ctx/ +--+-- Set /C/ to the coefficient of /A/ with respect to the variables in+-- /vars/ with powers in the corresponding array /exps/. Both /vars/ and+-- /exps/ point to array of length /length/. It is assumed that+-- \(0 < length \le nvars(A)\) and that the variables in /vars/ are+-- distinct.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_coeff_vars_ui"+ fmpq_mpoly_get_coeff_vars_ui :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CLong -> Ptr CULong -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fmpq_mpoly_cmp/ /A/ /B/ /ctx/ +--+-- Return \(1\) (resp. \(-1\), or \(0\)) if /A/ is after (resp. before,+-- same as) /B/ in some arbitrary but fixed total ordering of the+-- polynomials. This ordering agrees with the usual ordering of monomials+-- when /A/ and /B/ are both monomials.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_cmp"+ fmpq_mpoly_cmp :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- Container operations --------------------------------------------------------+++++-- | /fmpq_mpoly_content_ref/ /A/ /ctx/ +--+-- Return a reference to the content of /A/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_content_ref"+ fmpq_mpoly_content_ref :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO (Ptr CFmpq)++-- | /fmpq_mpoly_zpoly_ref/ /A/ /ctx/ +--+-- Return a reference to the integer polynomial of /A/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_zpoly_ref"+ fmpq_mpoly_zpoly_ref :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO (Ptr (Ptr CFmpzMPoly))++-- | /fmpq_mpoly_zpoly_term_coeff_ref/ /A/ /i/ /ctx/ +--+-- Return a reference to the coefficient of index /i/ of the integer+-- polynomial of /A/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_zpoly_term_coeff_ref"+ fmpq_mpoly_zpoly_term_coeff_ref :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO (Ptr CFmpz)++-- | /fmpq_mpoly_is_canonical/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is in canonical form. Otherwise, return \(0\). An+-- @fmpq_mpoly_t@ is represented as the product of an @fmpq_t content@ and+-- an @fmpz_mpoly_t zpoly@. The representation is considered canonical when+-- either (1) both @content@ and @zpoly@ are zero, or (2) both @content@+-- and @zpoly@ are nonzero and canonical and @zpoly@ is reduced. A nonzero+-- @zpoly@ is considered reduced when the coefficients have GCD one and the+-- leading coefficient is positive.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_is_canonical"+ fmpq_mpoly_is_canonical :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_length/ /A/ /ctx/ +--+-- Return the number of terms stored in /A/. If the polynomial is in+-- canonical form, this will be the number of nonzero coefficients.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_length"+ fmpq_mpoly_length :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CLong++-- | /fmpq_mpoly_resize/ /A/ /new_length/ /ctx/ +--+-- Set the length of /A/ to @new_length@. Terms are either deleted from the+-- end, or new zero terms are appended.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_resize"+ fmpq_mpoly_resize :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_get_term_coeff_fmpq/ /c/ /A/ /i/ /ctx/ +--+-- Set /c/ to coefficient of index /i/+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_term_coeff_fmpq"+ fmpq_mpoly_get_term_coeff_fmpq :: Ptr CFmpq -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_set_term_coeff_fmpq/ /A/ /i/ /c/ /ctx/ +--+-- Set the coefficient of index /i/ to /c/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set_term_coeff_fmpq"+ fmpq_mpoly_set_term_coeff_fmpq :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpq -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_term_exp_fits_si/ /A/ /i/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_term_exp_fits_si"+ fmpq_mpoly_term_exp_fits_si :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO CInt+-- | /fmpq_mpoly_term_exp_fits_ui/ /A/ /i/ /ctx/ +--+-- Return \(1\) if all entries of the exponent vector of the term of index+-- /i/ fit into an @slong@ (resp. a @ulong@). Otherwise, return \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_term_exp_fits_ui"+ fmpq_mpoly_term_exp_fits_ui :: Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_get_term_exp_fmpz/ /exps/ /A/ /i/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_term_exp_fmpz"+ fmpq_mpoly_get_term_exp_fmpz :: Ptr (Ptr CFmpz) -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_get_term_exp_ui/ /exps/ /A/ /i/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_term_exp_ui"+ fmpq_mpoly_get_term_exp_ui :: Ptr CULong -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_get_term_exp_si/ /exps/ /A/ /i/ /ctx/ +--+-- Set /exp/ to the exponent vector of the term of index /i/. The @_ui@+-- (resp. @_si@) version throws if any entry does not fit into a @ulong@+-- (resp. @slong@).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_term_exp_si"+ fmpq_mpoly_get_term_exp_si :: Ptr CLong -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_get_term_var_exp_ui/ /A/ /i/ /var/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_term_var_exp_ui"+ fmpq_mpoly_get_term_var_exp_ui :: Ptr CFmpqMPoly -> CLong -> CLong -> Ptr CFmpqMPolyCtx -> IO CULong+-- | /fmpq_mpoly_get_term_var_exp_si/ /A/ /i/ /var/ /ctx/ +--+-- Return the exponent of the variable /var/ of the term of index /i/. This+-- function throws if the exponent does not fit into a @ulong@ (resp.+-- @slong@).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_term_var_exp_si"+ fmpq_mpoly_get_term_var_exp_si :: Ptr CFmpqMPoly -> CLong -> CLong -> Ptr CFmpqMPolyCtx -> IO CLong++-- | /fmpq_mpoly_set_term_exp_fmpz/ /A/ /i/ /exps/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set_term_exp_fmpz"+ fmpq_mpoly_set_term_exp_fmpz :: Ptr CFmpqMPoly -> CLong -> Ptr (Ptr CFmpz) -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_set_term_exp_ui/ /A/ /i/ /exps/ /ctx/ +--+-- Set the exponent vector of the term of index /i/ to /exp/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_set_term_exp_ui"+ fmpq_mpoly_set_term_exp_ui :: Ptr CFmpqMPoly -> CLong -> Ptr CULong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_get_term/ /M/ /A/ /i/ /ctx/ +--+-- Set /M/ to the term of index /i/ in /A/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_term"+ fmpq_mpoly_get_term :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_get_term_monomial/ /M/ /A/ /i/ /ctx/ +--+-- Set /M/ to the monomial of the term of index /i/ in /A/. The coefficient+-- of /M/ will be one.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_get_term_monomial"+ fmpq_mpoly_get_term_monomial :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_push_term_fmpq_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_push_term_fmpq_fmpz"+ fmpq_mpoly_push_term_fmpq_fmpz :: Ptr CFmpqMPoly -> Ptr CFmpq -> Ptr (Ptr CFmpz) -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_push_term_fmpz_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_push_term_fmpz_fmpz"+ fmpq_mpoly_push_term_fmpz_fmpz :: Ptr CFmpqMPoly -> Ptr CFmpz -> Ptr (Ptr CFmpz) -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_push_term_ui_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_push_term_ui_fmpz"+ fmpq_mpoly_push_term_ui_fmpz :: Ptr CFmpqMPoly -> CULong -> Ptr (Ptr CFmpz) -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_push_term_si_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_push_term_si_fmpz"+ fmpq_mpoly_push_term_si_fmpz :: Ptr CFmpqMPoly -> CLong -> Ptr (Ptr CFmpz) -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_push_term_fmpq_ui/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_push_term_fmpq_ui"+ fmpq_mpoly_push_term_fmpq_ui :: Ptr CFmpqMPoly -> Ptr CFmpq -> Ptr CULong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_push_term_fmpz_ui/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_push_term_fmpz_ui"+ fmpq_mpoly_push_term_fmpz_ui :: Ptr CFmpqMPoly -> Ptr CFmpz -> Ptr CULong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_push_term_ui_ui/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_push_term_ui_ui"+ fmpq_mpoly_push_term_ui_ui :: Ptr CFmpqMPoly -> CULong -> Ptr CULong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_push_term_si_ui/ /A/ /c/ /exp/ /ctx/ +--+-- Append a term to /A/ with coefficient /c/ and exponent vector /exp/.+-- This function should run in constant average time if the terms pushed+-- have bounded denominator.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_push_term_si_ui"+ fmpq_mpoly_push_term_si_ui :: Ptr CFmpqMPoly -> CLong -> Ptr CULong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_reduce/ /A/ /ctx/ +--+-- Factor out necessary content from @A->zpoly@ so that it is reduced. If+-- the terms of /A/ were nonzero and sorted with distinct exponents to+-- begin with, the result will be in canonical form.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_reduce"+ fmpq_mpoly_reduce :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_sort_terms/ /A/ /ctx/ +--+-- Sort the internal @A->zpoly@ into the canonical ordering dictated by the+-- ordering in /ctx/. This function does not combine like terms, nor does+-- it delete terms with coefficient zero, nor does it reduce.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_sort_terms"+ fmpq_mpoly_sort_terms :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_combine_like_terms/ /A/ /ctx/ +--+-- Combine adjacent like terms in the internal @A->zpoly@ and then factor+-- out content via a call to @fmpq_mpoly_reduce@. If the terms of /A/ were+-- sorted to begin with, the result will be in canonical form.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_combine_like_terms"+ fmpq_mpoly_combine_like_terms :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- -- | /fmpq_mpoly_reverse/ /A/ /B/ /ctx/ +-- --+-- -- Set /A/ to the reversal of /B/.+-- foreign import ccall "fmpq_mpoly.h fmpq_mpoly_reverse"+-- fmpq_mpoly_reverse :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- Random generation -----------------------------------------------------------++-- | /fmpq_mpoly_randtest_bound/ /A/ /state/ /length/ /coeff_bits/ /exp_bound/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents in+-- the range @[0, exp_bound - 1]@. The exponents of each variable are+-- generated by calls to @n_randint(state, exp_bound)@.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_randtest_bound"+ fmpq_mpoly_randtest_bound :: Ptr CFmpqMPoly -> Ptr CFRandState -> CLong -> CMpLimb -> CULong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_randtest_bounds/ /A/ /state/ /length/ /coeff_bits/ /exp_bounds/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents in+-- the range @[0, exp_bounds[i] - 1]@. The exponents of the variable of+-- index /i/ are generated by calls to @n_randint(state, exp_bounds[i])@.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_randtest_bounds"+ fmpq_mpoly_randtest_bounds :: Ptr CFmpqMPoly -> Ptr CFRandState -> CLong -> CMpLimb -> Ptr CULong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_randtest_bits/ /A/ /state/ /length/ /coeff_bits/ /exp_bits/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents+-- whose packed form does not exceed the given bit count.+-- +-- The parameter @coeff_bits@ to the three functions+-- @fmpq_mpoly_randtest_{bound|bounds|bits}@ is merely a suggestion for the+-- approximate bit count of the resulting coefficients.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_randtest_bits"+ fmpq_mpoly_randtest_bits :: Ptr CFmpqMPoly -> Ptr CFRandState -> CLong -> CMpLimb -> CMpLimb -> Ptr CFmpqMPolyCtx -> IO ()++-- Addition\/Subtraction -------------------------------------------------------++-- | /fmpq_mpoly_add_fmpq/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_add_fmpq"+ fmpq_mpoly_add_fmpq :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpq -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_add_fmpz/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_add_fmpz"+ fmpq_mpoly_add_fmpz :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpz -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_add_ui/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_add_ui"+ fmpq_mpoly_add_ui :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CULong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_add_si/ /A/ /B/ /c/ /ctx/ +--+-- Set /A/ to \(B + c\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_add_si"+ fmpq_mpoly_add_si :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_sub_fmpq/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_sub_fmpq"+ fmpq_mpoly_sub_fmpq :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpq -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_sub_fmpz/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_sub_fmpz"+ fmpq_mpoly_sub_fmpz :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpz -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_sub_ui/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_sub_ui"+ fmpq_mpoly_sub_ui :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CULong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_sub_si/ /A/ /B/ /c/ /ctx/ +--+-- Set /A/ to \(B - c\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_sub_si"+ fmpq_mpoly_sub_si :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_add/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B + C\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_add"+ fmpq_mpoly_add :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_sub/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B - C\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_sub"+ fmpq_mpoly_sub :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- Scalar operations -----------------------------------------------------------++-- | /fmpq_mpoly_neg/ /A/ /B/ /ctx/ +--+-- Set /A/ to \(-B\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_neg"+ fmpq_mpoly_neg :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_scalar_mul_fmpq/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_scalar_mul_fmpq"+ fmpq_mpoly_scalar_mul_fmpq :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpq -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_scalar_mul_fmpz/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_scalar_mul_fmpz"+ fmpq_mpoly_scalar_mul_fmpz :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpz -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_scalar_mul_ui/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_scalar_mul_ui"+ fmpq_mpoly_scalar_mul_ui :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CULong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_scalar_mul_si/ /A/ /B/ /c/ /ctx/ +--+-- Set /A/ to \(B \times c\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_scalar_mul_si"+ fmpq_mpoly_scalar_mul_si :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_scalar_div_fmpq/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_scalar_div_fmpq"+ fmpq_mpoly_scalar_div_fmpq :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpq -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_scalar_div_fmpz/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_scalar_div_fmpz"+ fmpq_mpoly_scalar_div_fmpz :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpz -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_scalar_div_ui/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_scalar_div_ui"+ fmpq_mpoly_scalar_div_ui :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CULong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_scalar_div_si/ /A/ /B/ /c/ /ctx/ +--+-- Set /A/ to \(B/c\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_scalar_div_si"+ fmpq_mpoly_scalar_div_si :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_make_monic/ /A/ /B/ /ctx/ +--+-- Set /A/ to /B/ divided by the leading coefficient of /B/. This throws if+-- /B/ is zero.+-- +-- All of these functions run quickly if /A/ and /B/ are aliased.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_make_monic"+ fmpq_mpoly_make_monic :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- Differentiation\/Integration ------------------------------------------------++-- | /fmpq_mpoly_derivative/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to the derivative of /B/ with respect to the variable of index+-- /var/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_derivative"+ fmpq_mpoly_derivative :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_integral/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to the integral with the fewest number of terms of /B/ with+-- respect to the variable of index /var/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_integral"+ fmpq_mpoly_integral :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- Evaluation ------------------------------------------------------------------+++++-- | /fmpq_mpoly_evaluate_all_fmpq/ /ev/ /A/ /vals/ /ctx/ +--+-- Set @ev@ to the evaluation of /A/ where the variables are replaced by+-- the corresponding elements of the array @vals@. Return \(1\) for success+-- and \(0\) for failure.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_evaluate_all_fmpq"+ fmpq_mpoly_evaluate_all_fmpq :: Ptr CFmpq -> Ptr CFmpqMPoly -> Ptr (Ptr CFmpq) -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_evaluate_one_fmpq/ /A/ /B/ /var/ /val/ /ctx/ +--+-- Set /A/ to the evaluation of /B/ where the variable of index /var/ is+-- replaced by @val@. Return \(1\) for success and \(0\) for failure.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_evaluate_one_fmpq"+ fmpq_mpoly_evaluate_one_fmpq :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpq -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_compose_fmpq_poly/ /A/ /B/ /C/ /ctxB/ +--+-- Set /A/ to the evaluation of /B/ where the variables are replaced by the+-- corresponding elements of the array /C/. The context object of /B/ is+-- /ctxB/. Return \(1\) for success and \(0\) for failure.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_compose_fmpq_poly"+ fmpq_mpoly_compose_fmpq_poly :: Ptr CFmpqPoly -> Ptr CFmpqMPoly -> Ptr (Ptr (Ptr (Ptr CFmpqPoly))) -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_compose_fmpq_mpoly/ /A/ /B/ /C/ /ctxB/ /ctxAC/ +--+-- Set /A/ to the evaluation of /B/ where the variables are replaced by the+-- corresponding elements of the array /C/. Both /A/ and the elements of+-- /C/ have context object /ctxAC/, while /B/ has context object /ctxB/.+-- Neither /A/ nor /B/ is allowed to alias any other polynomial. Return+-- \(1\) for success and \(0\) for failure.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_compose_fmpq_mpoly"+ fmpq_mpoly_compose_fmpq_mpoly :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr (Ptr (Ptr CFmpqMPoly)) -> Ptr CFmpqMPolyCtx -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_compose_fmpq_mpoly_gen/ /A/ /B/ /c/ /ctxB/ /ctxAC/ +--+-- Set /A/ to the evaluation of /B/ where the variable of index /i/ in+-- /ctxB/ is replaced by the variable of index @c[i]@ in /ctxAC/. The+-- length of the array /C/ is the number of variables in /ctxB/. If any+-- @c[i]@ is negative, the corresponding variable of /B/ is replaced by+-- zero. Otherwise, it is expected that @c[i]@ is less than the number of+-- variables in /ctxAC/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_compose_fmpq_mpoly_gen"+ fmpq_mpoly_compose_fmpq_mpoly_gen :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CLong -> Ptr CFmpqMPolyCtx -> Ptr CFmpqMPolyCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /fmpq_mpoly_mul/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B \times C\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_mul"+ fmpq_mpoly_mul :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- Powering --------------------------------------------------------------------+++++-- | /fmpq_mpoly_pow_fmpz/ /A/ /B/ /k/ /ctx/ +--+-- Set /A/ to /B/ raised to the /k/-th power. Return \(1\) for success and+-- \(0\) for failure.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_pow_fmpz"+ fmpq_mpoly_pow_fmpz :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpz -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_pow_ui/ /A/ /B/ /k/ /ctx/ +--+-- Set /A/ to /B/ raised to the /k/-th power. Return \(1\) for success and+-- \(0\) for failure.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_pow_ui"+ fmpq_mpoly_pow_ui :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CULong -> Ptr CFmpqMPolyCtx -> IO CInt++-- Division --------------------------------------------------------------------++-- | /fmpq_mpoly_divides/ /Q/ /A/ /B/ /ctx/ +--+-- If /A/ is divisible by /B/, set /Q/ to the exact quotient and return+-- \(1\). Otherwise, set /Q/ to zero and return \(0\). Note that the+-- function @fmpq_mpoly_div@ may be faster if the quotient is known to be+-- exact.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_divides"+ fmpq_mpoly_divides :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_div/ /Q/ /A/ /B/ /ctx/ +--+-- Set /Q/ to the quotient of /A/ by /B/, discarding the remainder.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_div"+ fmpq_mpoly_div :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_divrem/ /Q/ /R/ /A/ /B/ /ctx/ +--+-- Set /Q/ and /R/ to the quotient and remainder of /A/ divided by /B/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_divrem"+ fmpq_mpoly_divrem :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_divrem_ideal/ /Q/ /R/ /A/ /B/ /len/ /ctx/ +--+-- This function is as per @fmpq_mpoly_divrem@ except that it takes an+-- array of divisor polynomials /B/ and it returns an array of quotient+-- polynomials /Q/. The number of divisor (and hence quotient) polynomials+-- is given by /len/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_divrem_ideal"+ fmpq_mpoly_divrem_ideal :: Ptr (Ptr (Ptr CFmpqMPoly)) -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr (Ptr (Ptr CFmpqMPoly)) -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- Greatest Common Divisor -----------------------------------------------------++-- | /fmpq_mpoly_content/ /g/ /A/ /ctx/ +--+-- Set /g/ to the (nonnegative) gcd of the coefficients of /A/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_content"+ fmpq_mpoly_content :: Ptr CFmpq -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_term_content/ /M/ /A/ /ctx/ +--+-- Set /M/ to the GCD of the terms of /A/. If /A/ is zero, /M/ will be+-- zero. Otherwise, /M/ will be a monomial with coefficient one.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_term_content"+ fmpq_mpoly_term_content :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_content_vars/ /g/ /A/ /vars/ /vars_length/ /ctx/ +--+-- Set /g/ to the GCD of the coefficients of /A/ when viewed as a+-- polynomial in the variables /vars/. Return \(1\) for success and \(0\)+-- for failure. Upon success, /g/ will be independent of the variables+-- /vars/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_content_vars"+ fmpq_mpoly_content_vars :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CLong -> CLong -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_gcd/ /G/ /A/ /B/ /ctx/ +--+-- Try to set /G/ to the monic GCD of /A/ and /B/. The GCD of zero and zero+-- is defined to be zero. If the return is \(1\) the function was+-- successful. Otherwise the return is \(0\) and /G/ is left untouched.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_gcd"+ fmpq_mpoly_gcd :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_gcd_cofactors/ /G/ /Abar/ /Bbar/ /A/ /B/ /ctx/ +--+-- Do the operation of @fmpq_mpoly_gcd@ and also compute \(Abar = A/G\) and+-- \(Bbar = B/G\) if successful.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_gcd_cofactors"+ fmpq_mpoly_gcd_cofactors :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_gcd_brown/ /G/ /A/ /B/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_gcd_brown"+ fmpq_mpoly_gcd_brown :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt+-- | /fmpq_mpoly_gcd_hensel/ /G/ /A/ /B/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_gcd_hensel"+ fmpq_mpoly_gcd_hensel :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt+-- | /fmpq_mpoly_gcd_subresultant/ /G/ /A/ /B/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_gcd_subresultant"+ fmpq_mpoly_gcd_subresultant :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt+-- | /fmpq_mpoly_gcd_zippel/ /G/ /A/ /B/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_gcd_zippel"+ fmpq_mpoly_gcd_zippel :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt+-- | /fmpq_mpoly_gcd_zippel2/ /G/ /A/ /B/ /ctx/ +--+-- Try to set /G/ to the GCD of /A/ and /B/ using various algorithms.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_gcd_zippel2"+ fmpq_mpoly_gcd_zippel2 :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_resultant/ /R/ /A/ /B/ /var/ /ctx/ +--+-- Try to set /R/ to the resultant of /A/ and /B/ with respect to the+-- variable of index /var/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_resultant"+ fmpq_mpoly_resultant :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_discriminant/ /D/ /A/ /var/ /ctx/ +--+-- Try to set /D/ to the discriminant of /A/ with respect to the variable+-- of index /var/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_discriminant"+ fmpq_mpoly_discriminant :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO CInt++-- Square Root -----------------------------------------------------------------++-- | /fmpq_mpoly_sqrt/ /Q/ /A/ /ctx/ +--+-- If /A/ is a perfect square return \(1\) and set /Q/ to the square root+-- with positive leading coefficient. Otherwise return \(0\) and set /Q/ to+-- zero.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_sqrt"+ fmpq_mpoly_sqrt :: Ptr CFmpqMPoly -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_is_square/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is a perfect square, otherwise return \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_is_square"+ fmpq_mpoly_is_square :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- UniVariate Functions --------------------------------------------------------+++++-- | /fmpq_mpoly_univar_init/ /A/ /ctx/ +--+-- Initialize /A/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_univar_init"+ fmpq_mpoly_univar_init :: Ptr CFmpqMPolyUniVar -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_univar_clear/ /A/ /ctx/ +--+-- Clear /A/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_univar_clear"+ fmpq_mpoly_univar_clear :: Ptr CFmpqMPolyUniVar -> Ptr CFmpqMPolyCtx -> IO ()++foreign import ccall "fmpq_mpoly.h &fmpq_mpoly_univar_clear"+ p_fmpq_mpoly_univar_clear :: FunPtr (Ptr CFmpqMPolyUniVar -> Ptr CFmpqMPolyCtx -> IO ())++-- | /fmpq_mpoly_univar_swap/ /A/ /B/ /ctx/ +--+-- Swap /A/ and /B/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_univar_swap"+ fmpq_mpoly_univar_swap :: Ptr CFmpqMPolyUniVar -> Ptr CFmpqMPolyUniVar -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_to_univar/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to a univariate form of /B/ by pulling out the variable of index+-- /var/. The coefficients of /A/ will still belong to the content /ctx/+-- but will not depend on the variable of index /var/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_to_univar"+ fmpq_mpoly_to_univar :: Ptr CFmpqMPolyUniVar -> Ptr CFmpqMPoly -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_from_univar/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to the normal form of /B/ by putting in the variable of index+-- /var/. This function is undefined if the coefficients of /B/ depend on+-- the variable of index /var/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_from_univar"+ fmpq_mpoly_from_univar :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyUniVar -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_univar_degree_fits_si/ /A/ /ctx/ +--+-- Return \(1\) if the degree of /A/ with respect to the main variable fits+-- an @slong@. Otherwise, return \(0\).+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_univar_degree_fits_si"+ fmpq_mpoly_univar_degree_fits_si :: Ptr CFmpqMPolyUniVar -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_univar_length/ /A/ /ctx/ +--+-- Return the number of terms in /A/ with respect to the main variable.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_univar_length"+ fmpq_mpoly_univar_length :: Ptr CFmpqMPolyUniVar -> Ptr CFmpqMPolyCtx -> IO CLong++-- | /fmpq_mpoly_univar_get_term_exp_si/ /A/ /i/ /ctx/ +--+-- Return the exponent of the term of index /i/ of /A/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_univar_get_term_exp_si"+ fmpq_mpoly_univar_get_term_exp_si :: Ptr CFmpqMPolyUniVar -> CLong -> Ptr CFmpqMPolyCtx -> IO CLong++-- | /fmpq_mpoly_univar_get_term_coeff/ /c/ /A/ /i/ /ctx/ +foreign import ccall "fmpq_mpoly.h fmpq_mpoly_univar_get_term_coeff"+ fmpq_mpoly_univar_get_term_coeff :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyUniVar -> CLong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_univar_swap_term_coeff/ /c/ /A/ /i/ /ctx/ +--+-- Set (resp. swap) /c/ to (resp. with) the coefficient of the term of+-- index /i/ of /A/.+foreign import ccall "fmpq_mpoly.h fmpq_mpoly_univar_swap_term_coeff"+ fmpq_mpoly_univar_swap_term_coeff :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyUniVar -> CLong -> Ptr CFmpqMPolyCtx -> IO ()+
+ src/Data/Number/Flint/Fmpq/MPoly/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpq.MPoly.Factor (+ module Data.Number.Flint.Fmpq.MPoly.Factor.FFI+ ) where++import Data.Number.Flint.Fmpq.MPoly.Factor.FFI
+ src/Data/Number/Flint/Fmpq/MPoly/Factor/FFI.hsc view
@@ -0,0 +1,179 @@+{-|+module : Data.Number.Flint.Fmpq.MPoly.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpq.MPoly.Factor.FFI (+ -- * Factorisation of multivariate polynomials over the rational numbers+ -- * Memory management+ FmpqMPolyFactor (..)+ , CFmpqMPolyFactor (..)+ , newFmpqMPolyFactor+ , withFmpqMPolyFactor+ -- * + , fmpq_mpoly_factor_init+ , fmpq_mpoly_factor_clear+ -- * Basic manipulation+ -- , fmpq_mpoly_factor_swap+ , fmpq_mpoly_factor_length+ , fmpq_mpoly_factor_get_constant_fmpq+ , fmpq_mpoly_factor_get_base+ , fmpq_mpoly_factor_swap_base+ , fmpq_mpoly_factor_get_exp_si+ , fmpq_mpoly_factor_sort+ , fmpq_mpoly_factor_make_monic+ , fmpq_mpoly_factor_make_integral+ -- * Factorisation+ , fmpq_mpoly_factor_squarefree+ , fmpq_mpoly_factor+) where++-- factorisation of multivariate polynomials over the rational numbers ---------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.MPoly+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.MPoly+import Data.Number.Flint.Fmpz.MPoly.Q+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fmpq.Poly+import Data.Number.Flint.Fmpq.MPoly++#include <flint/fmpq.h>+#include <flint/fmpq_types.h>+#include <flint/fmpq_mpoly.h>+#include <flint/fmpq_mpoly_factor.h>+#include <flint/mpoly_types.h>++-- fmpq_mpoly_factor_t ---------------------------------------------------------++data FmpqMPolyFactor =+ FmpqMPolyFactor {-# UNPACK #-} !(ForeignPtr CFmpqMPolyFactor)+data CFmpqMPolyFactor =+ CFmpqMPolyFactor (Ptr CFmpq) (Ptr CFmpqMPoly)+ (Ptr CFmpz) CLong CLong++instance Storable CFmpqMPolyFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpq_mpoly_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpq_mpoly_factor_t}+ peek ptr = CFmpqMPolyFactor+ <$> #{peek fmpq_mpoly_factor_struct, constant } ptr+ <*> #{peek fmpq_mpoly_factor_struct, poly } ptr+ <*> #{peek fmpq_mpoly_factor_struct, exp } ptr+ <*> #{peek fmpq_mpoly_factor_struct, num } ptr+ <*> #{peek fmpq_mpoly_factor_struct, alloc } ptr+ poke = error "CFmpqMPolyFactor.poke: Not defined"++newFmpqMPolyFactor ctx@(FmpqMPolyCtx pctx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpqMPolyCtx ctx $ \ctx -> do+ fmpq_mpoly_factor_init x ctx+ addForeignPtrFinalizerEnv p_fmpq_mpoly_factor_clear x pctx+ return $ FmpqMPolyFactor x++withFmpqMPolyFactor (FmpqMPolyFactor p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpqMPolyFactor p,)++-- Memory management -----------------------------------------------------------++-- | /fmpq_mpoly_factor_init/ /f/ /ctx/ +--+-- Initialise /f/.+foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_init"+ fmpq_mpoly_factor_init :: Ptr CFmpqMPolyFactor -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_factor_clear/ /f/ /ctx/ +--+-- Clear /f/.+foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_clear"+ fmpq_mpoly_factor_clear :: Ptr CFmpqMPolyFactor -> Ptr CFmpqMPolyCtx -> IO ()++foreign import ccall "fmpq_mpoly_factor.h &fmpq_mpoly_factor_clear"+ p_fmpq_mpoly_factor_clear :: FunPtr (Ptr CFmpqMPolyFactor -> Ptr CFmpqMPolyCtx -> IO ())++-- Basic manipulation ----------------------------------------------------------++-- -- | /fmpq_mpoly_factor_swap/ /f/ /g/ /ctx/ +-- --+-- -- Efficiently swap /f/ and /g/.+-- foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_swap"+-- fmpq_mpoly_factor_swap :: Ptr CFmpqMPolyFactor -> Ptr CFmpqMPolyFactor -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_factor_length/ /f/ /ctx/ +--+-- Return the length of the product in /f/.+foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_length"+ fmpq_mpoly_factor_length :: Ptr CFmpqMPolyFactor -> Ptr CFmpqMPolyCtx -> IO CLong++-- | /fmpq_mpoly_factor_get_constant_fmpq/ /c/ /f/ /ctx/ +--+-- Set /c/ to the constant of /f/.+foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_get_constant_fmpq"+ fmpq_mpoly_factor_get_constant_fmpq :: Ptr CFmpq -> Ptr CFmpqMPolyFactor -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_factor_get_base/ /B/ /f/ /i/ /ctx/ +foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_get_base"+ fmpq_mpoly_factor_get_base :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyFactor -> CLong -> Ptr CFmpqMPolyCtx -> IO ()+-- | /fmpq_mpoly_factor_swap_base/ /B/ /f/ /i/ /ctx/ +--+-- Set (resp. swap) /B/ to (resp. with) the base of the term of index /i/+-- in /A/.+foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_swap_base"+ fmpq_mpoly_factor_swap_base :: Ptr CFmpqMPoly -> Ptr CFmpqMPolyFactor -> CLong -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_factor_get_exp_si/ /f/ /i/ /ctx/ +--+-- Return the exponent of the term of index /i/ in /A/. It is assumed to+-- fit an @slong@.+foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_get_exp_si"+ fmpq_mpoly_factor_get_exp_si :: Ptr CFmpqMPolyFactor -> CLong -> Ptr CFmpqMPolyCtx -> IO CLong++-- | /fmpq_mpoly_factor_sort/ /f/ /ctx/ +--+-- Sort the product of /f/ first by exponent and then by base.+foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_sort"+ fmpq_mpoly_factor_sort :: Ptr CFmpqMPolyFactor -> Ptr CFmpqMPolyCtx -> IO ()++-- | /fmpq_mpoly_factor_make_monic/ /f/ /ctx/ +foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_make_monic"+ fmpq_mpoly_factor_make_monic :: Ptr CFmpqMPolyFactor -> Ptr CFmpqMPolyCtx -> IO CInt+-- | /fmpq_mpoly_factor_make_integral/ /f/ /ctx/ +--+-- Make the bases in /f/ monic (resp. integral and primitive with positive+-- leading coefficient). Return \(1\) for success, \(0\) for failure.+foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_make_integral"+ fmpq_mpoly_factor_make_integral :: Ptr CFmpqMPolyFactor -> Ptr CFmpqMPolyCtx -> IO CInt++-- Factorisation ---------------------------------------------------------------+++++-- | /fmpq_mpoly_factor_squarefree/ /f/ /A/ /ctx/ +--+-- Set /f/ to a factorization of /A/ where the bases are primitive and+-- pairwise relatively prime. If the product of all irreducible factors+-- with a given exponent is desired, it is recommended to call+-- @fmpq_mpoly_factor_sort@ and then multiply the bases with the desired+-- exponent.+foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor_squarefree"+ fmpq_mpoly_factor_squarefree :: Ptr CFmpqMPolyFactor -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt++-- | /fmpq_mpoly_factor/ /f/ /A/ /ctx/ +--+-- Set /f/ to a factorization of /A/ where the bases are irreducible.+foreign import ccall "fmpq_mpoly_factor.h fmpq_mpoly_factor"+ fmpq_mpoly_factor :: Ptr CFmpqMPolyFactor -> Ptr CFmpqMPoly -> Ptr CFmpqMPolyCtx -> IO CInt+
+ src/Data/Number/Flint/Fmpq/Mat.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpq.Mat (+ module Data.Number.Flint.Fmpq.Mat.FFI,+) where++import Data.Number.Flint.Fmpq.Mat.FFI
+ src/Data/Number/Flint/Fmpq/Mat/FFI.hsc view
@@ -0,0 +1,876 @@+{-|+module : Data.Number.Flint.Fmpq.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpq.Mat.FFI (+ -- * Matrices over the rational numbers+ FmpqMat (..)+ , CFmpqMat (..)+ , newFmpqMat+ , withFmpqMat+ , withNewFmpqMat+ -- * Memory management+ , fmpq_mat_init+ , fmpq_mat_init_set+ , fmpq_mat_clear+ , fmpq_mat_swap+ , fmpq_mat_swap_entrywise+ -- * Entry access+ , fmpq_mat_entry+ , fmpq_mat_entry_num+ , fmpq_mat_entry_den+ , fmpq_mat_set_entry+ , fmpq_mat_get_entry+ , fmpq_mat_nrows+ , fmpq_mat_ncols+ -- * Basic assignment+ , fmpq_mat_set+ , fmpq_mat_zero+ , fmpq_mat_one+ , fmpq_mat_transpose+ , fmpq_mat_swap_rows+ , fmpq_mat_swap_cols+ , fmpq_mat_invert_rows+ , fmpq_mat_invert_cols+ -- * Addition, scalar multiplication+ , fmpq_mat_add+ , fmpq_mat_sub+ , fmpq_mat_neg+ , fmpq_mat_scalar_mul_fmpq+ , fmpq_mat_scalar_mul_fmpz+ , fmpq_mat_scalar_div_fmpz+ -- * Input and output+ , fmpq_mat_get_str+ , fmpq_mat_fprint+ , fmpq_mat_print+ -- * Random matrix generation+ , fmpq_mat_randbits+ , fmpq_mat_randtest+ -- * Window+ , fmpq_mat_window_init+ , fmpq_mat_window_clear+ -- * Concatenate+ , fmpq_mat_concat_vertical+ , fmpq_mat_concat_horizontal+ -- * Special matrices+ , fmpq_mat_hilbert_matrix+ -- * Basic comparison and properties+ , fmpq_mat_equal+ , fmpq_mat_is_integral+ , fmpq_mat_is_zero+ , fmpq_mat_is_one+ , fmpq_mat_is_empty+ , fmpq_mat_is_square+ -- * Integer matrix conversion+ , fmpq_mat_get_fmpz_mat+ , fmpq_mat_get_fmpz_mat_entrywise+ , fmpq_mat_get_fmpz_mat_matwise+ , fmpq_mat_get_fmpz_mat_rowwise+ , fmpq_mat_get_fmpz_mat_rowwise_2+ , fmpq_mat_get_fmpz_mat_colwise+ , fmpq_mat_set_fmpz_mat+ , fmpq_mat_set_fmpz_mat_div_fmpz+ -- * Modular reduction and rational reconstruction+ , fmpq_mat_get_fmpz_mat_mod_fmpz+ , fmpq_mat_set_fmpz_mat_mod_fmpz+ -- * Matrix multiplication+ , fmpq_mat_mul_direct+ , fmpq_mat_mul_cleared+ , fmpq_mat_mul+ , fmpq_mat_mul_fmpz_mat+ , fmpq_mat_mul_r_fmpz_mat+ , fmpq_mat_mul_fmpq_vec+ , fmpq_mat_fmpq_vec_mul+ -- * Kronecker product+ , fmpq_mat_kronecker_product+ -- * Trace+ , fmpq_mat_trace+ -- * Determinant+ , fmpq_mat_det+ -- * Nonsingular solving+ , fmpq_mat_solve_fraction_free+ , fmpq_mat_solve_dixon+ , fmpq_mat_solve_multi_mod+ , fmpq_mat_solve+ , fmpq_mat_solve_fmpz_mat_fraction_free+ , fmpq_mat_solve_fmpz_mat_dixon+ , fmpq_mat_solve_fmpz_mat_multi_mod+ , fmpq_mat_solve_fmpz_mat+ , fmpq_mat_can_solve_multi_mod+ , fmpq_mat_can_solve_fraction_free+ , fmpq_mat_can_solve_fmpz_mat_dixon+ , fmpq_mat_can_solve_dixon+ , fmpq_mat_can_solve+ -- * Inverse+ , fmpq_mat_inv+ -- * Echelon form+ , fmpq_mat_pivot+ , fmpq_mat_rref_classical+ , fmpq_mat_rref_fraction_free+ , fmpq_mat_rref+ -- * Gram-Schmidt Orthogonalisation+ , fmpq_mat_gso+ -- * Transforms+ , fmpq_mat_similarity+ -- * Characteristic polynomial+ , _fmpq_mat_charpoly+ , fmpq_mat_charpoly+ -- * Minimal polynomial+ , _fmpq_mat_minpoly+ , fmpq_mat_minpoly+) where++-- Matrices over the rational numbers ------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fmpq.Poly++#include <flint/flint.h>+#include <flint/fmpq.h>+#include <flint/fmpq_mat.h>++-- fmpq_mat_t ------------------------------------------------------------------++data FmpqMat = FmpqMat {-# UNPACK #-} !(ForeignPtr CFmpqMat)+data CFmpqMat = CFmpqMat (Ptr CFmpq) CLong CLong (Ptr (Ptr CFmpq))++instance Storable CFmpqMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpq_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpq_mat_t}+ peek ptr = CFmpqMat+ <$> #{peek fmpq_mat_struct, entries} ptr+ <*> #{peek fmpq_mat_struct, r } ptr+ <*> #{peek fmpq_mat_struct, c } ptr+ <*> #{peek fmpq_mat_struct, rows } ptr+ poke = error "CFmpqMat.poke: Not defined."++newFmpqMat rows cols = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> fmpq_mat_init x rows cols+ addForeignPtrFinalizer p_fmpq_mat_clear x+ return $ FmpqMat x++{-# INLINE withFmpqMat #-}+withFmpqMat (FmpqMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FmpqMat x,)++{-# INLINE withNewFmpqMat #-}+withNewFmpqMat rows cols f = do+ x <- newFmpqMat rows cols+ withFmpqMat x f+ +-- Memory management -----------------------------------------------------------++-- | /fmpq_mat_init/ /mat/ /rows/ /cols/ +-- +-- Initialises a matrix with the given number of rows and columns for use.+foreign import ccall "fmpq_mat.h fmpq_mat_init"+ fmpq_mat_init :: Ptr CFmpqMat -> CLong -> CLong -> IO ()++-- | /fmpq_mat_init_set/ /mat1/ /mat2/ +-- +-- Initialises @mat1@ and sets it equal to @mat2@.+foreign import ccall "fmpq_mat.h fmpq_mat_init_set"+ fmpq_mat_init_set :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_clear/ /mat/ +-- +-- Frees all memory associated with the matrix. The matrix must be+-- reinitialised if it is to be used again.+foreign import ccall "fmpq_mat.h fmpq_mat_clear"+ fmpq_mat_clear :: Ptr CFmpqMat -> IO ()++foreign import ccall "fmpq_mat.h &fmpq_mat_clear"+ p_fmpq_mat_clear :: FunPtr (Ptr CFmpqMat -> IO ())++-- | /fmpq_mat_swap/ /mat1/ /mat2/ +-- +-- Swaps two matrices. The dimensions of @mat1@ and @mat2@ are allowed to+-- be different.+foreign import ccall "fmpq_mat.h fmpq_mat_swap"+ fmpq_mat_swap :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_swap_entrywise/ /mat1/ /mat2/ +-- +-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "fmpq_mat.h fmpq_mat_swap_entrywise"+ fmpq_mat_swap_entrywise :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- Entry access ----------------------------------------------------------------++-- | /fmpq_mat_entry/ /mat/ /i/ /j/ +-- +-- Gives a reference to the entry at row @i@ and column @j@. The reference+-- can be passed as an input or output variable to any @fmpq@ function for+-- direct manipulation of the matrix element. No bounds checking is+-- performed.+fmpq_mat_entry :: Ptr CFmpqMat -> CLong -> CLong -> IO (Ptr CFmpq)+fmpq_mat_entry mat i j = do+ CFmpqMat entries r c rows <- peek mat+ return $ entries `advancePtr` (fromIntegral (i*c + j))++fmpq_mat_set_entry :: Ptr CFmpqMat -> CLong -> CLong -> Ptr CFmpq -> IO ()+fmpq_mat_set_entry mat i j x = do+ p <- fmpq_mat_entry mat i j+ fmpq_set p x+ +fmpq_mat_get_entry :: Ptr CFmpq -> Ptr CFmpqMat -> CLong -> CLong -> IO ()+fmpq_mat_get_entry x mat i j = do+ p <- fmpq_mat_entry mat i j+ fmpq_set x p++-- | /fmpq_mat_entry_num/ /mat/ /i/ /j/ +-- +-- Gives a reference to the numerator of the entry at row @i@ and column+-- @j@. The reference can be passed as an input or output variable to any+-- @fmpz@ function for direct manipulation of the matrix element. No bounds+-- checking is performed.+foreign import ccall "fmpq_mat.h fmpq_mat_entry_num"+ fmpq_mat_entry_num :: Ptr CFmpqMat -> CLong -> CLong -> IO (Ptr CFmpz)++-- | /fmpq_mat_entry_den/ /mat/ /i/ /j/ +-- +-- Gives a reference to the denominator of the entry at row @i@ and column+-- @j@. The reference can be passed as an input or output variable to any+-- @fmpz@ function for direct manipulation of the matrix element. No bounds+-- checking is performed.+foreign import ccall "fmpq_mat.h fmpq_mat_entry_den"+ fmpq_mat_entry_den :: Ptr CFmpqMat -> CLong -> CLong -> IO (Ptr CFmpz)++-- | /fmpq_mat_nrows/ /mat/ +-- +-- Return the number of rows of the matrix @mat@.+foreign import ccall "fmpq_mat.h fmpq_mat_nrows"+ fmpq_mat_nrows :: Ptr CFmpqMat -> IO CLong++-- | /fmpq_mat_ncols/ /mat/ +-- +-- Return the number of columns of the matrix @mat@.+foreign import ccall "fmpq_mat.h fmpq_mat_ncols"+ fmpq_mat_ncols :: Ptr CFmpqMat -> IO CLong++-- Basic assignment ------------------------------------------------------------++-- | /fmpq_mat_set/ /dest/ /src/ +-- +-- Sets the entries in @dest@ to the same values as in @src@, assuming the+-- two matrices have the same dimensions.+foreign import ccall "fmpq_mat.h fmpq_mat_set"+ fmpq_mat_set :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_zero/ /mat/ +-- +-- Sets @mat@ to the zero matrix.+foreign import ccall "fmpq_mat.h fmpq_mat_zero"+ fmpq_mat_zero :: Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_one/ /mat/ +-- +-- Let \(m\) be the minimum of the number of rows and columns in the matrix+-- @mat@. This function sets the first \(m \times m\) block to the identity+-- matrix, and the remaining block to zero.+foreign import ccall "fmpq_mat.h fmpq_mat_one"+ fmpq_mat_one :: Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_transpose/ /rop/ /op/ +-- +-- Sets the matrix @rop@ to the transpose of the matrix @op@, assuming that+-- their dimensions are compatible.+foreign import ccall "fmpq_mat.h fmpq_mat_transpose"+ fmpq_mat_transpose :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_swap_rows/ /mat/ /perm/ /r/ /s/ +-- +-- Swaps rows @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the rows will also be applied to @perm@.+foreign import ccall "fmpq_mat.h fmpq_mat_swap_rows"+ fmpq_mat_swap_rows :: Ptr CFmpqMat -> Ptr CLong -> CLong -> CLong -> IO ()++-- | /fmpq_mat_swap_cols/ /mat/ /perm/ /r/ /s/ +-- +-- Swaps columns @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the columns will also be applied to @perm@.+foreign import ccall "fmpq_mat.h fmpq_mat_swap_cols"+ fmpq_mat_swap_cols :: Ptr CFmpqMat -> Ptr CLong -> CLong -> CLong -> IO ()++-- | /fmpq_mat_invert_rows/ /mat/ /perm/ +-- +-- Swaps rows @i@ and @r - i@ of @mat@ for @0 \<= i \< r\/2@, where @r@ is+-- the number of rows of @mat@. If @perm@ is non-@NULL@, the permutation of+-- the rows will also be applied to @perm@.+foreign import ccall "fmpq_mat.h fmpq_mat_invert_rows"+ fmpq_mat_invert_rows :: Ptr CFmpqMat -> Ptr CLong -> IO ()++-- | /fmpq_mat_invert_cols/ /mat/ /perm/ +-- +-- Swaps columns @i@ and @c - i@ of @mat@ for @0 \<= i \< c\/2@, where @c@+-- is the number of columns of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the columns will also be applied to @perm@.+foreign import ccall "fmpq_mat.h fmpq_mat_invert_cols"+ fmpq_mat_invert_cols :: Ptr CFmpqMat -> Ptr CLong -> IO ()++-- Addition, scalar multiplication ---------------------------------------------++-- | /fmpq_mat_add/ /mat/ /mat1/ /mat2/ +-- +-- Sets @mat@ to the sum of @mat1@ and @mat2@, assuming that all three+-- matrices have the same dimensions.+foreign import ccall "fmpq_mat.h fmpq_mat_add"+ fmpq_mat_add :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_sub/ /mat/ /mat1/ /mat2/ +-- +-- Sets @mat@ to the difference of @mat1@ and @mat2@, assuming that all+-- three matrices have the same dimensions.+foreign import ccall "fmpq_mat.h fmpq_mat_sub"+ fmpq_mat_sub :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_neg/ /rop/ /op/ +-- +-- Sets @rop@ to the negative of @op@, assuming that the two matrices have+-- the same dimensions.+foreign import ccall "fmpq_mat.h fmpq_mat_neg"+ fmpq_mat_neg :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_scalar_mul_fmpq/ /rop/ /op/ /x/ +-- +-- Sets @rop@ to @op@ multiplied by the rational \(x\), assuming that the+-- two matrices have the same dimensions.+-- +-- Note that the rational @x@ may not be aliased with any part of the+-- entries of @rop@.+foreign import ccall "fmpq_mat.h fmpq_mat_scalar_mul_fmpq"+ fmpq_mat_scalar_mul_fmpq :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpq -> IO ()++-- | /fmpq_mat_scalar_mul_fmpz/ /rop/ /op/ /x/ +-- +-- Sets @rop@ to @op@ multiplied by the integer \(x\), assuming that the+-- two matrices have the same dimensions.+-- +-- Note that the integer \(x\) may not be aliased with any part of the+-- entries of @rop@.+foreign import ccall "fmpq_mat.h fmpq_mat_scalar_mul_fmpz"+ fmpq_mat_scalar_mul_fmpz :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpz -> IO ()++-- | /fmpq_mat_scalar_div_fmpz/ /rop/ /op/ /x/ +-- +-- Sets @rop@ to @op@ divided by the integer \(x\), assuming that the two+-- matrices have the same dimensions and that \(x\) is non-zero.+-- +-- Note that the integer \(x\) may not be aliased with any part of the+-- entries of @rop@.+foreign import ccall "fmpq_mat.h fmpq_mat_scalar_div_fmpz"+ fmpq_mat_scalar_div_fmpz :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpz -> IO ()++-- Input and output ------------------------------------------------------------++-- | /fmpq_mat_get_str/ /mat/+--+-- Returns a string representation.+foreign import ccall "fmpq_mat.h fmpq_mat_get_str"+ fmpq_mat_get_str :: Ptr CFmpqMat -> IO CString++-- | /fmpq_mat_fprint/ /file/ /mat/ +-- +-- Prints the matrix @mat@ to the stream @file@.+foreign import ccall "fmpq_mat.h fmpq_mat_fprint"+ fmpq_mat_fprint :: Ptr CFile -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_print/ /mat/ +-- +-- Prints the matrix @mat@ to standard output.+fmpq_mat_print :: Ptr CFmpqMat -> IO CInt+fmpq_mat_print mat = printCStr (fmpq_mat_get_str) mat++-- Random matrix generation ----------------------------------------------------++-- | /fmpq_mat_randbits/ /mat/ /state/ /bits/ +-- +-- This is equivalent to applying @fmpq_randbits@ to all entries in the+-- matrix.+foreign import ccall "fmpq_mat.h fmpq_mat_randbits"+ fmpq_mat_randbits :: Ptr CFmpqMat -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /fmpq_mat_randtest/ /mat/ /state/ /bits/ +-- +-- This is equivalent to applying @fmpq_randtest@ to all entries in the+-- matrix.+foreign import ccall "fmpq_mat.h fmpq_mat_randtest"+ fmpq_mat_randtest :: Ptr CFmpqMat -> Ptr CFRandState -> CFBitCnt -> IO ()++-- Window ----------------------------------------------------------------------++-- | /fmpq_mat_window_init/ /window/ /mat/ /r1/ /c1/ /r2/ /c2/ +-- +-- Initializes the matrix @window@ to be an @r2 - r1@ by @c2 - c1@+-- submatrix of @mat@ whose @(0,0)@ entry is the @(r1, c1)@ entry of @mat@.+-- The memory for the elements of @window@ is shared with @mat@.+foreign import ccall "fmpq_mat.h fmpq_mat_window_init"+ fmpq_mat_window_init :: Ptr CFmpqMat -> Ptr CFmpqMat -> CLong -> CLong -> CLong -> CLong -> IO ()++-- | /fmpq_mat_window_clear/ /window/ +-- +-- Clears the matrix @window@ and releases any memory that it uses. Note+-- that the memory to the underlying matrix that @window@ points to is not+-- freed.+foreign import ccall "fmpq_mat.h fmpq_mat_window_clear"+ fmpq_mat_window_clear :: Ptr CFmpqMat -> IO ()++-- Concatenate -----------------------------------------------------------------++-- | /fmpq_mat_concat_vertical/ /res/ /mat1/ /mat2/ +-- +-- Sets @res@ to vertical concatenation of (@mat1@, @mat2@) in that order.+-- Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ : \(k \times n\),+-- @res@ : \((m + k) \times n\).+foreign import ccall "fmpq_mat.h fmpq_mat_concat_vertical"+ fmpq_mat_concat_vertical :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_concat_horizontal/ /res/ /mat1/ /mat2/ +-- +-- Sets @res@ to horizontal concatenation of (@mat1@, @mat2@) in that+-- order. Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ :+-- \(m \times k\), @res@ : \(m \times (n + k)\).+foreign import ccall "fmpq_mat.h fmpq_mat_concat_horizontal"+ fmpq_mat_concat_horizontal :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- Special matrices ------------------------------------------------------------++-- | /fmpq_mat_hilbert_matrix/ /mat/ +-- +-- Sets @mat@ to a Hilbert matrix of the given size. That is, the entry at+-- row \(i\) and column \(j\) is set to \(1/(i+j+1)\).+foreign import ccall "fmpq_mat.h fmpq_mat_hilbert_matrix"+ fmpq_mat_hilbert_matrix :: Ptr CFmpqMat -> IO ()++-- Basic comparison and properties ---------------------------------------------++-- | /fmpq_mat_equal/ /mat1/ /mat2/ +-- +-- Returns nonzero if @mat1@ and @mat2@ have the same shape and all their+-- entries agree, and returns zero otherwise. Assumes the entries in both+-- @mat1@ and @mat2@ are in canonical form.+foreign import ccall "fmpq_mat.h fmpq_mat_equal"+ fmpq_mat_equal :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt++-- | /fmpq_mat_is_integral/ /mat/ +-- +-- Returns nonzero if all entries in @mat@ are integer-valued, and returns+-- zero otherwise. Assumes that the entries in @mat@ are in canonical form.+foreign import ccall "fmpq_mat.h fmpq_mat_is_integral"+ fmpq_mat_is_integral :: Ptr CFmpqMat -> IO CInt++-- | /fmpq_mat_is_zero/ /mat/ +-- +-- Returns nonzero if all entries in @mat@ are zero, and returns zero+-- otherwise.+foreign import ccall "fmpq_mat.h fmpq_mat_is_zero"+ fmpq_mat_is_zero :: Ptr CFmpqMat -> IO CInt++-- | /fmpq_mat_is_one/ /mat/ +-- +-- Returns nonzero if @mat@ ones along the diagonal and zeros elsewhere,+-- and returns zero otherwise.+foreign import ccall "fmpq_mat.h fmpq_mat_is_one"+ fmpq_mat_is_one :: Ptr CFmpqMat -> IO CInt++-- | /fmpq_mat_is_empty/ /mat/ +-- +-- Returns a non-zero value if the number of rows or the number of columns+-- in @mat@ is zero, and otherwise returns zero.+foreign import ccall "fmpq_mat.h fmpq_mat_is_empty"+ fmpq_mat_is_empty :: Ptr CFmpqMat -> IO CInt++-- | /fmpq_mat_is_square/ /mat/ +-- +-- Returns a non-zero value if the number of rows is equal to the number of+-- columns in @mat@, and otherwise returns zero.+foreign import ccall "fmpq_mat.h fmpq_mat_is_square"+ fmpq_mat_is_square :: Ptr CFmpqMat -> IO CInt++-- Integer matrix conversion ---------------------------------------------------++-- | /fmpq_mat_get_fmpz_mat/ /dest/ /mat/ +-- +-- Sets @dest@ to @mat@ and returns nonzero if all entries in @mat@ are+-- integer-valued. If not all entries in @mat@ are integer-valued, sets+-- @dest@ to an undefined matrix and returns zero. Assumes that the entries+-- in @mat@ are in canonical form.+foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat"+ fmpq_mat_get_fmpz_mat :: Ptr CFmpzMat -> Ptr CFmpqMat -> IO CInt++-- | /fmpq_mat_get_fmpz_mat_entrywise/ /num/ /den/ /mat/ +-- +-- Sets the integer matrices @num@ and @den@ respectively to the numerators+-- and denominators of the entries in @mat@.+foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_entrywise"+ fmpq_mat_get_fmpz_mat_entrywise :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_get_fmpz_mat_matwise/ /num/ /den/ /mat/ +-- +-- Converts all entries in @mat@ to a common denominator, storing the+-- rescaled numerators in @num@ and the denominator in @den@. The+-- denominator will be minimal if the entries in @mat@ are in canonical+-- form.+foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_matwise"+ fmpq_mat_get_fmpz_mat_matwise :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_get_fmpz_mat_rowwise/ /num/ /den/ /mat/ +-- +-- Clears denominators in @mat@ row by row. The rescaled numerators are+-- written to @num@, and the denominator of row @i@ is written to position+-- @i@ in @den@ which can be a preinitialised @fmpz@ vector. Alternatively,+-- @NULL@ can be passed as the @den@ variable, in which case the+-- denominators will not be stored.+foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_rowwise"+ fmpq_mat_get_fmpz_mat_rowwise :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_get_fmpz_mat_rowwise_2/ /num/ /num2/ /den/ /mat/ /mat2/ +-- +-- Clears denominators row by row of both @mat@ and @mat2@, writing the+-- respective numerators to @num@ and @num2@. This is equivalent to+-- concatenating @mat@ and @mat2@ horizontally, calling+-- @fmpq_mat_get_fmpz_mat_rowwise@, and extracting the two submatrices in+-- the result.+foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_rowwise_2"+ fmpq_mat_get_fmpz_mat_rowwise_2 :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_get_fmpz_mat_colwise/ /num/ /den/ /mat/ +-- +-- Clears denominators in @mat@ column by column. The rescaled numerators+-- are written to @num@, and the denominator of column @i@ is written to+-- position @i@ in @den@ which can be a preinitialised @fmpz@ vector.+-- Alternatively, @NULL@ can be passed as the @den@ variable, in which case+-- the denominators will not be stored.+foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_colwise"+ fmpq_mat_get_fmpz_mat_colwise :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_set_fmpz_mat/ /dest/ /src/ +-- +-- Sets @dest@ to @src@.+foreign import ccall "fmpq_mat.h fmpq_mat_set_fmpz_mat"+ fmpq_mat_set_fmpz_mat :: Ptr CFmpqMat -> Ptr CFmpzMat -> IO ()++-- | /fmpq_mat_set_fmpz_mat_div_fmpz/ /mat/ /num/ /den/ +-- +-- Sets @mat@ to the integer matrix @num@ divided by the common denominator+-- @den@.+foreign import ccall "fmpq_mat.h fmpq_mat_set_fmpz_mat_div_fmpz"+ fmpq_mat_set_fmpz_mat_div_fmpz :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpz -> IO ()++-- Modular reduction and rational reconstruction -------------------------------++-- | /fmpq_mat_get_fmpz_mat_mod_fmpz/ /dest/ /mat/ /mod/ +-- +-- Sets each entry in @dest@ to the corresponding entry in @mat@, reduced+-- modulo @mod@.+foreign import ccall "fmpq_mat.h fmpq_mat_get_fmpz_mat_mod_fmpz"+ fmpq_mat_get_fmpz_mat_mod_fmpz :: Ptr CFmpzMat -> Ptr CFmpqMat -> Ptr CFmpz -> IO ()++-- | /fmpq_mat_set_fmpz_mat_mod_fmpz/ /X/ /Xmod/ /mod/ +-- +-- Set @X@ to the entrywise rational reconstruction integer matrix @Xmod@+-- modulo @mod@, and returns nonzero if the reconstruction is successful.+-- If rational reconstruction fails for any element, returns zero and sets+-- the entries in @X@ to undefined values.+foreign import ccall "fmpq_mat.h fmpq_mat_set_fmpz_mat_mod_fmpz"+ fmpq_mat_set_fmpz_mat_mod_fmpz :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpz -> IO CInt++-- Matrix multiplication -------------------------------------------------------++-- | /fmpq_mat_mul_direct/ /C/ /A/ /B/ +-- +-- Sets @C@ to the matrix product @AB@, computed naively using rational+-- arithmetic. This is typically very slow and should only be used in+-- circumstances where clearing denominators would consume too much memory.+foreign import ccall "fmpq_mat.h fmpq_mat_mul_direct"+ fmpq_mat_mul_direct :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_mul_cleared/ /C/ /A/ /B/ +-- +-- Sets @C@ to the matrix product @AB@, computed by clearing denominators+-- and multiplying over the integers.+foreign import ccall "fmpq_mat.h fmpq_mat_mul_cleared"+ fmpq_mat_mul_cleared :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_mul/ /C/ /A/ /B/ +-- +-- Sets @C@ to the matrix product @AB@. This simply calls+-- @fmpq_mat_mul_cleared@.+foreign import ccall "fmpq_mat.h fmpq_mat_mul"+ fmpq_mat_mul :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_mul_fmpz_mat/ /C/ /A/ /B/ +-- +-- Sets @C@ to the matrix product @AB@, with @B@ an integer matrix. This+-- function works efficiently by clearing denominators of @A@.+foreign import ccall "fmpq_mat.h fmpq_mat_mul_fmpz_mat"+ fmpq_mat_mul_fmpz_mat :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpzMat -> IO ()++-- | /fmpq_mat_mul_r_fmpz_mat/ /C/ /A/ /B/ +-- +-- Sets @C@ to the matrix product @AB@, with @A@ an integer matrix. This+-- function works efficiently by clearing denominators of @B@.+foreign import ccall "fmpq_mat.h fmpq_mat_mul_r_fmpz_mat"+ fmpq_mat_mul_r_fmpz_mat :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_mul_fmpq_vec/ /c/ /A/ /b/ /blen/ +-- +-- Compute a matrix-vector product of @A@ and @(b, blen)@ and store the+-- result in @c@. The vector @(b, blen)@ is either truncated or+-- zero-extended to the number of columns of @A@. The number entries+-- written to @c@ is always equal to the number of rows of @A@.+foreign import ccall "fmpq_mat.h fmpq_mat_mul_fmpq_vec"+ fmpq_mat_mul_fmpq_vec :: Ptr CFmpq -> Ptr CFmpqMat -> Ptr CFmpq -> CLong -> IO ()++-- | /fmpq_mat_fmpq_vec_mul/ /c/ /a/ /alen/ /B/ +-- +-- Compute a vector-matrix product of @(a, alen)@ and @B@ and and store the+-- result in @c@. The vector @(a, alen)@ is either truncated or+-- zero-extended to the number of rows of @B@. The number entries written+-- to @c@ is always equal to the number of columns of @B@.+foreign import ccall "fmpq_mat.h fmpq_mat_fmpq_vec_mul"+ fmpq_mat_fmpq_vec_mul :: Ptr CFmpq -> Ptr CFmpq -> CLong -> Ptr CFmpqMat -> IO ()++-- Kronecker product -----------------------------------------------------------++-- | /fmpq_mat_kronecker_product/ /C/ /A/ /B/ +-- +-- Sets @C@ to the Kronecker product of @A@ and @B@.+foreign import ccall "fmpq_mat.h fmpq_mat_kronecker_product"+ fmpq_mat_kronecker_product :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- Trace -----------------------------------------------------------------------++-- | /fmpq_mat_trace/ /trace/ /mat/ +-- +-- Computes the trace of the matrix, i.e. the sum of the entries on the+-- main diagonal. The matrix is required to be square.+foreign import ccall "fmpq_mat.h fmpq_mat_trace"+ fmpq_mat_trace :: Ptr CFmpq -> Ptr CFmpqMat -> IO ()++-- Determinant -----------------------------------------------------------------++-- | /fmpq_mat_det/ /det/ /mat/ +-- +-- Sets @det@ to the determinant of @mat@. In the general case, the+-- determinant is computed by clearing denominators and computing a+-- determinant over the integers. Matrices of size 0, 1 or 2 are handled+-- directly.+foreign import ccall "fmpq_mat.h fmpq_mat_det"+ fmpq_mat_det :: Ptr CFmpq -> Ptr CFmpqMat -> IO ()++-- Nonsingular solving ---------------------------------------------------------++-- | /fmpq_mat_solve_fraction_free/ /X/ /A/ /B/ +foreign import ccall "fmpq_mat.h fmpq_mat_solve_fraction_free"+ fmpq_mat_solve_fraction_free :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt+-- | /fmpq_mat_solve_dixon/ /X/ /A/ /B/ +foreign import ccall "fmpq_mat.h fmpq_mat_solve_dixon"+ fmpq_mat_solve_dixon :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt+-- | /fmpq_mat_solve_multi_mod/ /X/ /A/ /B/ +foreign import ccall "fmpq_mat.h fmpq_mat_solve_multi_mod"+ fmpq_mat_solve_multi_mod :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt+-- | /fmpq_mat_solve/ /X/ /A/ /B/ +--+-- Solves @AX = B@ for nonsingular @A@. Returns nonzero if @A@ is+-- nonsingular or if the right hand side is empty, and zero otherwise.+-- +-- All algorithms clear denominators to obtain a rescaled system over the+-- integers. The /fraction_free/ algorithm uses FFLU solving over the+-- integers. The /dixon/ and /multi_mod/ algorithms use Dixon p-adic+-- lifting or multimodular solving, followed by rational reconstruction+-- with an adaptive stopping test. The /dixon/ and /multi_mod/ algorithms+-- are generally the best choice for large systems.+-- +-- The default method chooses an algorithm automatically.+foreign import ccall "fmpq_mat.h fmpq_mat_solve"+ fmpq_mat_solve :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt++-- | /fmpq_mat_solve_fmpz_mat_fraction_free/ /X/ /A/ /B/ +foreign import ccall "fmpq_mat.h fmpq_mat_solve_fmpz_mat_fraction_free"+ fmpq_mat_solve_fmpz_mat_fraction_free :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt+-- | /fmpq_mat_solve_fmpz_mat_dixon/ /X/ /A/ /B/ +foreign import ccall "fmpq_mat.h fmpq_mat_solve_fmpz_mat_dixon"+ fmpq_mat_solve_fmpz_mat_dixon :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt+-- | /fmpq_mat_solve_fmpz_mat_multi_mod/ /X/ /A/ /B/ +foreign import ccall "fmpq_mat.h fmpq_mat_solve_fmpz_mat_multi_mod"+ fmpq_mat_solve_fmpz_mat_multi_mod :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt+-- | /fmpq_mat_solve_fmpz_mat/ /X/ /A/ /B/ +--+-- Solves @AX = B@ for nonsingular @A@, where /A/ and /B/ are integer+-- matrices. Returns nonzero if @A@ is nonsingular or if the right hand+-- side is empty, and zero otherwise.+foreign import ccall "fmpq_mat.h fmpq_mat_solve_fmpz_mat"+ fmpq_mat_solve_fmpz_mat :: Ptr CFmpqMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- | /fmpq_mat_can_solve_multi_mod/ /X/ /A/ /B/ +--+-- Returns \(1\) if @AX = B@ has a solution and if so, sets @X@ to one such+-- solution. The matrices can have any shape but must have the same number+-- of rows.+foreign import ccall "fmpq_mat.h fmpq_mat_can_solve_multi_mod"+ fmpq_mat_can_solve_multi_mod :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt++-- | /fmpq_mat_can_solve_fraction_free/ /X/ /A/ /B/ +--+-- Returns \(1\) if @AX = B@ has a solution and if so, sets @X@ to one such+-- solution. The matrices can have any shape but must have the same number+-- of rows.+foreign import ccall "fmpq_mat.h fmpq_mat_can_solve_fraction_free"+ fmpq_mat_can_solve_fraction_free :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt++-- | /fmpq_mat_can_solve_fmpz_mat_dixon/ /X/ /A/ /B/+--+-- Returns if \(AX = B\) has a solution and if so, sets \(X\) to one+-- such solution. The matrices can have any shape but must have the+-- same number of rows. The input matrices must have integer entries+-- and cannot be an empty matrix.+foreign import ccall "fmpq_mat.h fmpq_mat_can_solve_fmpz_mat_dixon"+ fmpq_mat_can_solve_fmpz_mat_dixon :: Ptr CFmpqMat+ -> Ptr CFmpzMat+ -> Ptr CFmpzMat+ -> IO CInt+ +-- | /fmpq_mat_can_solve_dixon/ /X/ /A/ /B/+--+-- Returns \(1\) if \(AX = B\) has a solution and if so, sets \(X\) to one+-- such solution. The matrices can have any shape but must have the+-- same number of rows.+foreign import ccall "fmpq_mat.h fmpq_mat_can_solve_dixon"+ fmpq_mat_can_solve_dixon :: Ptr CFmpqMat+ -> Ptr CFmpqMat+ -> Ptr CFmpqMat+ -> IO CInt++-- | /fmpq_mat_can_solve/ /X/ /A/ /B/ +--+-- Returns \(1\) if @AX = B@ has a solution and if so, sets @X@ to one such+-- solution. The matrices can have any shape but must have the same number+-- of rows.+foreign import ccall "fmpq_mat.h fmpq_mat_can_solve"+ fmpq_mat_can_solve :: Ptr CFmpqMat -> Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt+ +-- Inverse ---------------------------------------------------------------------++-- | /fmpq_mat_inv/ /B/ /A/ +-- +-- Sets @B@ to the inverse matrix of @A@ and returns nonzero. Returns zero+-- if @A@ is singular. @A@ must be a square matrix.+foreign import ccall "fmpq_mat.h fmpq_mat_inv"+ fmpq_mat_inv :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO CInt++-- Echelon form ----------------------------------------------------------------++-- | /fmpq_mat_pivot/ /perm/ /mat/ /r/ /c/ +-- +-- Helper function for row reduction. Returns 1 if the entry of @mat@ at+-- row \(r\) and column \(c\) is nonzero. Otherwise searches for a nonzero+-- entry in the same column among rows \(r+1, r+2, \ldots\). If a nonzero+-- entry is found at row \(s\), swaps rows \(r\) and \(s\) and the+-- corresponding entries in @perm@ (unless @NULL@) and returns -1. If no+-- nonzero pivot entry is found, leaves the inputs unchanged and returns 0.+foreign import ccall "fmpq_mat.h fmpq_mat_pivot"+ fmpq_mat_pivot :: Ptr CLong -> Ptr CFmpqMat -> CLong -> CLong -> IO CInt++-- | /fmpq_mat_rref_classical/ /B/ /A/ +-- +-- Sets @B@ to the reduced row echelon form of @A@ and returns the rank.+-- Performs Gauss-Jordan elimination directly over the rational numbers.+-- This algorithm is usually inefficient and is mainly intended to be used+-- for testing purposes.+foreign import ccall "fmpq_mat.h fmpq_mat_rref_classical"+ fmpq_mat_rref_classical :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO CLong++-- | /fmpq_mat_rref_fraction_free/ /B/ /A/ +-- +-- Sets @B@ to the reduced row echelon form of @A@ and returns the rank.+-- Clears denominators and performs fraction-free Gauss-Jordan elimination+-- using @fmpz_mat@ functions.+foreign import ccall "fmpq_mat.h fmpq_mat_rref_fraction_free"+ fmpq_mat_rref_fraction_free :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO CLong++-- | /fmpq_mat_rref/ /B/ /A/ +-- +-- Sets @B@ to the reduced row echelon form of @A@ and returns the rank.+-- This function automatically chooses between the classical and+-- fraction-free algorithms depending on the size of the matrix.+foreign import ccall "fmpq_mat.h fmpq_mat_rref"+ fmpq_mat_rref :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO CLong++-- Gram-Schmidt Orthogonalisation ----------------------------------------------++-- | /fmpq_mat_gso/ /B/ /A/ +-- +-- Takes a subset of \(\mathbb{Q}^m\) \(S = \{a_1, a_2, \ldots ,a_n\}\) (as+-- the columns of a \(m \times n\) matrix @A@) and generates an orthogonal+-- set \(S' = \{b_1, b_2, \ldots ,b_n\}\) (as the columns of the+-- \(m \times n\) matrix @B@) that spans the same subspace of+-- \(\mathbb{Q}^m\) as \(S\).+foreign import ccall "fmpq_mat.h fmpq_mat_gso"+ fmpq_mat_gso :: Ptr CFmpqMat -> Ptr CFmpqMat -> IO ()++-- Transforms ------------------------------------------------------------------++-- | /fmpq_mat_similarity/ /A/ /r/ /d/ +-- +-- Applies a similarity transform to the \(n\times n\) matrix \(M\)+-- in-place.+-- +-- If \(P\) is the \(n\times n\) identity matrix the zero entries of whose+-- row \(r\) (0-indexed) have been replaced by \(d\), this transform is+-- equivalent to \(M = P^{-1}MP\).+-- +-- Similarity transforms preserve the determinant, characteristic+-- polynomial and minimal polynomial.+foreign import ccall "fmpq_mat.h fmpq_mat_similarity"+ fmpq_mat_similarity :: Ptr CFmpqMat -> CLong -> Ptr CFmpq -> IO ()++-- Characteristic polynomial ---------------------------------------------------++-- | /_fmpq_mat_charpoly/ /coeffs/ /den/ /mat/ +-- +-- Set @(coeffs, den)@ to the characteristic polynomial of the given+-- \(n\times n\) matrix.+foreign import ccall "fmpq_mat.h _fmpq_mat_charpoly"+ _fmpq_mat_charpoly :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpqMat -> IO ()++-- | /fmpq_mat_charpoly/ /pol/ /mat/ +-- +-- Set @pol@ to the characteristic polynomial of the given \(n\times n\)+-- matrix. If @mat@ is not square, an exception is raised.+foreign import ccall "fmpq_mat.h fmpq_mat_charpoly"+ fmpq_mat_charpoly :: Ptr CFmpqPoly -> Ptr CFmpqMat -> IO ()++-- Minimal polynomial ----------------------------------------------------------++-- | /_fmpq_mat_minpoly/ /coeffs/ /den/ /mat/ +-- +-- Set @(coeffs, den)@ to the minimal polynomial of the given \(n\times n\)+-- matrix and return the length of the polynomial.+foreign import ccall "fmpq_mat.h _fmpq_mat_minpoly"+ _fmpq_mat_minpoly :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpqMat -> IO CLong++-- | /fmpq_mat_minpoly/ /pol/ /mat/ +-- +-- Set @pol@ to the minimal polynomial of the given \(n\times n\) matrix.+-- If @mat@ is not square, an exception is raised.+foreign import ccall "fmpq_mat.h fmpq_mat_minpoly"+ fmpq_mat_minpoly :: Ptr CFmpqPoly -> Ptr CFmpqMat -> IO ()+
+ src/Data/Number/Flint/Fmpq/Mat/Instances.hs view
@@ -0,0 +1,73 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Fmpq.Mat.Instances where++import System.IO.Unsafe++import Foreign.C.String+import Foreign.Marshal.Alloc ( free )+import Foreign.Storable++import Data.Number.Flint.Fmpq.Mat++instance Show FmpqMat where+ show x = unsafePerformIO $ do+ (_, cs) <- withFmpqMat x fmpq_mat_get_str+ s <- peekCString cs+ free cs+ return s+ +instance Eq FmpqMat where+ (==) x y = unsafePerformIO $ do+ (_, (_, flag)) <- withFmpqMat x $ \x -> do+ withFmpqMat y $ \y -> do+ fmpq_mat_equal x y+ return $ flag == 1++instance Num FmpqMat where+ (+) = lift2 fmpq_mat_add+ (-) = lift2 fmpq_mat_sub+ (*) = lift2 fmpq_mat_mul+ negate = lift1 fmpq_mat_neg+ fromInteger = undefined+ signum = undefined+ abs = undefined++instance Fractional FmpqMat where+ recip x = unsafePerformIO $ do+ (_, (nx, mx)) <- withFmpqMat x $ \x -> do+ CFmpqMat _ nx mx _ <- peek x+ return (nx, mx)+ result <- newFmpqMat nx mx+ (_, (_, flag)) <- withFmpqMat x $ \x -> do+ withFmpqMat result $ \result -> do+ flag <- fmpq_mat_inv result x+ return flag+ return result+ fromRational = undefined++instance Semigroup FmpqMat where+ (<>) = (*)+ +lift1 f x = unsafePerformIO $ do+ (_, (nx, mx)) <- withFmpqMat x $ \x -> do+ CFmpqMat _ nx mx _ <- peek x+ return (nx, mx)+ result <- newFmpqMat nx mx+ withFmpqMat x $ \x -> do+ withFmpqMat result $ \result -> do+ f result x+ return result+ +lift2 f x y = unsafePerformIO $ do+ (_, (nx, mx)) <- withFmpqMat x $ \x -> do+ CFmpqMat _ nx mx _ <- peek x+ return (nx, mx)+ (_, (ny, my)) <- withFmpqMat y $ \y -> do + CFmpqMat _ ny my _ <- peek y+ return (ny, my)+ result <- newFmpqMat nx my+ withFmpqMat result $ \z -> do+ withFmpqMat x $ \x -> do+ withFmpqMat y $ \y -> do+ f z x y+ return result
+ src/Data/Number/Flint/Fmpq/Poly.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpq.Poly (+ module Data.Number.Flint.Fmpq.Poly.FFI+ ) where++import Data.Number.Flint.Fmpq.Poly.FFI
+ src/Data/Number/Flint/Fmpq/Poly/FFI.hsc view
@@ -0,0 +1,2484 @@+{-|+module : Data.Number.Flint.Fmpq.Poly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpq.Poly.FFI (+ -- * Univariate polynomials over the rational numbers+ FmpqPoly(..)+ , CFmpqPoly (..)+ , newFmpqPoly+ , withFmpqPoly+ , withNewFmpqPoly+ -- * Memory management+ , fmpq_poly_init+ , fmpq_poly_init2+ , fmpq_poly_realloc+ , fmpq_poly_fit_length+ , _fmpq_poly_set_length+ , fmpq_poly_clear+ , _fmpq_poly_normalise+ , _fmpq_poly_canonicalise+ , fmpq_poly_canonicalise+ , _fmpq_poly_is_canonical+ , fmpq_poly_is_canonical+ -- * Polynomial parameters+ , fmpq_poly_degree+ , fmpq_poly_length+ -- * Accessing the numerator and denominator+ , fmpq_poly_numref+ , fmpq_poly_denref+ , fmpq_poly_get_numerator+ , fmpq_poly_get_denominator+ -- * Random testing+ , fmpq_poly_randtest+ , fmpq_poly_randtest_unsigned+ , fmpq_poly_randtest_not_zero+ -- * Assignment, swap, negation+ , fmpq_poly_set+ , fmpq_poly_set_si+ , fmpq_poly_set_ui+ , fmpq_poly_set_fmpz+ , fmpq_poly_set_fmpq+ -- , fmpq_poly_set_mpz -- deprecated+ -- , fmpq_poly_set_mpq -- deprecated+ , fmpq_poly_set_fmpz_poly+ , fmpq_poly_set_nmod_poly+ , fmpq_poly_get_nmod_poly+ , fmpq_poly_get_nmod_poly_den+ -- , _fmpq_poly_set_array_mpq -- deprecated+ -- , fmpq_poly_set_array_mpq -- deprecated+ , fmpq_poly_zero+ , fmpq_poly_one+ , fmpq_poly_neg+ , fmpq_poly_inv+ , fmpq_poly_swap+ , fmpq_poly_truncate+ , fmpq_poly_set_trunc+ , fmpq_poly_get_slice+ , fmpq_poly_reverse+ -- * Getting and setting coefficients+ , fmpq_poly_get_coeff_fmpz+ , fmpq_poly_get_coeff_fmpq+ -- , fmpq_poly_get_coeff_mpq+ , fmpq_poly_set_coeff_si+ , fmpq_poly_set_coeff_ui+ , fmpq_poly_set_coeff_fmpz+ , fmpq_poly_set_coeff_fmpq+ -- , fmpq_poly_set_coeff_mpz -- deprecated+ -- , fmpq_poly_set_coeff_mpq -- deprecated+ -- * Comparison+ , fmpq_poly_equal+ , _fmpq_poly_equal_trunc+ , fmpq_poly_equal_trunc+ , _fmpq_poly_cmp+ , fmpq_poly_cmp+ , fmpq_poly_is_one+ , fmpq_poly_is_zero+ , fmpq_poly_is_gen+ -- * Addition and subtraction+ , _fmpq_poly_add+ , _fmpq_poly_add_can+ , fmpq_poly_add+ , fmpq_poly_add_can+ , _fmpq_poly_add_series+ , _fmpq_poly_add_series_can+ , fmpq_poly_add_series+ , fmpq_poly_add_series_can+ , _fmpq_poly_sub+ , _fmpq_poly_sub_can+ , fmpq_poly_sub+ , fmpq_poly_sub_can+ , _fmpq_poly_sub_series+ , _fmpq_poly_sub_series_can+ , fmpq_poly_sub_series+ , fmpq_poly_sub_series_can+ -- * Scalar multiplication and division+ , _fmpq_poly_scalar_mul_si+ , _fmpq_poly_scalar_mul_ui+ , _fmpq_poly_scalar_mul_fmpz+ , _fmpq_poly_scalar_mul_fmpq+ , fmpq_poly_scalar_mul_si+ , fmpq_poly_scalar_mul_ui+ , fmpq_poly_scalar_mul_fmpz+ , fmpq_poly_scalar_mul_fmpq+ -- , fmpq_poly_scalar_mul_mpz -- deprecated+ -- , fmpq_poly_scalar_mul_mpq -- deprecated+ , _fmpq_poly_scalar_div_fmpz+ , _fmpq_poly_scalar_div_si+ , _fmpq_poly_scalar_div_ui+ , _fmpq_poly_scalar_div_fmpq+ , fmpq_poly_scalar_div_si+ , fmpq_poly_scalar_div_ui+ , fmpq_poly_scalar_div_fmpz+ , fmpq_poly_scalar_div_fmpq+ -- , fmpq_poly_scalar_div_mpz -- deprecated+ -- , fmpq_poly_scalar_div_mpq -- deprecated+ -- * Multiplication+ , _fmpq_poly_mul+ , fmpq_poly_mul+ , _fmpq_poly_mullow+ , fmpq_poly_mullow+ , fmpq_poly_addmul+ , fmpq_poly_submul+ -- * Powering+ , _fmpq_poly_pow+ , fmpq_poly_pow+ , _fmpq_poly_pow_trunc+ , fmpq_poly_pow_trunc+ -- * Shifting+ , fmpq_poly_shift_left+ , fmpq_poly_shift_right+ -- * Euclidean division+ , _fmpq_poly_divrem+ , fmpq_poly_divrem+ , _fmpq_poly_div+ , fmpq_poly_div+ , _fmpq_poly_rem+ , fmpq_poly_rem+ -- * Powering+ , _fmpq_poly_powers_precompute+ , fmpq_poly_powers_precompute+ , _fmpq_poly_powers_clear+ , fmpq_poly_powers_clear+ , _fmpq_poly_rem_powers_precomp+ , fmpq_poly_rem_powers_precomp+ -- * Divisibility testing+ , _fmpq_poly_divides+ , fmpq_poly_divides+ , fmpq_poly_remove+ -- * Power series division+ , _fmpq_poly_inv_series_newton+ , fmpq_poly_inv_series_newton+ , _fmpq_poly_inv_series+ , fmpq_poly_inv_series+ , _fmpq_poly_div_series+ , fmpq_poly_div_series+ -- * Greatest common divisor+ , _fmpq_poly_gcd+ , fmpq_poly_gcd+ , _fmpq_poly_xgcd+ , fmpq_poly_xgcd+ , _fmpq_poly_lcm+ , fmpq_poly_lcm+ , _fmpq_poly_resultant+ , fmpq_poly_resultant+ , fmpq_poly_resultant_div+ -- * Derivative and integral+ , _fmpq_poly_derivative+ , fmpq_poly_derivative+ , _fmpq_poly_nth_derivative+ , fmpq_poly_nth_derivative+ , _fmpq_poly_integral+ , fmpq_poly_integral+ -- * Square roots+ , _fmpq_poly_sqrt_series+ , fmpq_poly_sqrt_series+ , _fmpq_poly_invsqrt_series+ , fmpq_poly_invsqrt_series+ -- * Power sums+ , _fmpq_poly_power_sums+ , fmpq_poly_power_sums+ , _fmpq_poly_power_sums_to_poly+ , fmpq_poly_power_sums_to_fmpz_poly+ , fmpq_poly_power_sums_to_poly+ -- * Transcendental functions+ , _fmpq_poly_log_series+ , fmpq_poly_log_series+ , _fmpq_poly_exp_series+ , fmpq_poly_exp_series+ , _fmpq_poly_exp_expinv_series+ , fmpq_poly_exp_expinv_series+ , _fmpq_poly_atan_series+ , fmpq_poly_atan_series+ , _fmpq_poly_atanh_series+ , fmpq_poly_atanh_series+ , _fmpq_poly_asin_series+ , fmpq_poly_asin_series+ , _fmpq_poly_asinh_series+ , fmpq_poly_asinh_series+ , _fmpq_poly_tan_series+ , fmpq_poly_tan_series+ , _fmpq_poly_sin_series+ , fmpq_poly_sin_series+ , _fmpq_poly_cos_series+ , fmpq_poly_cos_series+ , _fmpq_poly_sin_cos_series+ , fmpq_poly_sin_cos_series+ , _fmpq_poly_sinh_series+ , fmpq_poly_sinh_series+ , _fmpq_poly_cosh_series+ , fmpq_poly_cosh_series+ , _fmpq_poly_sinh_cosh_series+ , fmpq_poly_sinh_cosh_series+ , _fmpq_poly_tanh_series+ , fmpq_poly_tanh_series+ -- * Orthogonal polynomials+ , _fmpq_poly_legendre_p+ , fmpq_poly_legendre_p+ , _fmpq_poly_laguerre_l+ , fmpq_poly_laguerre_l+ , _fmpq_poly_gegenbauer_c+ , fmpq_poly_gegenbauer_c+ , _fmpq_poly_monien_h+ , fmpq_poly_monien_h+ -- * Evaluation+ , _fmpq_poly_evaluate_fmpz+ , fmpq_poly_evaluate_fmpz+ , _fmpq_poly_evaluate_fmpq+ , fmpq_poly_evaluate_fmpq+ -- , fmpq_poly_evaluate_mpz -- deprecated+ -- , fmpq_poly_evaluate_mpq -- deprecated+ -- * Interpolation+ , _fmpq_poly_interpolate_fmpz_vec+ , fmpq_poly_interpolate_fmpz_vec+ -- * Composition+ , _fmpq_poly_compose+ , fmpq_poly_compose+ , _fmpq_poly_rescale+ , fmpq_poly_rescale+ -- * Power series composition+ , _fmpq_poly_compose_series_horner+ , fmpq_poly_compose_series_horner+ , _fmpq_poly_compose_series_brent_kung+ , fmpq_poly_compose_series_brent_kung+ , _fmpq_poly_compose_series+ , fmpq_poly_compose_series+ -- * Power series reversion+ , _fmpq_poly_revert_series_lagrange+ , fmpq_poly_revert_series_lagrange+ , _fmpq_poly_revert_series_lagrange_fast+ , fmpq_poly_revert_series_lagrange_fast+ , _fmpq_poly_revert_series_newton+ , fmpq_poly_revert_series_newton+ , _fmpq_poly_revert_series+ , fmpq_poly_revert_series+ -- * Gaussian content+ , _fmpq_poly_content+ , fmpq_poly_content+ , _fmpq_poly_primitive_part+ , fmpq_poly_primitive_part+ , _fmpq_poly_is_monic+ , fmpq_poly_is_monic+ , _fmpq_poly_make_monic+ , fmpq_poly_make_monic+ -- * Square-free+ , fmpq_poly_is_squarefree+ -- * Input and output+ , _fmpq_poly_set_str+ , fmpq_poly_set_str+ , fmpq_poly_get_str+ , fmpq_poly_get_str_pretty+ , fmpq_poly_get_str_pretty_as_series+ , _fmpq_poly_print+ , fmpq_poly_print+ , _fmpq_poly_print_pretty+ , fmpq_poly_print_pretty+ , _fmpq_poly_fprint+ , fmpq_poly_fprint+ , _fmpq_poly_fprint_pretty+ , fmpq_poly_fprint_pretty+ , fmpq_poly_fprint_pretty_as_series+ , fmpq_poly_print_pretty_as_series+ , fmpq_poly_read+ , fmpq_poly_fread+) where ++-- univariate polynomials over the rational numbers ----------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpq++import Data.Number.Flint.NMod.Types+++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpq.h>+#include <flint/fmpz_poly.h>+#include <flint/fmpq_poly.h>++-- fmpq_poly_t -----------------------------------------------------------------++data FmpqPoly = FmpqPoly {-# UNPACK #-} !(ForeignPtr CFmpqPoly)+data CFmpqPoly = CFmpqPoly (Ptr CFmpz) (Ptr CFmpz) CLong CLong++instance Storable CFmpqPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpq_poly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpq_poly_t}+ peek ptr = CFmpqPoly + <$> #{peek fmpq_poly_struct, coeffs} ptr+ <*> #{peek fmpq_poly_struct, den } ptr+ <*> #{peek fmpq_poly_struct, alloc } ptr+ <*> #{peek fmpq_poly_struct, length} ptr+ poke = error "CFmpqPoly.poke: Not defined"++newFmpqPoly = do+ p <- mallocForeignPtr+ withForeignPtr p fmpq_poly_init+ addForeignPtrFinalizer p_fmpq_poly_clear p+ return $ FmpqPoly p++{-# INLINE withFmpqPoly #-}+withFmpqPoly (FmpqPoly p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpqPoly p,)++withNewFmpqPoly f = do+ x <- newFmpqPoly+ withFmpqPoly x $ \x -> f x++-- fmpq_poly_powers_precomp_t --------------------------------------------------++-- | Data structure containing the /CFmpqPolyPowersPrecomp/ pointer+data FmpqPolyPowersPrecomp = FmpqPolyPowersPrecomp+ {-# UNPACK #-} !(ForeignPtr CFmpqPolyPowersPrecomp) +type CFmpqPolyPowersPrecomp = CFlint FmpqPolyPowersPrecomp++-- | Data structure containing the /CFmpqPolyFactor/ pointer+data FmpqPolyFactor = FmpqPolyFactor+ {-# UNPACK #-} !(ForeignPtr CFmpqPolyFactor) +type CFmpqPolyFactor = CFlint FmpqPolyFactor++-- Memory management -----------------------------------------------------------++-- | /fmpq_poly_init/ /poly/ +-- +-- Initialises the polynomial for use. The length is set to zero.+foreign import ccall "fmpq_poly.h fmpq_poly_init"+ fmpq_poly_init :: Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_init2/ /poly/ /alloc/ +-- +-- Initialises the polynomial with space for at least @alloc@ coefficients+-- and set the length to zero. The @alloc@ coefficients are all set to+-- zero.+foreign import ccall "fmpq_poly.h fmpq_poly_init2"+ fmpq_poly_init2 :: Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_realloc/ /poly/ /alloc/ +-- +-- Reallocates the given polynomial to have space for @alloc@ coefficients.+-- If @alloc@ is zero then the polynomial is cleared and then+-- reinitialised. If the current length is greater than @alloc@ then @poly@+-- is first truncated to length @alloc@. Note that this might leave the+-- rational polynomial in non-canonical form.+foreign import ccall "fmpq_poly.h fmpq_poly_realloc"+ fmpq_poly_realloc :: Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_fit_length/ /poly/ /len/ +-- +-- If @len@ is greater than the number of coefficients currently allocated,+-- then the polynomial is reallocated to have space for at least @len@+-- coefficients. No data is lost when calling this function. The function+-- efficiently deals with the case where @fit_length@ is called many times+-- in small increments by at least doubling the number of allocated+-- coefficients when @len@ is larger than the number of coefficients+-- currently allocated.+foreign import ccall "fmpq_poly.h fmpq_poly_fit_length"+ fmpq_poly_fit_length :: Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_set_length/ /poly/ /len/ +-- +-- Sets the length of the numerator polynomial to @len@, demoting+-- coefficients beyond the new length. Note that this method does not+-- guarantee that the rational polynomial is in canonical form.+foreign import ccall "fmpq_poly.h _fmpq_poly_set_length"+ _fmpq_poly_set_length :: Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_clear/ /poly/ +-- +-- Clears the given polynomial, releasing any memory used. The polynomial+-- must be reinitialised in order to be used again.+foreign import ccall "fmpq_poly.h fmpq_poly_clear"+ fmpq_poly_clear :: Ptr CFmpqPoly -> IO ()++foreign import ccall "fmpq_poly.h &fmpq_poly_clear"+ p_fmpq_poly_clear :: FunPtr (Ptr CFmpqPoly -> IO ())++-- | /_fmpq_poly_normalise/ /poly/ +-- +-- Sets the length of @poly@ so that the top coefficient is non-zero. If+-- all coefficients are zero, the length is set to zero. Note that this+-- function does not guarantee the coprimality of the numerator polynomial+-- and the integer denominator.+foreign import ccall "fmpq_poly.h _fmpq_poly_normalise"+ _fmpq_poly_normalise :: Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_canonicalise/ /poly/ /den/ /len/ +-- +-- Puts @(poly, den)@ of length @len@ into canonical form.+-- +-- It is assumed that the array @poly@ contains a non-zero entry in+-- position @len - 1@ whenever @len > 0@. Assumes that @den@ is non-zero.+foreign import ccall "fmpq_poly.h _fmpq_poly_canonicalise"+ _fmpq_poly_canonicalise :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_canonicalise/ /poly/ +-- +-- Puts the polynomial @poly@ into canonical form. Firstly, the length is+-- set to the actual length of the numerator polynomial. For non-zero+-- polynomials, it is then ensured that the numerator and denominator are+-- coprime and that the denominator is positive. The canonical form of the+-- zero polynomial is a zero numerator polynomial and a one denominator.+foreign import ccall "fmpq_poly.h fmpq_poly_canonicalise"+ fmpq_poly_canonicalise :: Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_is_canonical/ /poly/ /den/ /len/ +-- +-- Returns whether the polynomial is in canonical form.+foreign import ccall "fmpq_poly.h _fmpq_poly_is_canonical"+ _fmpq_poly_is_canonical :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpq_poly_is_canonical/ /poly/ +-- +-- Returns whether the polynomial is in canonical form.+foreign import ccall "fmpq_poly.h fmpq_poly_is_canonical"+ fmpq_poly_is_canonical :: Ptr CFmpqPoly -> IO CInt++-- Polynomial parameters -------------------------------------------------------++-- | /fmpq_poly_degree/ /poly/ +-- +-- Returns the degree of @poly@, which is one less than its length, as a+-- @slong@.+foreign import ccall "fmpq_poly.h fmpq_poly_degree"+ fmpq_poly_degree :: Ptr CFmpqPoly -> IO CLong++-- | /fmpq_poly_length/ /poly/ +-- +-- Returns the length of @poly@.+foreign import ccall "fmpq_poly.h fmpq_poly_length"+ fmpq_poly_length :: Ptr CFmpqPoly -> IO CLong++-- Accessing the numerator and denominator -------------------------------------++-- | /fmpq_poly_numref/ /poly/ +-- +-- Returns a reference to the numerator polynomial as an array.+-- +-- Note that, because of a delayed initialisation approach, this might be+-- @NULL@ for zero polynomials. This situation can be salvaged by calling+-- either @fmpq_poly_fit_length@ or @fmpq_poly_realloc@.+-- +-- This function is implemented as a macro returning @(poly)->coeffs@.+fmpq_poly_numref :: Ptr CFmpqPoly -> IO (Ptr CFmpz)+fmpq_poly_numref poly = do+ CFmpqPoly coeffs _ _ _ <- peek poly+ return $ coeffs+ +-- | /fmpq_poly_denref/ /poly/ +-- +-- Returns a reference to the denominator as a @fmpz_t@. The integer is+-- guaranteed to be properly initialised.+-- +-- This function is implemented as a macro returning @(poly)->den@.+fmpq_poly_denref :: Ptr CFmpqPoly -> IO (Ptr CFmpz)+fmpq_poly_denref poly = do+ CFmpqPoly _ den _ _ <- peek poly+ return $ den+ +-- | /fmpq_poly_get_numerator/ /res/ /poly/ +-- +-- Sets @res@ to the numerator of @poly@, e.g. the primitive part as an+-- @fmpz_poly_t@ if it is in canonical form .+foreign import ccall "fmpq_poly.h fmpq_poly_get_numerator"+ fmpq_poly_get_numerator :: Ptr CFmpzPoly -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_get_denominator/ /den/ /poly/ +-- +-- Sets @res@ to the denominator of @poly@.+foreign import ccall "fmpq_poly.h fmpq_poly_get_denominator"+ fmpq_poly_get_denominator :: Ptr CFmpz -> Ptr CFmpqPoly -> IO ()++-- Random testing --------------------------------------------------------------++-- The functions @fmpq_poly_randtest_foo@ provide random polynomials+-- suitable for testing. On an integer level, this means that long strings+-- of zeros and ones in the binary representation are favoured as well as+-- the special absolute values \(0\), \(1\), @COEFF_MAX@, and @WORD_MAX@.+-- On a polynomial level, the integer numerator has a reasonable chance to+-- have a non-trivial content.+--+-- | /fmpq_poly_randtest/ /f/ /state/ /len/ /bits/ +-- +-- Sets \(f\) to a random polynomial with coefficients up to the given+-- length and where each coefficient has up to the given number of bits.+-- The coefficients are signed randomly. One must call @flint_randinit@+-- before calling this function.+foreign import ccall "fmpq_poly.h fmpq_poly_randtest"+ fmpq_poly_randtest :: Ptr CFmpqPoly -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- | /fmpq_poly_randtest_unsigned/ /f/ /state/ /len/ /bits/ +-- +-- Sets \(f\) to a random polynomial with coefficients up to the given+-- length and where each coefficient has up to the given number of bits.+-- One must call @flint_randinit@ before calling this function.+foreign import ccall "fmpq_poly.h fmpq_poly_randtest_unsigned"+ fmpq_poly_randtest_unsigned :: Ptr CFmpqPoly -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- | /fmpq_poly_randtest_not_zero/ /f/ /state/ /len/ /bits/ +-- +-- As for @fmpq_poly_randtest@ except that @len@ and @bits@ may not be zero+-- and the polynomial generated is guaranteed not to be the zero+-- polynomial. One must call @flint_randinit@ before calling this function.+foreign import ccall "fmpq_poly.h fmpq_poly_randtest_not_zero"+ fmpq_poly_randtest_not_zero :: Ptr CFmpqPoly -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- Assignment, swap, negation --------------------------------------------------++-- | /fmpq_poly_set/ /poly1/ /poly2/ +-- +-- Sets @poly1@ to equal @poly2@.+foreign import ccall "fmpq_poly.h fmpq_poly_set"+ fmpq_poly_set :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_set_si/ /poly/ /x/ +-- +-- Sets @poly@ to the integer \(x\).+foreign import ccall "fmpq_poly.h fmpq_poly_set_si"+ fmpq_poly_set_si :: Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_set_ui/ /poly/ /x/ +-- +-- Sets @poly@ to the integer \(x\).+foreign import ccall "fmpq_poly.h fmpq_poly_set_ui"+ fmpq_poly_set_ui :: Ptr CFmpqPoly -> CULong -> IO ()++-- | /fmpq_poly_set_fmpz/ /poly/ /x/ +-- +-- Sets @poly@ to the integer \(x\).+foreign import ccall "fmpq_poly.h fmpq_poly_set_fmpz"+ fmpq_poly_set_fmpz :: Ptr CFmpqPoly -> Ptr CFmpz -> IO ()++-- | /fmpq_poly_set_fmpq/ /poly/ /x/ +-- +-- Sets @poly@ to the rational \(x\), which is assumed to be given in+-- lowest terms.+foreign import ccall "fmpq_poly.h fmpq_poly_set_fmpq"+ fmpq_poly_set_fmpq :: Ptr CFmpqPoly -> Ptr CFmpq -> IO ()++-- -- | /fmpq_poly_set_mpz/ /poly/ /x/ +-- -- +-- -- Sets @poly@ to the integer \(x\).+-- foreign import ccall "fmpq_poly.h fmpq_poly_set_mpz"+-- fmpq_poly_set_mpz :: Ptr CFmpqPoly -> Ptr CMpz -> IO ()++-- -- | /fmpq_poly_set_mpq/ /poly/ /x/ +-- -- +-- -- Sets @poly@ to the rational \(x\), which is assumed to be given in+-- -- lowest terms.+-- foreign import ccall "fmpq_poly.h fmpq_poly_set_mpq"+-- fmpq_poly_set_mpq :: Ptr CFmpqPoly -> Ptr CMpq -> IO ()++-- | /fmpq_poly_set_fmpz_poly/ /rop/ /op/ +-- +-- Sets the rational polynomial @rop@ to the same value as the integer+-- polynomial @op@.+foreign import ccall "fmpq_poly.h fmpq_poly_set_fmpz_poly"+ fmpq_poly_set_fmpz_poly :: Ptr CFmpqPoly -> Ptr CFmpzPoly -> IO ()++-- | /fmpq_poly_set_nmod_poly/ /rop/ /op/ +-- +-- Sets the coefficients of @rop@ to the residues in @op@, normalised to+-- the interval \(-m/2 \le r < m/2\) where \(m\) is the modulus.+foreign import ccall "fmpq_poly.h fmpq_poly_set_nmod_poly"+ fmpq_poly_set_nmod_poly :: Ptr CFmpqPoly -> Ptr CNModPoly -> IO ()++-- | /fmpq_poly_get_nmod_poly/ /rop/ /op/ +-- +-- Sets the coefficients of @rop@ to the coefficients in the denominator+-- of@op@, reduced by the modulus of @rop@. The result is multiplied by the+-- inverse of the denominator of @op@. It is assumed that the reduction of+-- the denominator of @op@ is invertible.+foreign import ccall "fmpq_poly.h fmpq_poly_get_nmod_poly"+ fmpq_poly_get_nmod_poly :: Ptr CNModPoly -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_get_nmod_poly_den/ /rop/ /op/ /den/ +-- +-- Sets the coefficients of @rop@ to the coefficients in the denominator of+-- @op@, reduced by the modulus of @rop@. If @den == 1@, the result is+-- multiplied by the inverse of the denominator of @op@. In this case it is+-- assumed that the reduction of the denominator of @op@ is invertible.+foreign import ccall "fmpq_poly.h fmpq_poly_get_nmod_poly_den"+ fmpq_poly_get_nmod_poly_den :: Ptr CNModPoly -> Ptr CFmpqPoly -> CInt -> IO ()++-- -- | /_fmpq_poly_set_array_mpq/ /poly/ /den/ /a/ /n/ +-- -- +-- -- Sets @(poly, den)@ to the polynomial given by the first \(n \geq 1\)+-- -- coefficients in the array \(a\), from lowest degree to highest degree.+-- -- +-- -- The result is only guaranteed to be in lowest terms if all input+-- -- coefficients are given in lowest terms.+-- foreign import ccall "fmpq_poly.h _fmpq_poly_set_array_mpq"+-- _fmpq_poly_set_array_mpq :: Ptr CFmpz -> Ptr CFmpz -> Ptr CMpq -> CLong -> IO ()++-- -- | /fmpq_poly_set_array_mpq/ /poly/ /a/ /n/ +-- -- +-- -- Sets @poly@ to the polynomial with coefficients as given in the array+-- -- \(a\) of length \(n \geq 0\), from lowest degree to highest degree.+-- -- +-- -- The result is only guaranteed to be in canonical form if all input+-- -- coefficients are given in lowest terms.+-- foreign import ccall "fmpq_poly.h fmpq_poly_set_array_mpq"+-- fmpq_poly_set_array_mpq :: Ptr CFmpqPoly -> Ptr CMpq -> CLong -> IO ()++-- | /_fmpq_poly_set_str/ /poly/ /den/ /str/ /len/ +-- +-- Sets @(poly, den)@ to the polynomial specified by the null-terminated+-- string @str@ of @len@ coefficients. The input format is a sequence of+-- coefficients separated by one space.+-- +-- The result is only guaranteed to be in lowest terms if all coefficients+-- in the input string are in lowest terms.+-- +-- Returns \(0\) if no error occurred. Otherwise, returns -1 in which case+-- the resulting value of @(poly, den)@ is undefined. If @str@ is not+-- null-terminated, calling this method might result in a segmentation+-- fault.+foreign import ccall "fmpq_poly.h _fmpq_poly_set_str"+ _fmpq_poly_set_str :: Ptr CFmpz -> Ptr CFmpz -> CString -> CLong -> IO CInt++-- | /fmpq_poly_set_str/ /poly/ /str/ +-- +-- Sets @poly@ to the polynomial specified by the null-terminated string+-- @str@. The input format is the same as the output format of+-- @fmpq_poly_get_str@: the length given as a decimal integer, then two+-- spaces, then the list of coefficients separated by one space.+-- +-- The result is only guaranteed to be in canonical form if all+-- coefficients in the input string are in lowest terms.+-- +-- Returns \(0\) if no error occurred. Otherwise, returns -1 in which case+-- the resulting value of @poly@ is set to zero. If @str@ is not+-- null-terminated, calling this method might result in a segmentation+-- fault.+foreign import ccall "fmpq_poly.h fmpq_poly_set_str"+ fmpq_poly_set_str :: Ptr CFmpqPoly -> CString -> IO CInt++-- | /fmpq_poly_get_str/ /poly/ +-- +-- Returns the string representation of @poly@.+foreign import ccall "fmpq_poly.h fmpq_poly_get_str"+ fmpq_poly_get_str :: Ptr CFmpqPoly -> IO CString++-- | /fmpq_poly_get_str_pretty/ /poly/ /var/ +-- +-- Returns the pretty representation of @poly@, using the null-terminated+-- string @var@ not equal to @\"\\0\"@ as the variable name.+foreign import ccall "fmpq_poly.h fmpq_poly_get_str_pretty"+ fmpq_poly_get_str_pretty :: Ptr CFmpqPoly -> CString -> IO CString++-- | /fmpq_poly_zero/ /poly/ +-- +-- Sets @poly@ to zero.+foreign import ccall "fmpq_poly.h fmpq_poly_zero"+ fmpq_poly_zero :: Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_one/ /poly/ +-- +-- Sets @poly@ to the constant polynomial \(1\).+foreign import ccall "fmpq_poly.h fmpq_poly_one"+ fmpq_poly_one :: Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_neg/ /poly1/ /poly2/ +-- +-- Sets @poly1@ to the additive inverse of @poly2@.+foreign import ccall "fmpq_poly.h fmpq_poly_neg"+ fmpq_poly_neg :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_inv/ /poly1/ /poly2/ +-- +-- Sets @poly1@ to the multiplicative inverse of @poly2@ if possible.+-- Otherwise, if @poly2@ is not a unit, leaves @poly1@ unmodified and calls+-- @abort@.+foreign import ccall "fmpq_poly.h fmpq_poly_inv"+ fmpq_poly_inv :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_swap/ /poly1/ /poly2/ +-- +-- Efficiently swaps the polynomials @poly1@ and @poly2@.+foreign import ccall "fmpq_poly.h fmpq_poly_swap"+ fmpq_poly_swap :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_truncate/ /poly/ /n/ +-- +-- If the current length of @poly@ is greater than \(n\), it is truncated+-- to the given length. Discarded coefficients are demoted, but they are+-- not necessarily set to zero.+foreign import ccall "fmpq_poly.h fmpq_poly_truncate"+ fmpq_poly_truncate :: Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_set_trunc/ /res/ /poly/ /n/ +-- +-- Sets @res@ to a copy of @poly@, truncated to length @n@.+foreign import ccall "fmpq_poly.h fmpq_poly_set_trunc"+ fmpq_poly_set_trunc :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_get_slice/ /rop/ /op/ /i/ /j/ +-- +-- Returns the slice with coefficients from \(x^i\) (including) to \(x^j\)+-- (excluding).+foreign import ccall "fmpq_poly.h fmpq_poly_get_slice"+ fmpq_poly_get_slice :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> CLong -> IO ()++-- | /fmpq_poly_reverse/ /res/ /poly/ /n/ +-- +-- This function considers the polynomial @poly@ to be of length \(n\),+-- notionally truncating and zero padding if required, and reverses the+-- result. Since the function normalises its result @res@ may be of length+-- less than \(n\).+foreign import ccall "fmpq_poly.h fmpq_poly_reverse"+ fmpq_poly_reverse :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- Getting and setting coefficients --------------------------------------------++-- | /fmpq_poly_get_coeff_fmpz/ /x/ /poly/ /n/ +-- +-- Retrieves the \(n`th coefficient of the numerator of \)poly\`.+foreign import ccall "fmpq_poly.h fmpq_poly_get_coeff_fmpz"+ fmpq_poly_get_coeff_fmpz :: Ptr CFmpz -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_get_coeff_fmpq/ /x/ /poly/ /n/ +-- +-- Retrieves the \(n`th coefficient of \)poly\`, in lowest terms.+foreign import ccall "fmpq_poly.h fmpq_poly_get_coeff_fmpq"+ fmpq_poly_get_coeff_fmpq :: Ptr CFmpq -> Ptr CFmpqPoly -> CLong -> IO ()++-- -- | /fmpq_poly_get_coeff_mpq/ /x/ /poly/ /n/ +-- -- +-- -- Retrieves the \(n`th coefficient of \)poly\`, in lowest terms.+-- foreign import ccall "fmpq_poly.h fmpq_poly_get_coeff_mpq"+-- fmpq_poly_get_coeff_mpq :: Ptr CMpq -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_set_coeff_si/ /poly/ /n/ /x/ +-- +-- Sets the \(n`th coefficient in \)poly to the integer :math:\`x.+foreign import ccall "fmpq_poly.h fmpq_poly_set_coeff_si"+ fmpq_poly_set_coeff_si :: Ptr CFmpqPoly -> CLong -> CLong -> IO ()++-- | /fmpq_poly_set_coeff_ui/ /poly/ /n/ /x/ +-- +-- Sets the \(n`th coefficient in \)poly to the integer :math:\`x.+foreign import ccall "fmpq_poly.h fmpq_poly_set_coeff_ui"+ fmpq_poly_set_coeff_ui :: Ptr CFmpqPoly -> CLong -> CULong -> IO ()++-- | /fmpq_poly_set_coeff_fmpz/ /poly/ /n/ /x/ +-- +-- Sets the \(n`th coefficient in \)poly to the integer :math:\`x.+foreign import ccall "fmpq_poly.h fmpq_poly_set_coeff_fmpz"+ fmpq_poly_set_coeff_fmpz :: Ptr CFmpqPoly -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpq_poly_set_coeff_fmpq/ /poly/ /n/ /x/ +-- +-- Sets the \(n`th coefficient in \)poly to the rational :math:\`x.+foreign import ccall "fmpq_poly.h fmpq_poly_set_coeff_fmpq"+ fmpq_poly_set_coeff_fmpq :: Ptr CFmpqPoly -> CLong -> Ptr CFmpq -> IO ()++-- -- | /fmpq_poly_set_coeff_mpz/ /rop/ /n/ /x/ +-- -- +-- -- Sets the \(n`th coefficient in \)poly to the integer :math:\`x.+-- foreign import ccall "fmpq_poly.h fmpq_poly_set_coeff_mpz"+-- fmpq_poly_set_coeff_mpz :: Ptr CFmpqPoly -> CLong -> Ptr CMpz -> IO ()++-- -- | /fmpq_poly_set_coeff_mpq/ /rop/ /n/ /x/ +-- -- +-- -- Sets the \(n`th coefficient in \)poly to the rational~\`x, which is+-- -- expected to be provided in lowest terms.+-- foreign import ccall "fmpq_poly.h fmpq_poly_set_coeff_mpq"+-- fmpq_poly_set_coeff_mpq :: Ptr CFmpqPoly -> CLong -> Ptr CMpq -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fmpq_poly_equal/ /poly1/ /poly2/ +-- +-- Returns \(1\) if @poly1@ is equal to @poly2@, otherwise returns~\`0\`.+foreign import ccall "fmpq_poly.h fmpq_poly_equal"+ fmpq_poly_equal :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO CInt++-- | /_fmpq_poly_equal_trunc/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ /n/ +-- +-- Return \(1\) if @poly1@ and @poly2@ notionally truncated to length \(n\)+-- are equal, otherwise returns~\`0\`.+foreign import ccall "fmpq_poly.h _fmpq_poly_equal_trunc"+ _fmpq_poly_equal_trunc :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO CInt++-- | /fmpq_poly_equal_trunc/ /poly1/ /poly2/ /n/ +-- +-- Return \(1\) if @poly1@ and @poly2@ notionally truncated to length \(n\)+-- are equal, otherwise returns~\`0\`.+foreign import ccall "fmpq_poly.h fmpq_poly_equal_trunc"+ fmpq_poly_equal_trunc :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO CInt++-- | /_fmpq_poly_cmp/ /lpoly/ /lden/ /rpoly/ /rden/ /len/ +-- +-- Compares two non-zero polynomials, assuming they have the same length+-- @len > 0@.+-- +-- The polynomials are expected to be provided in canonical form.+foreign import ccall "fmpq_poly.h _fmpq_poly_cmp"+ _fmpq_poly_cmp :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpq_poly_cmp/ /left/ /right/ +-- +-- Compares the two polynomials @left@ and @right@.+-- +-- Compares the two polynomials @left@ and @right@, returning \(-1\),+-- \(0\), or \(1\) as @left@ is less than, equal to, or greater than+-- @right@. The comparison is first done by the degree, and then, in case+-- of a tie, by the individual coefficients from highest to lowest.+foreign import ccall "fmpq_poly.h fmpq_poly_cmp"+ fmpq_poly_cmp :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO CInt++-- | /fmpq_poly_is_one/ /poly/ +-- +-- Returns \(1\) if @poly@ is the constant polynomial~\`1\`, otherwise+-- returns \(0\).+foreign import ccall "fmpq_poly.h fmpq_poly_is_one"+ fmpq_poly_is_one :: Ptr CFmpqPoly -> IO CInt++-- | /fmpq_poly_is_zero/ /poly/ +-- +-- Returns \(1\) if @poly@ is the zero polynomial, otherwise returns \(0\).+foreign import ccall "fmpq_poly.h fmpq_poly_is_zero"+ fmpq_poly_is_zero :: Ptr CFmpqPoly -> IO CInt++-- | /fmpq_poly_is_gen/ /poly/ +-- +-- Returns \(1\) if @poly@ is the degree \(1\) polynomial \(x\), otherwise+-- returns \(0\).+foreign import ccall "fmpq_poly.h fmpq_poly_is_gen"+ fmpq_poly_is_gen :: Ptr CFmpqPoly -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /_fmpq_poly_add/ /rpoly/ /rden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ +-- +-- Forms the sum @(rpoly, rden)@ of @(poly1, den1, len1)@ and+-- @(poly2, den2, len2)@, placing the result into canonical form.+-- +-- Assumes that @rpoly@ is an array of length the maximum of @len1@ and+-- @len2@. The input operands are assumed to be in canonical form and are+-- also allowed to be of length~\`0\`.+-- +-- @(rpoly, rden)@ and @(poly1, den1)@ may be aliased, but @(rpoly, rden)@+-- and @(poly2, den2)@ may /not/ be aliased.+foreign import ccall "fmpq_poly.h _fmpq_poly_add"+ _fmpq_poly_add :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpq_poly_add_can/ /rpoly/ /rden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ /can/ +-- +-- As per @_fmpq_poly_add@ except that one can specify whether to+-- canonicalise the output or not. This function is intended to be used+-- with weak canonicalisation to prevent explosion in memory usage. It+-- exists for performance reasons.+foreign import ccall "fmpq_poly.h _fmpq_poly_add_can"+ _fmpq_poly_add_can :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CInt -> IO ()++-- | /fmpq_poly_add/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the sum of @poly1@ and @poly2@, using Henrici\'s+-- algorithm.+foreign import ccall "fmpq_poly.h fmpq_poly_add"+ fmpq_poly_add :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_add_can/ /res/ /poly1/ /poly2/ /can/ +-- +-- As per @fmpq_poly_add@ except that one can specify whether to+-- canonicalise the output or not. This function is intended to be used+-- with weak canonicalisation to prevent explosion in memory usage. It+-- exists for performance reasons.+foreign import ccall "fmpq_poly.h fmpq_poly_add_can"+ fmpq_poly_add_can :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CInt -> IO ()++-- | /_fmpq_poly_add_series/ /rpoly/ /rden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ /n/ +-- +-- As per @_fmpq_poly_add@ but the inputs are first notionally truncated to+-- length \(n\). If \(n\) is less than @len1@ or @len2@ then the output+-- only needs space for \(n\) coefficients. We require \(n \geq 0\).+foreign import ccall "fmpq_poly.h _fmpq_poly_add_series"+ _fmpq_poly_add_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /_fmpq_poly_add_series_can/ /rpoly/ /rden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ /n/ /can/ +-- +-- As per @_fmpq_poly_add_can@ but the inputs are first notionally+-- truncated to length \(n\). If \(n\) is less than @len1@ or @len2@ then+-- the output only needs space for \(n\) coefficients. We require+-- \(n \geq 0\).+foreign import ccall "fmpq_poly.h _fmpq_poly_add_series_can"+ _fmpq_poly_add_series_can :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> CInt -> IO ()++-- | /fmpq_poly_add_series/ /res/ /poly1/ /poly2/ /n/ +-- +-- As per @fmpq_poly_add@ but the inputs are first notionally truncated to+-- length \(n\).+foreign import ccall "fmpq_poly.h fmpq_poly_add_series"+ fmpq_poly_add_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_add_series_can/ /res/ /poly1/ /poly2/ /n/ /can/ +-- +-- As per @fmpq_poly_add_can@ but the inputs are first notionally truncated+-- to length \(n\).+foreign import ccall "fmpq_poly.h fmpq_poly_add_series_can"+ fmpq_poly_add_series_can :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> CInt -> IO ()++-- | /_fmpq_poly_sub/ /rpoly/ /rden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ +-- +-- Forms the difference @(rpoly, rden)@ of @(poly1, den1, len1)@ and+-- @(poly2, den2, len2)@, placing the result into canonical form.+-- +-- Assumes that @rpoly@ is an array of length the maximum of @len1@ and+-- @len2@. The input operands are assumed to be in canonical form and are+-- also allowed to be of length~\`0\`.+-- +-- @(rpoly, rden)@ and @(poly1, den1, len1)@ may be aliased, but+-- @(rpoly, rden)@ and @(poly2, den2, len2)@ may /not/ be aliased.+foreign import ccall "fmpq_poly.h _fmpq_poly_sub"+ _fmpq_poly_sub :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpq_poly_sub_can/ /rpoly/ /rden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ /can/ +-- +-- As per @_fmpq_poly_sub@ except that one can specify whether to+-- canonicalise the output or not. This function is intended to be used+-- with weak canonicalisation to prevent explosion in memory usage. It+-- exists for performance reasons.+foreign import ccall "fmpq_poly.h _fmpq_poly_sub_can"+ _fmpq_poly_sub_can :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CInt -> IO ()++-- | /fmpq_poly_sub/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the difference of @poly1@ and @poly2@, using Henrici\'s+-- algorithm.+foreign import ccall "fmpq_poly.h fmpq_poly_sub"+ fmpq_poly_sub :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_sub_can/ /res/ /poly1/ /poly2/ /can/ +-- +-- As per @_fmpq_poly_sub@ except that one can specify whether to+-- canonicalise the output or not. This function is intended to be used+-- with weak canonicalisation to prevent explosion in memory usage. It+-- exists for performance reasons.+foreign import ccall "fmpq_poly.h fmpq_poly_sub_can"+ fmpq_poly_sub_can :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CInt -> IO ()++-- | /_fmpq_poly_sub_series/ /rpoly/ /rden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ /n/ +-- +-- As per @_fmpq_poly_sub@ but the inputs are first notionally truncated to+-- length \(n\). If \(n\) is less than @len1@ or @len2@ then the output+-- only needs space for \(n\) coefficients. We require \(n \geq 0\).+foreign import ccall "fmpq_poly.h _fmpq_poly_sub_series"+ _fmpq_poly_sub_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /_fmpq_poly_sub_series_can/ /rpoly/ /rden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ /n/ /can/ +-- +-- As per @_fmpq_poly_sub_can@ but the inputs are first notionally+-- truncated to length \(n\). If \(n\) is less than @len1@ or @len2@ then+-- the output only needs space for \(n\) coefficients. We require+-- \(n \geq 0\).+foreign import ccall "fmpq_poly.h _fmpq_poly_sub_series_can"+ _fmpq_poly_sub_series_can :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> CInt -> IO ()++-- | /fmpq_poly_sub_series/ /res/ /poly1/ /poly2/ /n/ +-- +-- As per @fmpq_poly_sub@ but the inputs are first notionally truncated to+-- length \(n\).+foreign import ccall "fmpq_poly.h fmpq_poly_sub_series"+ fmpq_poly_sub_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_sub_series_can/ /res/ /poly1/ /poly2/ /n/ /can/ +-- +-- As per @fmpq_poly_sub_can@ but the inputs are first notionally truncated+-- to length \(n\).+foreign import ccall "fmpq_poly.h fmpq_poly_sub_series_can"+ fmpq_poly_sub_series_can :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> CInt -> IO ()++-- Scalar multiplication and division ------------------------------------------++-- | /_fmpq_poly_scalar_mul_si/ /rpoly/ /rden/ /poly/ /den/ /len/ /c/ +-- +-- Sets @(rpoly, rden, len)@ to the product of \(c\) of @(poly, den, len)@.+-- +-- If the input is normalised, then so is the output, provided it is+-- non-zero. If the input is in lowest terms, then so is the output.+-- However, even if neither of these conditions are met, the result will be+-- (mathematically) correct.+-- +-- Supports exact aliasing between @(rpoly, den)@ and @(poly, den)@.+foreign import ccall "fmpq_poly.h _fmpq_poly_scalar_mul_si"+ _fmpq_poly_scalar_mul_si :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /_fmpq_poly_scalar_mul_ui/ /rpoly/ /rden/ /poly/ /den/ /len/ /c/ +-- +-- Sets @(rpoly, rden, len)@ to the product of \(c\) of @(poly, den, len)@.+-- +-- If the input is normalised, then so is the output, provided it is+-- non-zero. If the input is in lowest terms, then so is the output.+-- However, even if neither of these conditions are met, the result will be+-- (mathematically) correct.+-- +-- Supports exact aliasing between @(rpoly, den)@ and @(poly, den)@.+foreign import ccall "fmpq_poly.h _fmpq_poly_scalar_mul_ui"+ _fmpq_poly_scalar_mul_ui :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /_fmpq_poly_scalar_mul_fmpz/ /rpoly/ /rden/ /poly/ /den/ /len/ /c/ +-- +-- Sets @(rpoly, rden, len)@ to the product of \(c\) of @(poly, den, len)@.+-- +-- If the input is normalised, then so is the output, provided it is+-- non-zero. If the input is in lowest terms, then so is the output.+-- However, even if neither of these conditions are met, the result will be+-- (mathematically) correct.+-- +-- Supports exact aliasing between @(rpoly, den)@ and @(poly, den)@.+foreign import ccall "fmpq_poly.h _fmpq_poly_scalar_mul_fmpz"+ _fmpq_poly_scalar_mul_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /_fmpq_poly_scalar_mul_fmpq/ /rpoly/ /rden/ /poly/ /den/ /len/ /r/ /s/ +-- +-- Sets @(rpoly, rden)@ to the product of \(r/s\) and @(poly, den, len)@,+-- in lowest terms.+-- +-- Assumes that @(poly, den, len)@ and \(r/s\) are provided in lowest+-- terms. Assumes that @rpoly@ is an array of length @len@. Supports+-- aliasing of @(rpoly, den)@ and @(poly, den)@. The @fmpz_t@\'s \(r\) and+-- \(s\) may not be part of @(rpoly, rden)@.+foreign import ccall "fmpq_poly.h _fmpq_poly_scalar_mul_fmpq"+ _fmpq_poly_scalar_mul_fmpq :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpq_poly_scalar_mul_si/ /rop/ /op/ /c/ +-- +-- Sets @rop@ to \(c\) times @op@.+foreign import ccall "fmpq_poly.h fmpq_poly_scalar_mul_si"+ fmpq_poly_scalar_mul_si :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_scalar_mul_ui/ /rop/ /op/ /c/ +-- +-- Sets @rop@ to \(c\) times @op@.+foreign import ccall "fmpq_poly.h fmpq_poly_scalar_mul_ui"+ fmpq_poly_scalar_mul_ui :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CULong -> IO ()++-- | /fmpq_poly_scalar_mul_fmpz/ /rop/ /op/ /c/ +-- +-- Sets @rop@ to \(c\) times @op@. Assumes that the @fmpz_t c@ is not part+-- of @rop@.+foreign import ccall "fmpq_poly.h fmpq_poly_scalar_mul_fmpz"+ fmpq_poly_scalar_mul_fmpz :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpz -> IO ()++-- | /fmpq_poly_scalar_mul_fmpq/ /rop/ /op/ /c/ +-- +-- Sets @rop@ to \(c\) times @op@.+foreign import ccall "fmpq_poly.h fmpq_poly_scalar_mul_fmpq"+ fmpq_poly_scalar_mul_fmpq :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CMpq -> IO ()++-- -- | /fmpq_poly_scalar_mul_mpz/ /rop/ /op/ /c/ +-- -- +-- -- Sets @rop@ to \(c\) times @op@.+-- foreign import ccall "fmpq_poly.h fmpq_poly_scalar_mul_mpz"+-- fmpq_poly_scalar_mul_mpz :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CMpz -> IO ()++-- -- | /fmpq_poly_scalar_mul_mpq/ /rop/ /op/ /c/ +-- -- +-- -- Sets @rop@ to \(c\) times @op@.+-- foreign import ccall "fmpq_poly.h fmpq_poly_scalar_mul_mpq"+-- fmpq_poly_scalar_mul_mpq :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpq -> IO ()++-- | /_fmpq_poly_scalar_div_fmpz/ /rpoly/ /rden/ /poly/ /den/ /len/ /c/ +-- +-- Sets @(rpoly, rden, len)@ to @(poly, den, len)@ divided by \(c\), in+-- lowest terms.+-- +-- Assumes that @len@ is positive. Assumes that \(c\) is non-zero. Supports+-- aliasing between @(rpoly, rden)@ and @(poly, den)@. Assumes that \(c\)+-- is not part of @(rpoly, rden)@.+foreign import ccall "fmpq_poly.h _fmpq_poly_scalar_div_fmpz"+ _fmpq_poly_scalar_div_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /_fmpq_poly_scalar_div_si/ /rpoly/ /rden/ /poly/ /den/ /len/ /c/ +-- +-- Sets @(rpoly, rden, len)@ to @(poly, den, len)@ divided by \(c\), in+-- lowest terms.+-- +-- Assumes that @len@ is positive. Assumes that \(c\) is non-zero. Supports+-- aliasing between @(rpoly, rden)@ and @(poly, den)@.+foreign import ccall "fmpq_poly.h _fmpq_poly_scalar_div_si"+ _fmpq_poly_scalar_div_si :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /_fmpq_poly_scalar_div_ui/ /rpoly/ /rden/ /poly/ /den/ /len/ /c/ +-- +-- Sets @(rpoly, rden, len)@ to @(poly, den, len)@ divided by \(c\), in+-- lowest terms.+-- +-- Assumes that @len@ is positive. Assumes that \(c\) is non-zero. Supports+-- aliasing between @(rpoly, rden)@ and @(poly, den)@.+foreign import ccall "fmpq_poly.h _fmpq_poly_scalar_div_ui"+ _fmpq_poly_scalar_div_ui :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /_fmpq_poly_scalar_div_fmpq/ /rpoly/ /rden/ /poly/ /den/ /len/ /r/ /s/ +-- +-- Sets @(rpoly, rden, len)@ to @(poly, den, len)@ divided by \(r/s\), in+-- lowest terms.+-- +-- Assumes that @len@ is positive. Assumes that \(r/s\) is non-zero and in+-- lowest terms. Supports aliasing between @(rpoly, rden)@ and+-- @(poly, den)@. The @fmpz_t@\'s \(r\) and \(s\) may not be part of+-- @(rpoly, poly)@.+foreign import ccall "fmpq_poly.h _fmpq_poly_scalar_div_fmpq"+ _fmpq_poly_scalar_div_fmpq :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpq_poly_scalar_div_si/ /rop/ /op/ /c/ +-- +-- Sets @rop@ to @op@ divided by the scalar @c@.+foreign import ccall "fmpq_poly.h fmpq_poly_scalar_div_si"+ fmpq_poly_scalar_div_si :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++foreign import ccall "fmpq_poly.h fmpq_poly_scalar_div_ui"+ fmpq_poly_scalar_div_ui :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++foreign import ccall "fmpq_poly.h fmpq_poly_scalar_div_fmpz"+ fmpq_poly_scalar_div_fmpz :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpz -> IO ()++foreign import ccall "fmpq_poly.h fmpq_poly_scalar_div_fmpq"+ fmpq_poly_scalar_div_fmpq :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpq -> IO ()++-- foreign import ccall "fmpq_poly.h fmpq_poly_scalar_div_mpz"+-- fmpq_poly_scalar_div_mpz :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr Mpz -> IO ()++-- foreign import ccall "fmpq_poly.h fmpq_poly_scalar_div_mpq"+-- fmpq_poly_scalar_div_mpq :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr Mpq -> IO ()+ +-- Multiplication --------------------------------------------------------------++-- | /_fmpq_poly_mul/ /rpoly/ /rden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ +-- +-- Sets @(rpoly, rden, len1 + len2 - 1)@ to the product of+-- @(poly1, den1, len1)@ and @(poly2, den2, len2)@. If the input is+-- provided in canonical form, then so is the output.+-- +-- Assumes @len1 >= len2 > 0@. Allows zero-padding in the input. Does not+-- allow aliasing between the inputs and outputs.+foreign import ccall "fmpq_poly.h _fmpq_poly_mul"+ _fmpq_poly_mul :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_mul/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@.+foreign import ccall "fmpq_poly.h fmpq_poly_mul"+ fmpq_poly_mul :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_mullow/ /rpoly/ /rden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ /n/ +-- +-- Sets @(rpoly, rden, n)@ to the low \(n\) coefficients of @(poly1, den1)@+-- and @(poly2, den2)@. The output is not guaranteed to be in canonical+-- form.+-- +-- Assumes @len1 >= len2 > 0@ and @0 \< n \<= len1 + len2 - 1@. Allows for+-- zero-padding in the inputs. Does not allow aliasing between the inputs+-- and outputs.+foreign import ccall "fmpq_poly.h _fmpq_poly_mullow"+ _fmpq_poly_mullow :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_mullow/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@, truncated to+-- length~\`n\`.+foreign import ccall "fmpq_poly.h fmpq_poly_mullow"+ fmpq_poly_mullow :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_addmul/ /rop/ /op1/ /op2/ +-- +-- Adds the product of @op1@ and @op2@ to @rop@.+foreign import ccall "fmpq_poly.h fmpq_poly_addmul"+ fmpq_poly_addmul :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_submul/ /rop/ /op1/ /op2/ +-- +-- Subtracts the product of @op1@ and @op2@ from @rop@.+foreign import ccall "fmpq_poly.h fmpq_poly_submul"+ fmpq_poly_submul :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- Powering --------------------------------------------------------------------++-- | /_fmpq_poly_pow/ /rpoly/ /rden/ /poly/ /den/ /len/ /e/ +-- +-- Sets @(rpoly, rden)@ to @(poly, den)^e@, assuming @e, len > 0@. Assumes+-- that @rpoly@ is an array of length at least @e * (len - 1) + 1@.+-- Supports aliasing of @(rpoly, den)@ and @(poly, den)@.+foreign import ccall "fmpq_poly.h _fmpq_poly_pow"+ _fmpq_poly_pow :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /fmpq_poly_pow/ /res/ /poly/ /e/ +-- +-- Sets @res@ to @poly^e@, where the only special case \(0^0\) is defined+-- as \(1\).+foreign import ccall "fmpq_poly.h fmpq_poly_pow"+ fmpq_poly_pow :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CULong -> IO ()++-- | /_fmpq_poly_pow_trunc/ /res/ /rden/ /f/ /fden/ /flen/ /exp/ /len/ +-- +-- Sets @(rpoly, rden, len)@ to @(poly, den)^e@ truncated to length @len@,+-- where @len@ is at most @e * (flen - 1) + 1@.+foreign import ccall "fmpq_poly.h _fmpq_poly_pow_trunc"+ _fmpq_poly_pow_trunc :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> CLong -> IO ()++-- | /fmpq_poly_pow_trunc/ /res/ /poly/ /e/ /n/ +-- +-- Sets @res@ to @poly^e@ truncated to length @n@.+foreign import ccall "fmpq_poly.h fmpq_poly_pow_trunc"+ fmpq_poly_pow_trunc :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CULong -> CLong -> IO ()++-- Shifting --------------------------------------------------------------------++-- | /fmpq_poly_shift_left/ /res/ /poly/ /n/ +-- +-- Set @res@ to @poly@ shifted left by \(n\) coefficients. Zero+-- coefficients are inserted.+foreign import ccall "fmpq_poly.h fmpq_poly_shift_left"+ fmpq_poly_shift_left :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_shift_right/ /res/ /poly/ /n/ +-- +-- Set @res@ to @poly@ shifted right by \(n\) coefficients. If \(n\) is+-- equal to or greater than the current length of @poly@, @res@ is set to+-- the zero polynomial.+foreign import ccall "fmpq_poly.h fmpq_poly_shift_right"+ fmpq_poly_shift_right :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- Euclidean division ----------------------------------------------------------++-- | /_fmpq_poly_divrem/ /Q/ /q/ /R/ /r/ /A/ /a/ /lenA/ /B/ /b/ /lenB/ /inv/ +-- +-- Finds the quotient @(Q, q)@ and remainder @(R, r)@ of the Euclidean+-- division of @(A, a)@ by @(B, b)@.+-- +-- Assumes that @lenA >= lenB > 0@. Assumes that \(R\) has space for @lenA@+-- coefficients, although only the bottom @lenB - 1@ will carry meaningful+-- data on exit. Supports no aliasing between the two outputs, or between+-- the inputs and the outputs.+-- +-- An optional precomputed inverse of the leading coefficient of \(B\) from+-- @fmpz_preinvn_init@ can be supplied. Otherwise @inv@ should be @NULL@.+foreign import ccall "fmpq_poly.h _fmpq_poly_divrem"+ _fmpq_poly_divrem :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzPreInvN -> IO ()++-- | /fmpq_poly_divrem/ /Q/ /R/ /poly1/ /poly2/ +-- +-- Finds the quotient \(Q\) and remainder \(R\) of the Euclidean division+-- of @poly1@ by @poly2@.+foreign import ccall "fmpq_poly.h fmpq_poly_divrem"+ fmpq_poly_divrem :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_div/ /Q/ /q/ /A/ /a/ /lenA/ /B/ /b/ /lenB/ /inv/ +-- +-- Finds the quotient @(Q, q)@ of the Euclidean division of @(A, a)@ by+-- @(B, b)@.+-- +-- Assumes that @lenA >= lenB > 0@. Supports no aliasing between the inputs+-- and the outputs.+-- +-- An optional precomputed inverse of the leading coefficient of \(B\) from+-- @fmpz_preinvn_init@ can be supplied. Otherwise @inv@ should be @NULL@.+foreign import ccall "fmpq_poly.h _fmpq_poly_div"+ _fmpq_poly_div :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzPreInvN -> IO ()++-- | /fmpq_poly_div/ /Q/ /poly1/ /poly2/ +-- +-- Finds the quotient \(Q\) and remainder \(R\) of the Euclidean division+-- of @poly1@ by @poly2@.+foreign import ccall "fmpq_poly.h fmpq_poly_div"+ fmpq_poly_div :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_rem/ /R/ /r/ /A/ /a/ /lenA/ /B/ /b/ /lenB/ /inv/ +-- +-- Finds the remainder @(R, r)@ of the Euclidean division of @(A, a)@ by+-- @(B, b)@.+-- +-- Assumes that @lenA >= lenB > 0@. Supports no aliasing between the inputs+-- and the outputs.+-- +-- An optional precomputed inverse of the leading coefficient of \(B\) from+-- @fmpz_preinvn_init@ can be supplied. Otherwise @inv@ should be @NULL@.+foreign import ccall "fmpq_poly.h _fmpq_poly_rem"+ _fmpq_poly_rem :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzPreInvN -> IO ()++-- | /fmpq_poly_rem/ /R/ /poly1/ /poly2/ +-- +-- Finds the remainder \(R\) of the Euclidean division of @poly1@ by+-- @poly2@.+foreign import ccall "fmpq_poly.h fmpq_poly_rem"+ fmpq_poly_rem :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- Powering --------------------------------------------------------------------++-- | /_fmpq_poly_powers_precompute/ /B/ /denB/ /len/ +-- +-- Computes @2*len - 1@ powers of \(x\) modulo the polynomial \(B\) of the+-- given length. This is used as a kind of precomputed inverse in the+-- remainder routine below.+foreign import ccall "fmpq_poly.h _fmpq_poly_powers_precompute"+ _fmpq_poly_powers_precompute :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO (Ptr CFmpqPoly)++-- | /fmpq_poly_powers_precompute/ /pinv/ /poly/ +-- +-- Computes @2*len - 1@ powers of $x$ modulo the polynomial $B$ of the+-- given length. This is used as a kind of precomputed inverse in the+-- remainder routine below.+foreign import ccall "fmpq_poly.h fmpq_poly_powers_precompute"+ fmpq_poly_powers_precompute :: Ptr CFmpqPolyPowersPrecomp -> Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_powers_clear/ /powers/ /len/ +-- +-- Clean up resources used by precomputed powers which have been computed+-- by @_fmpq_poly_powers_precompute@.+foreign import ccall "fmpq_poly.h _fmpq_poly_powers_clear"+ _fmpq_poly_powers_clear :: Ptr CFmpqPoly -> CLong -> IO ()++-- | /fmpq_poly_powers_clear/ /pinv/ +-- +-- Clean up resources used by precomputed powers which have been computed+-- by @fmpq_poly_powers_precompute@.+foreign import ccall "fmpq_poly.h fmpq_poly_powers_clear"+ fmpq_poly_powers_clear :: Ptr CFmpqPolyPowersPrecomp -> IO ()++-- | /_fmpq_poly_rem_powers_precomp/ /A/ /denA/ /m/ /B/ /denB/ /n/ /powers/ +-- +-- Set \(A\) to the remainder of \(A\) divide \(B\) given precomputed+-- powers mod \(B\) provided by @_fmpq_poly_powers_precompute@. No aliasing+-- is allowed.+-- +-- This function is only faster if \(m \leq 2*n - 1\).+-- +-- The output of this function is /not/ canonicalised.+foreign import ccall "fmpq_poly.h _fmpq_poly_rem_powers_precomp"+ _fmpq_poly_rem_powers_precomp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_rem_powers_precomp/ /R/ /A/ /B/ /B_inv/ +-- +-- Set \(R\) to the remainder of \(A\) divide \(B\) given precomputed+-- powers mod \(B\) provided by @fmpq_poly_powers_precompute@.+-- +-- This function is only faster if @A->length \<= 2*B->length - 1@.+-- +-- The output of this function is /not/ canonicalised.+foreign import ccall "fmpq_poly.h fmpq_poly_rem_powers_precomp"+ fmpq_poly_rem_powers_precomp :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPolyPowersPrecomp -> IO ()++-- Divisibility testing --------------------------------------------------------++-- | /_fmpq_poly_divides/ /qpoly/ /qden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ +-- +-- Return \(1\) if @(poly2, den2, len2)@ divides @(poly1, den1, len1)@ and+-- set @(qpoly, qden, len1 - len2 + 1)@ to the quotient. Otherwise return+-- \(0\). Requires that @qpoly@ has space for @len1 - len2 + 1@+-- coefficients and that @len1 >= len2 > 0@.+foreign import ccall "fmpq_poly.h _fmpq_poly_divides"+ _fmpq_poly_divides :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpq_poly_divides/ /q/ /poly1/ /poly2/ +-- +-- Return \(1\) if @poly2@ divides @poly1@ and set @q@ to the quotient.+-- Otherwise return \(0\).+foreign import ccall "fmpq_poly.h fmpq_poly_divides"+ fmpq_poly_divides :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO CInt++-- | /fmpq_poly_remove/ /q/ /poly1/ /poly2/ +-- +-- Sets @q@ to the quotient of @poly1@ by the highest power of @poly2@+-- which divides it, and returns the power. The divisor @poly2@ must not be+-- constant or an exception is raised.+foreign import ccall "fmpq_poly.h fmpq_poly_remove"+ fmpq_poly_remove :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO CLong++-- Power series division -------------------------------------------------------++-- | /_fmpq_poly_inv_series_newton/ /rpoly/ /rden/ /poly/ /den/ /len/ /n/ +-- +-- Computes the first \(n\) terms of the inverse power series of+-- @(poly, den, len)@ using Newton iteration.+-- +-- The result is produced in canonical form.+-- +-- Assumes that \(n \geq 1\) and that @poly@ has non-zero constant term.+-- Does not support aliasing.+foreign import ccall "fmpq_poly.h _fmpq_poly_inv_series_newton"+ _fmpq_poly_inv_series_newton :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_inv_series_newton/ /res/ /poly/ /n/ +-- +-- Computes the first \(n\) terms of the inverse power series of @poly@+-- using Newton iteration, assuming that @poly@ has non-zero constant term+-- and \(n \geq 1\).+foreign import ccall "fmpq_poly.h fmpq_poly_inv_series_newton"+ fmpq_poly_inv_series_newton :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_inv_series/ /rpoly/ /rden/ /poly/ /den/ /n/ +-- +-- Computes the first \(n\) terms of the inverse power series of+-- @(poly, den, len)@.+-- +-- The result is produced in canonical form.+-- +-- Assumes that \(n \geq 1\) and that @poly@ has non-zero constant term.+-- Does not support aliasing.+foreign import ccall "fmpq_poly.h _fmpq_poly_inv_series"+ _fmpq_poly_inv_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_inv_series/ /res/ /poly/ /n/ +-- +-- Computes the first \(n\) terms of the inverse power series of @poly@,+-- assuming that @poly@ has non-zero constant term and \(n \geq 1\).+foreign import ccall "fmpq_poly.h fmpq_poly_inv_series"+ fmpq_poly_inv_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_div_series/ /Q/ /denQ/ /A/ /denA/ /lenA/ /B/ /denB/ /lenB/ /n/ +-- +-- Divides @(A, denA, lenA)@ by @(B, denB, lenB)@ as power series over+-- \(\mathbb{Q}\), assuming \(B\) has non-zero constant term and that all+-- lengths are positive.+-- +-- Aliasing is not supported.+-- +-- This function ensures that the numerator and denominator are coprime on+-- exit.+foreign import ccall "fmpq_poly.h _fmpq_poly_div_series"+ _fmpq_poly_div_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_div_series/ /Q/ /A/ /B/ /n/ +-- +-- Performs power series division in \(\mathbb{Q}[[x]] / (x^n)\). The+-- function considers the polynomials \(A\) and \(B\) as power series of+-- length~\`n\` starting with the constant terms. The function assumes that+-- \(B\) has non-zero constant term and \(n \geq 1\).+foreign import ccall "fmpq_poly.h fmpq_poly_div_series"+ fmpq_poly_div_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- Greatest common divisor -----------------------------------------------------++-- | /_fmpq_poly_gcd/ /G/ /denG/ /A/ /lenA/ /B/ /lenB/ +-- +-- Computes the monic greatest common divisor \(G\) of \(A\) and \(B\).+-- +-- Assumes that \(G\) has space for \(\operatorname{len}(B)\) coefficients,+-- where \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\).+-- +-- Aliasing between the output and input arguments is not supported.+-- +-- Does not support zero-padding.+foreign import ccall "fmpq_poly.h _fmpq_poly_gcd"+ _fmpq_poly_gcd :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_gcd/ /G/ /A/ /B/ +-- +-- Computes the monic greatest common divisor \(G\) of \(A\) and \(B\).+-- +-- In the the special case when \(A = B = 0\), sets \(G = 0\).+foreign import ccall "fmpq_poly.h fmpq_poly_gcd"+ fmpq_poly_gcd :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_xgcd/ /G/ /denG/ /S/ /denS/ /T/ /denT/ /A/ /denA/ /lenA/ /B/ /denB/ /lenB/ +-- +-- Computes polynomials \(G\), \(S\), and \(T\) such that+-- \(G = \gcd(A, B) = S A + T B\), where \(G\) is the monic greatest common+-- divisor of \(A\) and \(B\).+-- +-- Assumes that \(G\), \(S\), and \(T\) have space for+-- \(\operatorname{len}(B)\), \(\operatorname{len}(B)\), and+-- \(\operatorname{len}(A)\) coefficients, respectively, where it is also+-- assumed that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\).+-- +-- Does not support zero padding of the input arguments.+foreign import ccall "fmpq_poly.h _fmpq_poly_xgcd"+ _fmpq_poly_xgcd :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_xgcd/ /G/ /S/ /T/ /A/ /B/ +-- +-- Computes polynomials \(G\), \(S\), and \(T\) such that+-- \(G = \gcd(A, B) = S A + T B\), where \(G\) is the monic greatest common+-- divisor of \(A\) and \(B\).+-- +-- Corner cases are handled as follows. If \(A = B = 0\), returns+-- \(G = S = T = 0\). If \(A \neq 0\), \(B = 0\), returns the suitable+-- scalar multiple of \(G = A\), \(S = 1\), and \(T = 0\). The case when+-- \(A = 0\), \(B \neq 0\) is handled similarly.+foreign import ccall "fmpq_poly.h fmpq_poly_xgcd"+ fmpq_poly_xgcd :: Ptr CFmpqPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_lcm/ /L/ /denL/ /A/ /lenA/ /B/ /lenB/ +-- +-- Computes the monic least common multiple \(L\) of \(A\) and \(B\).+-- +-- Assumes that \(L\) has space for+-- \(\operatorname{len}(A) + \operatorname{len}(B) - 1\) coefficients,+-- where \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\).+-- +-- Aliasing between the output and input arguments is not supported.+-- +-- Does not support zero-padding.+foreign import ccall "fmpq_poly.h _fmpq_poly_lcm"+ _fmpq_poly_lcm :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_lcm/ /L/ /A/ /B/ +-- +-- Computes the monic least common multiple \(L\) of \(A\) and \(B\).+-- +-- In the special case when \(A = B = 0\), sets \(L = 0\).+foreign import ccall "fmpq_poly.h fmpq_poly_lcm"+ fmpq_poly_lcm :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_resultant/ /rnum/ /rden/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ +-- +-- Sets @(rnum, rden)@ to the resultant of the two input polynomials.+-- +-- Assumes that @len1 >= len2 > 0@. Does not support zero-padding of the+-- input polynomials. Does not support aliasing of the input and output+-- arguments.+foreign import ccall "fmpq_poly.h _fmpq_poly_resultant"+ _fmpq_poly_resultant :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_resultant/ /r/ /f/ /g/ +-- +-- Returns the resultant of \(f\) and \(g\).+-- +-- Enumerating the roots of \(f\) and \(g\) over \(\bar{\mathbf{Q}}\) as+-- \(r_1, \dotsc, r_m\) and \(s_1, \dotsc, s_n\), respectively, and letting+-- \(x\) and \(y\) denote the leading coefficients, the resultant is+-- defined as+-- +-- \[`\]+-- \[x^{\deg(f)} y^{\deg(g)} \prod_{1 \leq i, j \leq n} (r_i - s_j).\]+-- +-- We handle special cases as follows: if one of the polynomials is zero,+-- the resultant is zero. Note that otherwise if one of the polynomials is+-- constant, the last term in the above expression is the empty product.+foreign import ccall "fmpq_poly.h fmpq_poly_resultant"+ fmpq_poly_resultant :: Ptr CFmpq -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_resultant_div/ /r/ /f/ /g/ /div/ /nbits/ +-- +-- Returns the resultant of \(f\) and \(g\) divided by @div@ under the+-- assumption that the result has at most @nbits@ bits. The result must be+-- an integer.+foreign import ccall "fmpq_poly.h fmpq_poly_resultant_div"+ fmpq_poly_resultant_div :: Ptr CFmpq -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpz -> CLong -> IO ()++-- Derivative and integral -----------------------------------------------------++-- | /_fmpq_poly_derivative/ /rpoly/ /rden/ /poly/ /den/ /len/ +-- +-- Sets @(rpoly, rden, len - 1)@ to the derivative of @(poly, den, len)@.+-- Does nothing if @len \<= 1@. Supports aliasing between the two+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_derivative"+ _fmpq_poly_derivative :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_derivative/ /res/ /poly/ +-- +-- Sets @res@ to the derivative of @poly@.+foreign import ccall "fmpq_poly.h fmpq_poly_derivative"+ fmpq_poly_derivative :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_nth_derivative/ /rpoly/ /rden/ /poly/ /den/ /n/ /len/ +-- +-- Sets @(rpoly, rden, len - n)@ to the nth derivative of+-- @(poly, den, len)@. Does nothing if @len \<= n@. Supports aliasing+-- between the two polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_nth_derivative"+ _fmpq_poly_nth_derivative :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CULong -> CLong -> IO ()++-- | /fmpq_poly_nth_derivative/ /res/ /poly/ /n/ +-- +-- Sets @res@ to the nth derivative of @poly@.+foreign import ccall "fmpq_poly.h fmpq_poly_nth_derivative"+ fmpq_poly_nth_derivative :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CULong -> IO ()++-- | /_fmpq_poly_integral/ /rpoly/ /rden/ /poly/ /den/ /len/ +-- +-- Sets @(rpoly, rden, len)@ to the integral of @(poly, den, len - 1)@.+-- Assumes @len >= 0@. Supports aliasing between the two polynomials. The+-- output will be in canonical form if the input is in canonical form.+foreign import ccall "fmpq_poly.h _fmpq_poly_integral"+ _fmpq_poly_integral :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_integral/ /res/ /poly/ +-- +-- Sets @res@ to the integral of @poly@. The constant term is set to zero.+-- In particular, the integral of the zero polynomial is the zero+-- polynomial.+foreign import ccall "fmpq_poly.h fmpq_poly_integral"+ fmpq_poly_integral :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- Square roots ----------------------------------------------------------------++-- | /_fmpq_poly_sqrt_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the square root of+-- @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 1. Does not support aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_sqrt_series"+ _fmpq_poly_sqrt_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_sqrt_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the square root of @f@ to order+-- @n > 1@. Requires @f@ to have constant term 1.+foreign import ccall "fmpq_poly.h fmpq_poly_sqrt_series"+ fmpq_poly_sqrt_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_invsqrt_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the inverse square root+-- of @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 1. Does not support aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_invsqrt_series"+ _fmpq_poly_invsqrt_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_invsqrt_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the inverse square root of @f@ to+-- order @n > 0@. Requires @f@ to have constant term 1.+foreign import ccall "fmpq_poly.h fmpq_poly_invsqrt_series"+ fmpq_poly_invsqrt_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- Power sums ------------------------------------------------------------------++-- | /_fmpq_poly_power_sums/ /res/ /rden/ /poly/ /len/ /n/ +-- +-- Compute the (truncated) power sums series of the polynomial @(poly,len)@+-- up to length \(n\) using Newton identities.+foreign import ccall "fmpq_poly.h _fmpq_poly_power_sums"+ _fmpq_poly_power_sums :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_power_sums/ /res/ /poly/ /n/ +-- +-- Compute the (truncated) power sum series of the monic polynomial @poly@+-- up to length \(n\) using Newton identities. That is the power series+-- whose coefficient of degree \(i\) is the sum of the \(i\)-th power of+-- all (complex) roots of the polynomial @poly@.+foreign import ccall "fmpq_poly.h fmpq_poly_power_sums"+ fmpq_poly_power_sums :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_power_sums_to_poly/ /res/ /poly/ /den/ /len/ +-- +-- Compute an integer polynomial given by its power sums series+-- @(poly,den,len)@.+foreign import ccall "fmpq_poly.h _fmpq_poly_power_sums_to_poly"+ _fmpq_poly_power_sums_to_poly :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_power_sums_to_fmpz_poly/ /res/ /Q/ +-- +-- Compute the integer polynomial with content one and positive leading+-- coefficient given by its power sums series @Q@.+foreign import ccall "fmpq_poly.h fmpq_poly_power_sums_to_fmpz_poly"+ fmpq_poly_power_sums_to_fmpz_poly :: Ptr CFmpzPoly -> Ptr CFmpqPoly -> IO ()++-- | /fmpq_poly_power_sums_to_poly/ /res/ /Q/ +-- +-- Compute the monic polynomial from its power sums series @Q@.+foreign import ccall "fmpq_poly.h fmpq_poly_power_sums_to_poly"+ fmpq_poly_power_sums_to_poly :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- Transcendental functions ----------------------------------------------------++-- | /_fmpq_poly_log_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the logarithm of+-- @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 1. Supports aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_log_series"+ _fmpq_poly_log_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_log_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the logarithm of @f@ to order+-- @n > 0@. Requires @f@ to have constant term 1.+foreign import ccall "fmpq_poly.h fmpq_poly_log_series"+ fmpq_poly_log_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_exp_series/ /g/ /gden/ /h/ /hden/ /hlen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the exponential function+-- of @(h, hden, hlen)@. Assumes @n > 0, hlen > 0@ and that+-- @(h, hden, hlen)@ has constant term 0. Supports aliasing between the+-- input and output polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_exp_series"+ _fmpq_poly_exp_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_exp_series/ /res/ /h/ /n/ +-- +-- Sets @res@ to the series expansion of the exponential function of @h@ to+-- order @n > 0@. Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_exp_series"+ fmpq_poly_exp_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_exp_expinv_series/ /res1/ /res1den/ /res2/ /res2den/ /h/ /hden/ /hlen/ /n/ +-- +-- The same as @fmpq_poly_exp_series@, but simultaneously computes the+-- exponential (in @res1@, @res1den@) and its multiplicative inverse (in+-- @res2@, @res2den@). Supports aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_exp_expinv_series"+ _fmpq_poly_exp_expinv_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_exp_expinv_series/ /res1/ /res2/ /h/ /n/ +-- +-- The same as @fmpq_poly_exp_series@, but simultaneously computes the+-- exponential (in @res1@) and its multiplicative inverse (in @res2@).+foreign import ccall "fmpq_poly.h fmpq_poly_exp_expinv_series"+ fmpq_poly_exp_expinv_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_atan_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the inverse tangent of+-- @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 0. Supports aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_atan_series"+ _fmpq_poly_atan_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_atan_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the inverse tangent of @f@ to+-- order @n > 0@. Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_atan_series"+ fmpq_poly_atan_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_atanh_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the inverse hyperbolic+-- tangent of @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@+-- has constant term 0. Supports aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_atanh_series"+ _fmpq_poly_atanh_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_atanh_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the inverse hyperbolic tangent of+-- @f@ to order @n > 0@. Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_atanh_series"+ fmpq_poly_atanh_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_asin_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the inverse sine of+-- @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 0. Supports aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_asin_series"+ _fmpq_poly_asin_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_asin_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the inverse sine of @f@ to order+-- @n > 0@. Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_asin_series"+ fmpq_poly_asin_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_asinh_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the inverse hyperbolic+-- sine of @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@+-- has constant term 0. Supports aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_asinh_series"+ _fmpq_poly_asinh_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_asinh_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the inverse hyperbolic sine of @f@+-- to order @n > 0@. Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_asinh_series"+ fmpq_poly_asinh_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_tan_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the tangent function of+-- @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 0. Does not support aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_tan_series"+ _fmpq_poly_tan_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_tan_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the tangent function of @f@ to+-- order @n > 0@. Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_tan_series"+ fmpq_poly_tan_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_sin_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the sine of+-- @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 0. Supports aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_sin_series"+ _fmpq_poly_sin_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_sin_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the sine of @f@ to order @n > 0@.+-- Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_sin_series"+ fmpq_poly_sin_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_cos_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the cosine of+-- @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 0. Supports aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_cos_series"+ _fmpq_poly_cos_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_cos_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the cosine of @f@ to order+-- @n > 0@. Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_cos_series"+ fmpq_poly_cos_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_sin_cos_series/ /s/ /sden/ /c/ /cden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(s, sden, n)@ to the series expansion of the sine of+-- @(f, fden, flen)@, and @(c, cden, n)@ to the series expansion of the+-- cosine. Assumes @n > 0@ and that @(f, fden, flen)@ has constant term 0.+-- Supports aliasing between the input and output polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_sin_cos_series"+ _fmpq_poly_sin_cos_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_sin_cos_series/ /res1/ /res2/ /f/ /n/ +-- +-- Sets @res1@ to the series expansion of the sine of @f@ to order @n > 0@,+-- and @res2@ to the series expansion of the cosine. Requires @f@ to have+-- constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_sin_cos_series"+ fmpq_poly_sin_cos_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_sinh_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the hyperbolic sine of+-- @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 0. Does not support aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_sinh_series"+ _fmpq_poly_sinh_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_sinh_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the hyperbolic sine of @f@ to+-- order @n > 0@. Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_sinh_series"+ fmpq_poly_sinh_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_cosh_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the hyperbolic cosine of+-- @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 0. Does not support aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_cosh_series"+ _fmpq_poly_cosh_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_cosh_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the hyperbolic cosine of @f@ to+-- order @n > 0@. Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_cosh_series"+ fmpq_poly_cosh_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_sinh_cosh_series/ /s/ /sden/ /c/ /cden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(s, sden, n)@ to the series expansion of the hyperbolic sine of+-- @(f, fden, flen)@, and @(c, cden, n)@ to the series expansion of the+-- hyperbolic cosine. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 0. Supports aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_sinh_cosh_series"+ _fmpq_poly_sinh_cosh_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_sinh_cosh_series/ /res1/ /res2/ /f/ /n/ +-- +-- Sets @res1@ to the series expansion of the hyperbolic sine of @f@ to+-- order @n > 0@, and @res2@ to the series expansion of the hyperbolic+-- cosine. Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_sinh_cosh_series"+ fmpq_poly_sinh_cosh_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_tanh_series/ /g/ /gden/ /f/ /fden/ /flen/ /n/ +-- +-- Sets @(g, gden, n)@ to the series expansion of the hyperbolic tangent of+-- @(f, fden, flen)@. Assumes @n > 0@ and that @(f, fden, flen)@ has+-- constant term 0. Does not support aliasing between the input and output+-- polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_tanh_series"+ _fmpq_poly_tanh_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_tanh_series/ /res/ /f/ /n/ +-- +-- Sets @res@ to the series expansion of the hyperbolic tangent of @f@ to+-- order @n > 0@. Requires @f@ to have constant term 0.+foreign import ccall "fmpq_poly.h fmpq_poly_tanh_series"+ fmpq_poly_tanh_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- Orthogonal polynomials ------------------------------------------------------++-- | /_fmpq_poly_legendre_p/ /coeffs/ /den/ /n/ +-- +-- Sets @coeffs@ to the coefficient array of the Legendre polynomial+-- \(P_n(x)\), defined by+-- \((n+1) P_{n+1}(x) = (2n+1) x P_n(x) - n P_{n-1}(x)\), for \(n\ge0\).+-- Sets @den@ to the overall denominator. The coefficients are calculated+-- using a hypergeometric recurrence. The length of the array will be+-- @n+1@. To improve performance, the common denominator is computed in one+-- step and the coefficients are evaluated using integer arithmetic. The+-- denominator is given by+-- \(\gcd(n!,2^n) = 2^{\lfloor n/2 \rfloor + \lfloor n/4 \rfloor + \ldots}.\)+-- See @fmpz_poly@ for the shifted Legendre polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_legendre_p"+ _fmpq_poly_legendre_p :: Ptr CFmpq -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpq_poly_legendre_p/ /poly/ /n/ +-- +-- Sets @poly@ to the Legendre polynomial \(P_n(x)\), defined by+-- \((n+1) P_{n+1}(x) = (2n+1) x P_n(x) - n P_{n-1}(x)\), for \(n\ge0\).+-- The coefficients are calculated using a hypergeometric recurrence. To+-- improve performance, the common denominator is computed in one step and+-- the coefficients are evaluated using integer arithmetic. The denominator+-- is given by+-- \(\gcd(n!,2^n) = 2^{\lfloor n/2 \rfloor + \lfloor n/4 \rfloor + \ldots}.\)+-- See @fmpz_poly@ for the shifted Legendre polynomials.+foreign import ccall "fmpq_poly.h fmpq_poly_legendre_p"+ fmpq_poly_legendre_p :: Ptr CFmpqPoly -> CULong -> IO ()++-- | /_fmpq_poly_laguerre_l/ /coeffs/ /den/ /n/ +-- +-- Sets @coeffs@ to the coefficient array of the Laguerre polynomial+-- \(L_n(x)\), defined by+-- \((n+1) L_{n+1}(x) = (2n+1-x) L_n(x) - n L_{n-1}(x)\), for \(n\ge0\).+-- Sets @den@ to the overall denominator. The coefficients are calculated+-- using a hypergeometric recurrence. The length of the array will be+-- @n+1@.+foreign import ccall "fmpq_poly.h _fmpq_poly_laguerre_l"+ _fmpq_poly_laguerre_l :: Ptr CFmpq -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpq_poly_laguerre_l/ /poly/ /n/ +-- +-- Sets @poly@ to the Laguerre polynomial \(L_n(x)\), defined by+-- \((n+1) L_{n+1}(x) = (2n+1-x) L_n(x) - n L_{n-1}(x)\), for \(n\ge0\).+-- The coefficients are calculated using a hypergeometric recurrence.+foreign import ccall "fmpq_poly.h fmpq_poly_laguerre_l"+ fmpq_poly_laguerre_l :: Ptr CFmpqPoly -> CULong -> IO ()++-- | /_fmpq_poly_gegenbauer_c/ /coeffs/ /den/ /n/ /a/ +-- +-- Sets @coeffs@ to the coefficient array of the Gegenbauer+-- (ultraspherical) polynomial+-- \(C^{(\alpha)}_n(x) = \frac{(2\alpha)_n}{n!}{}_2F_1\left(-n,2\alpha+n;+-- \alpha+\frac12;\frac{1-x}{2}\right)\), for integer \(n\ge0\) and+-- rational \(\alpha>0\). Sets @den@ to the overall denominator. The+-- coefficients are calculated using a hypergeometric recurrence.+foreign import ccall "fmpq_poly.h _fmpq_poly_gegenbauer_c"+ _fmpq_poly_gegenbauer_c :: Ptr CFmpq -> Ptr CFmpz -> CULong -> Ptr CFmpq -> IO ()++-- | /fmpq_poly_gegenbauer_c/ /poly/ /n/ /a/ +-- +-- Sets @poly@ to the Gegenbauer (ultraspherical) polynomial+-- \(C^{(\alpha)}_n(x) = \frac{(2\alpha)_n}{n!}{}_2F_1\left(-n,2\alpha+n;+-- \alpha+\frac12;\frac{1-x}{2}\right)\), for integer \(n\ge0\) and+-- rational \(\alpha>0\). The coefficients are calculated using a+-- hypergeometric recurrence.+foreign import ccall "fmpq_poly.h fmpq_poly_gegenbauer_c"+ fmpq_poly_gegenbauer_c :: Ptr CFmpqPoly -> CULong -> Ptr CFmpq -> IO ()++foreign import ccall "fmpq_poly.h _fmpq_poly_monien_h"+ _fmpq_poly_monien_h :: Ptr CFmpz -> Ptr CFmpz -> Ptr CULong -> IO ()++foreign import ccall "fmpq_poly.h fmpq_poly_monien_h"+ fmpq_poly_monien_h :: Ptr CFmpqPoly -> CULong -> IO ()++-- Evaluation ------------------------------------------------------------------++-- | /_fmpq_poly_evaluate_fmpz/ /rnum/ /rden/ /poly/ /den/ /len/ /a/ +-- +-- Evaluates the polynomial @(poly, den, len)@ at the integer \(a\) and+-- sets @(rnum, rden)@ to the result in lowest terms.+foreign import ccall "fmpq_poly.h _fmpq_poly_evaluate_fmpz"+ _fmpq_poly_evaluate_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpq_poly_evaluate_fmpz/ /res/ /poly/ /a/ +-- +-- Evaluates the polynomial @poly@ at the integer \(a\) and sets @res@ to+-- the result.+foreign import ccall "fmpq_poly.h fmpq_poly_evaluate_fmpz"+ fmpq_poly_evaluate_fmpz :: Ptr CFmpq -> Ptr CFmpqPoly -> Ptr CFmpz -> IO ()++-- | /_fmpq_poly_evaluate_fmpq/ /rnum/ /rden/ /poly/ /den/ /len/ /anum/ /aden/ +-- +-- Evaluates the polynomial @(poly, den, len)@ at the rational+-- @(anum, aden)@ and sets @(rnum, rden)@ to the result in lowest terms.+-- Aliasing between @(rnum, rden)@ and @(anum, aden)@ is not supported.+foreign import ccall "fmpq_poly.h _fmpq_poly_evaluate_fmpq"+ _fmpq_poly_evaluate_fmpq :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpq_poly_evaluate_fmpq/ /res/ /poly/ /a/ +-- +-- Evaluates the polynomial @poly@ at the rational \(a\) and sets @res@ to+-- the result.+foreign import ccall "fmpq_poly.h fmpq_poly_evaluate_fmpq"+ fmpq_poly_evaluate_fmpq :: Ptr CFmpq -> Ptr CFmpqPoly -> Ptr CFmpq -> IO ()++-- -- | /fmpq_poly_evaluate_mpz/ /res/ /poly/ /a/ +-- -- +-- -- Evaluates the polynomial @poly@ at the integer \(a\) of type @mpz@ and+-- -- sets @res@ to the result.+-- foreign import ccall "fmpq_poly.h fmpq_poly_evaluate_mpz"+-- fmpq_poly_evaluate_mpz :: Ptr CMpq -> Ptr CFmpqPoly -> Ptr CMpz -> IO ()++-- -- | /fmpq_poly_evaluate_mpq/ /res/ /poly/ /a/ +-- -- +-- -- Evaluates the polynomial @poly@ at the rational \(a\) of type @mpq@ and+-- -- sets @res@ to the result.+-- foreign import ccall "fmpq_poly.h fmpq_poly_evaluate_mpq"+-- fmpq_poly_evaluate_mpq :: Ptr CMpq -> Ptr CFmpqPoly -> Ptr CMpq -> IO ()++-- Interpolation ---------------------------------------------------------------++-- | /_fmpq_poly_interpolate_fmpz_vec/ /poly/ /den/ /xs/ /ys/ /n/ +-- +-- Sets @poly@ \/ @den@ to the unique interpolating polynomial of degree at+-- most \(n - 1\) satisfying \(f(x_i) = y_i\) for every pair \(x_i, y_i\)+-- in @xs@ and @ys@.+-- +-- The vector @poly@ must have room for @n+1@ coefficients, even if the+-- interpolating polynomial is shorter. Aliasing of @poly@ or @den@ with+-- any other argument is not allowed.+-- +-- It is assumed that the \(x\) values are distinct.+-- +-- This function uses a simple \(O(n^2)\) implementation of Lagrange+-- interpolation, clearing denominators to avoid working with fractions. It+-- is currently not designed to be efficient for large \(n\).+foreign import ccall "fmpq_poly.h _fmpq_poly_interpolate_fmpz_vec"+ _fmpq_poly_interpolate_fmpz_vec :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_interpolate_fmpz_vec/ /poly/ /xs/ /ys/ /n/ +-- +-- Sets @poly@ to the unique interpolating polynomial of degree at most+-- \(n - 1\) satisfying \(f(x_i) = y_i\) for every pair \(x_i, y_i\) in+-- @xs@ and @ys@. It is assumed that the \(x\) values are distinct.+foreign import ccall "fmpq_poly.h fmpq_poly_interpolate_fmpz_vec"+ fmpq_poly_interpolate_fmpz_vec :: Ptr CFmpqPoly -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- Composition -----------------------------------------------------------------++-- | /_fmpq_poly_compose/ /res/ /den/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ +-- +-- Sets @(res, den)@ to the composition of @(poly1, den1, len1)@ and+-- @(poly2, den2, len2)@, assuming @len1, len2 > 0@.+-- +-- Assumes that @res@ has space for @(len1 - 1) * (len2 - 1) + 1@+-- coefficients. Does not support aliasing.+foreign import ccall "fmpq_poly.h _fmpq_poly_compose"+ _fmpq_poly_compose :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_compose/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@.+foreign import ccall "fmpq_poly.h fmpq_poly_compose"+ fmpq_poly_compose :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_rescale/ /res/ /denr/ /poly/ /den/ /len/ /anum/ /aden/ +-- +-- Sets @(res, denr, len)@ to @(poly, den, len)@ with the indeterminate+-- rescaled by @(anum, aden)@.+-- +-- Assumes that @len > 0@ and that @(anum, aden)@ is non-zero and in lowest+-- terms. Supports aliasing between @(res, denr, len)@ and+-- @(poly, den, len)@.+foreign import ccall "fmpq_poly.h _fmpq_poly_rescale"+ _fmpq_poly_rescale :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpq_poly_rescale/ /res/ /poly/ /a/ +-- +-- Sets @res@ to @poly@ with the indeterminate rescaled by \(a\).+foreign import ccall "fmpq_poly.h fmpq_poly_rescale"+ fmpq_poly_rescale :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpq -> IO ()++-- Power series composition ----------------------------------------------------++-- | /_fmpq_poly_compose_series_horner/ /res/ /den/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ /n/ +-- +-- Sets @(res, den, n)@ to the composition of @(poly1, den1, len1)@ and+-- @(poly2, den2, len2)@ modulo \(x^n\), where the constant term of @poly2@+-- is required to be zero.+-- +-- Assumes that @len1, len2, n > 0@, that @len1, len2 \<= n@, that+-- @(len1-1) * (len2-1) + 1 \<= n@, and that @res@ has space for @n@+-- coefficients. Does not support aliasing between any of the inputs and+-- the output.+-- +-- This implementation uses the Horner scheme. The default @fmpz_poly@+-- composition algorithm is automatically used when the composition can be+-- performed over the integers.+foreign import ccall "fmpq_poly.h _fmpq_poly_compose_series_horner"+ _fmpq_poly_compose_series_horner :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_compose_series_horner/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@ modulo \(x^n\),+-- where the constant term of @poly2@ is required to be zero.+-- +-- This implementation uses the Horner scheme. The default @fmpz_poly@+-- composition algorithm is automatically used when the composition can be+-- performed over the integers.+foreign import ccall "fmpq_poly.h fmpq_poly_compose_series_horner"+ fmpq_poly_compose_series_horner :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_compose_series_brent_kung/ /res/ /den/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ /n/ +-- +-- Sets @(res, den, n)@ to the composition of @(poly1, den1, len1)@ and+-- @(poly2, den2, len2)@ modulo \(x^n\), where the constant term of @poly2@+-- is required to be zero.+-- +-- Assumes that @len1, len2, n > 0@, that @len1, len2 \<= n@, that+-- @(len1-1) * (len2-1) + 1 \<= n@, and that @res@ has space for @n@+-- coefficients. Does not support aliasing between any of the inputs and+-- the output.+-- +-- This implementation uses Brent-Kung algorithm 2.1 < [BrentKung1978]>.+-- The default @fmpz_poly@ composition algorithm is automatically used when+-- the composition can be performed over the integers.+foreign import ccall "fmpq_poly.h _fmpq_poly_compose_series_brent_kung"+ _fmpq_poly_compose_series_brent_kung :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_compose_series_brent_kung/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@ modulo \(x^n\),+-- where the constant term of @poly2@ is required to be zero.+-- +-- This implementation uses Brent-Kung algorithm 2.1 < [BrentKung1978]>.+-- The default @fmpz_poly@ composition algorithm is automatically used when+-- the composition can be performed over the integers.+foreign import ccall "fmpq_poly.h fmpq_poly_compose_series_brent_kung"+ fmpq_poly_compose_series_brent_kung :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_compose_series/ /res/ /den/ /poly1/ /den1/ /len1/ /poly2/ /den2/ /len2/ /n/ +-- +-- Sets @(res, den, n)@ to the composition of @(poly1, den1, len1)@ and+-- @(poly2, den2, len2)@ modulo \(x^n\), where the constant term of @poly2@+-- is required to be zero.+-- +-- Assumes that @len1, len2, n > 0@, that @len1, len2 \<= n@, that+-- @(len1-1) * (len2-1) + 1 \<= n@, and that @res@ has space for @n@+-- coefficients. Does not support aliasing between any of the inputs and+-- the output.+-- +-- This implementation automatically switches between the Horner scheme and+-- Brent-Kung algorithm 2.1 depending on the size of the inputs. The+-- default @fmpz_poly@ composition algorithm is automatically used when the+-- composition can be performed over the integers.+foreign import ccall "fmpq_poly.h _fmpq_poly_compose_series"+ _fmpq_poly_compose_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_compose_series/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@ modulo \(x^n\),+-- where the constant term of @poly2@ is required to be zero.+-- +-- This implementation automatically switches between the Horner scheme and+-- Brent-Kung algorithm 2.1 depending on the size of the inputs. The+-- default @fmpz_poly@ composition algorithm is automatically used when the+-- composition can be performed over the integers.+foreign import ccall "fmpq_poly.h fmpq_poly_compose_series"+ fmpq_poly_compose_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- Power series reversion ------------------------------------------------------++-- | /_fmpq_poly_revert_series_lagrange/ /res/ /den/ /poly1/ /den1/ /len1/ /n/ +-- +-- Sets @(res, den)@ to the power series reversion of @(poly1, den1, len1)@+-- modulo \(x^n\).+-- +-- The constant term of @poly2@ is required to be zero and the linear term+-- is required to be nonzero. Assumes that \(n > 0\). Does not support+-- aliasing between any of the inputs and the output.+-- +-- This implementation uses the Lagrange inversion formula. The default+-- @fmpz_poly@ reversion algorithm is automatically used when the reversion+-- can be performed over the integers.+foreign import ccall "fmpq_poly.h _fmpq_poly_revert_series_lagrange"+ _fmpq_poly_revert_series_lagrange :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_revert_series_lagrange/ /res/ /poly/ /n/ +-- +-- Sets @res@ to the power series reversion of @poly1@ modulo \(x^n\). The+-- constant term of @poly2@ is required to be zero and the linear term is+-- required to be nonzero.+-- +-- This implementation uses the Lagrange inversion formula. The default+-- @fmpz_poly@ reversion algorithm is automatically used when the reversion+-- can be performed over the integers.+foreign import ccall "fmpq_poly.h fmpq_poly_revert_series_lagrange"+ fmpq_poly_revert_series_lagrange :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_revert_series_lagrange_fast/ /res/ /den/ /poly1/ /den1/ /len1/ /n/ +-- +-- Sets @(res, den)@ to the power series reversion of @(poly1, den1, len1)@+-- modulo \(x^n\).+-- +-- The constant term of @poly2@ is required to be zero and the linear term+-- is required to be nonzero. Assumes that \(n > 0\). Does not support+-- aliasing between any of the inputs and the output.+-- +-- This implementation uses a reduced-complexity implementation of the+-- Lagrange inversion formula. The default @fmpz_poly@ reversion algorithm+-- is automatically used when the reversion can be performed over the+-- integers.+foreign import ccall "fmpq_poly.h _fmpq_poly_revert_series_lagrange_fast"+ _fmpq_poly_revert_series_lagrange_fast :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_revert_series_lagrange_fast/ /res/ /poly/ /n/ +-- +-- Sets @res@ to the power series reversion of @poly1@ modulo \(x^n\). The+-- constant term of @poly2@ is required to be zero and the linear term is+-- required to be nonzero.+-- +-- This implementation uses a reduced-complexity implementation of the+-- Lagrange inversion formula. The default @fmpz_poly@ reversion algorithm+-- is automatically used when the reversion can be performed over the+-- integers.+foreign import ccall "fmpq_poly.h fmpq_poly_revert_series_lagrange_fast"+ fmpq_poly_revert_series_lagrange_fast :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_revert_series_newton/ /res/ /den/ /poly1/ /den1/ /len1/ /n/ +-- +-- Sets @(res, den)@ to the power series reversion of @(poly1, den1, len1)@+-- modulo \(x^n\).+-- +-- The constant term of @poly2@ is required to be zero and the linear term+-- is required to be nonzero. Assumes that \(n > 0\). Does not support+-- aliasing between any of the inputs and the output.+-- +-- This implementation uses Newton iteration. The default @fmpz_poly@+-- reversion algorithm is automatically used when the reversion can be+-- performed over the integers.+foreign import ccall "fmpq_poly.h _fmpq_poly_revert_series_newton"+ _fmpq_poly_revert_series_newton :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_revert_series_newton/ /res/ /poly/ /n/ +-- +-- Sets @res@ to the power series reversion of @poly1@ modulo \(x^n\). The+-- constant term of @poly2@ is required to be zero and the linear term is+-- required to be nonzero.+-- +-- This implementation uses Newton iteration. The default @fmpz_poly@+-- reversion algorithm is automatically used when the reversion can be+-- performed over the integers.+foreign import ccall "fmpq_poly.h fmpq_poly_revert_series_newton"+ fmpq_poly_revert_series_newton :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- | /_fmpq_poly_revert_series/ /res/ /den/ /poly1/ /den1/ /len1/ /n/ +-- +-- Sets @(res, den)@ to the power series reversion of @(poly1, den1, len1)@+-- modulo \(x^n\).+-- +-- The constant term of @poly2@ is required to be zero and the linear term+-- is required to be nonzero. Assumes that \(n > 0\). Does not support+-- aliasing between any of the inputs and the output.+-- +-- This implementation defaults to using Newton iteration. The default+-- @fmpz_poly@ reversion algorithm is automatically used when the reversion+-- can be performed over the integers.+foreign import ccall "fmpq_poly.h _fmpq_poly_revert_series"+ _fmpq_poly_revert_series :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpq_poly_revert_series/ /res/ /poly/ /n/ +-- +-- Sets @res@ to the power series reversion of @poly1@ modulo \(x^n\). The+-- constant term of @poly2@ is required to be zero and the linear term is+-- required to be nonzero.+-- +-- This implementation defaults to using Newton iteration. The default+-- @fmpz_poly@ reversion algorithm is automatically used when the reversion+-- can be performed over the integers.+foreign import ccall "fmpq_poly.h fmpq_poly_revert_series"+ fmpq_poly_revert_series :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> CLong -> IO ()++-- Gaussian content ------------------------------------------------------------++-- | /_fmpq_poly_content/ /res/ /poly/ /den/ /len/ +-- +-- Sets @res@ to the content of @(poly, den, len)@. If @len == 0@, sets+-- @res@ to zero.+foreign import ccall "fmpq_poly.h _fmpq_poly_content"+ _fmpq_poly_content :: Ptr CFmpq -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_content/ /res/ /poly/ +-- +-- Sets @res@ to the content of @poly@. The content of the zero polynomial+-- is defined to be zero.+foreign import ccall "fmpq_poly.h fmpq_poly_content"+ fmpq_poly_content :: Ptr CFmpq -> Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_primitive_part/ /rpoly/ /rden/ /poly/ /den/ /len/ +-- +-- Sets @(rpoly, rden, len)@ to the primitive part, with non-negative+-- leading coefficient, of @(poly, den, len)@. Assumes that @len > 0@.+-- Supports aliasing between the two polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_primitive_part"+ _fmpq_poly_primitive_part :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_primitive_part/ /res/ /poly/ +-- +-- Sets @res@ to the primitive part, with non-negative leading coefficient,+-- of @poly@.+foreign import ccall "fmpq_poly.h fmpq_poly_primitive_part"+ fmpq_poly_primitive_part :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- | /_fmpq_poly_is_monic/ /poly/ /den/ /len/ +-- +-- Returns whether the polynomial @(poly, den, len)@ is monic. The zero+-- polynomial is not monic by definition.+foreign import ccall "fmpq_poly.h _fmpq_poly_is_monic"+ _fmpq_poly_is_monic :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpq_poly_is_monic/ /poly/ +-- +-- Returns whether the polynomial @poly@ is monic. The zero polynomial is+-- not monic by definition.+foreign import ccall "fmpq_poly.h fmpq_poly_is_monic"+ fmpq_poly_is_monic :: Ptr CFmpqPoly -> IO CInt++-- | /_fmpq_poly_make_monic/ /rpoly/ /rden/ /poly/ /den/ /len/ +-- +-- Sets @(rpoly, rden, len)@ to the monic scalar multiple of+-- @(poly, den, len)@. Assumes that @len > 0@. Supports aliasing between+-- the two polynomials.+foreign import ccall "fmpq_poly.h _fmpq_poly_make_monic"+ _fmpq_poly_make_monic :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpq_poly_make_monic/ /res/ /poly/ +-- +-- Sets @res@ to the monic scalar multiple of @poly@ whenever @poly@ is+-- non-zero. If @poly@ is the zero polynomial, sets @res@ to zero.+foreign import ccall "fmpq_poly.h fmpq_poly_make_monic"+ fmpq_poly_make_monic :: Ptr CFmpqPoly -> Ptr CFmpqPoly -> IO ()++-- Square-free -----------------------------------------------------------------++-- | /fmpq_poly_is_squarefree/ /poly/ +-- +-- Returns whether the polynomial @poly@ is square-free. A non-zero+-- polynomial is defined to be square-free if it has no non-unit square+-- factors. We also define the zero polynomial to be square-free.+foreign import ccall "fmpq_poly.h fmpq_poly_is_squarefree"+ fmpq_poly_is_squarefree :: Ptr CFmpqPoly -> IO CInt++-- Input and output ------------------------------------------------------------++-- | /_fmpq_poly_print/ /poly/ /den/ /len/ +-- +-- Prints the polynomial @(poly, den, len)@ to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpq_poly.h _fmpq_poly_print"+ _fmpq_poly_print :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpq_poly_print/ /poly/ +-- +-- Prints the polynomial to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+-- foreign import ccall "fmpq_poly.h fmpq_poly_print"+fmpq_poly_print :: Ptr CFmpqPoly -> IO CInt+fmpq_poly_print poly = printCStr fmpq_poly_get_str poly++foreign import ccall "fmpq_poly.h _fmpq_poly_print_pretty"+ _fmpq_poly_print_pretty :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CString -> IO CInt++-- | /fmpq_poly_print_pretty/ /poly/ /var/ +-- +-- Prints the pretty representation of @poly@ to @stdout@, using the+-- null-terminated string @var@ not equal to @\"\\0\"@ as the variable+-- name.+-- +-- In the current implementation always returns~\`1\`.+fmpq_poly_print_pretty :: Ptr CFmpqPoly -> CString -> IO CInt+fmpq_poly_print_pretty poly var =+ printCStr (flip fmpq_poly_get_str_pretty var) poly++-- | /_fmpq_poly_fprint/ /file/ /poly/ /den/ /len/ +-- +-- Prints the polynomial @(poly, den, len)@ to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpq_poly.h _fmpq_poly_fprint"+ _fmpq_poly_fprint :: Ptr CFile -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpq_poly_fprint/ /file/ /poly/ +-- +-- Prints the polynomial to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpq_poly.h fmpq_poly_fprint"+ fmpq_poly_fprint :: Ptr CFile -> Ptr CFmpqPoly -> IO CInt++foreign import ccall "fmpq_poly.h _fmpq_poly_fprint_pretty"+ _fmpq_poly_fprint_pretty :: Ptr CFile -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CString -> IO CInt++-- | /fmpq_poly_fprint_pretty/ /file/ /poly/ /var/ +-- +-- Prints the pretty representation of @poly@ to @stdout@, using the+-- null-terminated string @var@ not equal to @\"\\0\"@ as the variable+-- name.+-- +-- In the current implementation, always returns~\`1\`.+foreign import ccall "fmpq_poly.h fmpq_poly_fprint_pretty"+ fmpq_poly_fprint_pretty :: Ptr CFile -> Ptr CFmpqPoly -> CString -> IO CInt++-- | /fmpq_poly_read/ /poly/ +-- +-- Reads a polynomial from @stdin@, storing the result in @poly@.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpq_poly.h fmpq_poly_read"+ fmpq_poly_read :: Ptr CFmpqPoly -> IO CInt++-- | /fmpq_poly_fread/ /file/ /poly/ +-- +-- Reads a polynomial from the stream @file@, storing the result in @poly@.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpq_poly.h fmpq_poly_fread"+ fmpq_poly_fread :: Ptr CFile -> Ptr CFmpqPoly -> IO CInt++foreign import ccall "fmpq_poly.h fmpq_poly_fprint_pretty_as_series"+ fmpq_poly_fprint_pretty_as_series :: Ptr CFile -> Ptr CFmpqPoly -> CString -> IO CInt++fmpq_poly_print_pretty_as_series :: Ptr CFmpqPoly -> CString -> IO CInt+fmpq_poly_print_pretty_as_series poly var =+ printCStr (flip fmpq_poly_get_str_pretty_as_series var) poly+ +foreign import ccall "fmpq_poly.h fmpq_poly_get_str_pretty_as_series"+ fmpq_poly_get_str_pretty_as_series :: Ptr CFmpqPoly -> CString -> IO CString
+ src/Data/Number/Flint/Fmpq/Poly/Instances.hs view
@@ -0,0 +1,63 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Fmpq.Poly.Instances (+ FmpqPoly (..)+) where++import GHC.Exts+import System.IO.Unsafe+import Control.Monad+import Foreign.C.String+import Foreign.Marshal.Alloc++import Data.Ratio hiding (numerator, denominator)++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Instances+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fmpq.Poly++instance IsList FmpqPoly where+ type Item FmpqPoly = Fmpq+ fromList c = unsafePerformIO $ do+ p <- newFmpqPoly+ withFmpqPoly p $ \p -> do+ forM_ [0..length c-1] $ \j -> do+ withFmpq (c!!j) $ \a -> + fmpq_poly_set_coeff_fmpq p (fromIntegral j) a+ return p+ toList p = snd $ unsafePerformIO $ do+ withFmpqPoly p $ \p -> do+ d <- fmpq_poly_degree p+ forM [0..d] $ \j -> do+ c <- newFmpq+ withFmpq c $ \c -> fmpq_poly_get_coeff_fmpq c p j+ return c+ +instance Show FmpqPoly where+ show p = snd $ unsafePerformIO $ do+ withFmpqPoly p $ \p -> do+ withCString "x" $ \x -> do+ cs <- fmpq_poly_get_str_pretty p x+ s <- peekCString cs+ free cs+ return s++instance Num FmpqPoly where+ (*) = lift2 fmpq_poly_mul+ (+) = lift2 fmpq_poly_add+ (-) = lift2 fmpq_poly_sub+ abs = undefined+ signum = undefined+ fromInteger x = fst $ unsafePerformIO $ do+ let t = fromInteger x :: Fmpz+ withNewFmpqPoly $ \poly -> do+ withFmpz t $ \x -> do+ fmpq_poly_set_fmpz poly x+ +lift2 f x y = unsafePerformIO $ do+ result <- newFmpqPoly+ withFmpqPoly result $ \result -> do+ withFmpqPoly x $ \x -> do+ withFmpqPoly y $ \y -> do+ f result x y+ return result
+ src/Data/Number/Flint/Fmpq/Vec.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpq.Vec (+ module Data.Number.Flint.Fmpq.Vec.FFI+ ) where++import Data.Number.Flint.Fmpq.Vec.FFI
+ src/Data/Number/Flint/Fmpq/Vec/FFI.hsc view
@@ -0,0 +1,135 @@+{-|+module : Data.Number.Flint.Fmpq.Vec.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpq.Vec.FFI (+ -- * Vectors over rational numbers+ -- * Memory management+ _fmpq_vec_init+ , _fmpq_vec_clear+ -- * Randomisation+ , _fmpq_vec_randtest+ , _fmpq_vec_randtest_uniq_sorted+ -- * Sorting+ , _fmpq_vec_sort+ -- * Conversions+ , _fmpq_vec_set_fmpz_vec+ , _fmpq_vec_get_fmpz_vec_fmpz+ -- * Dot product+ , _fmpq_vec_dot+ -- * Input and output+ , _fmpq_vec_get_str+ , _fmpq_vec_fprint+ , _fmpq_vec_print+) where ++-- vectors over rational numbers -----------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, nullPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_vec.h>+#include <flint/fmpq_vec.h>++-- Memory management -----------------------------------------------------------++-- | /_fmpq_vec_init/ /n/ +-- +-- Initialises a vector of @fmpq@ values of length \(n\) and sets all+-- values to 0. This is equivalent to generating a @fmpz@ vector of length+-- \(2n\) with @_fmpz_vec_init@ and setting all denominators to 1.+foreign import ccall "fmpq_vec.h _fmpq_vec_init"+ _fmpq_vec_init :: CLong -> IO (Ptr CFmpq)++-- | /_fmpq_vec_clear/ /vec/ /n/ +-- +-- Frees an @fmpq@ vector.+foreign import ccall "fmpq_vec.h _fmpq_vec_clear"+ _fmpq_vec_clear :: Ptr CFmpq -> CLong -> IO ()++-- Randomisation ---------------------------------------------------------------++-- | /_fmpq_vec_randtest/ /f/ /state/ /len/ /bits/ +-- +-- Sets the entries of a vector of the given length to random rationals+-- with numerator and denominator having up to the given number of bits per+-- entry.+foreign import ccall "fmpq_vec.h _fmpq_vec_randtest"+ _fmpq_vec_randtest :: Ptr CFmpq -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- | /_fmpq_vec_randtest_uniq_sorted/ /vec/ /state/ /len/ /bits/ +-- +-- Sets the entries of a vector of the given length to random distinct+-- rationals with numerator and denominator having up to the given number+-- of bits per entry. The entries in the vector are sorted.+foreign import ccall "fmpq_vec.h _fmpq_vec_randtest_uniq_sorted"+ _fmpq_vec_randtest_uniq_sorted :: Ptr CFmpq -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- Sorting ---------------------------------------------------------------------++-- | /_fmpq_vec_sort/ /vec/ /len/ +-- +-- Sorts the entries of @(vec, len)@.+foreign import ccall "fmpq_vec.h _fmpq_vec_sort"+ _fmpq_vec_sort :: Ptr CFmpq -> CLong -> IO ()++-- Conversions -----------------------------------------------------------------++-- | /_fmpq_vec_set_fmpz_vec/ /res/ /vec/ /len/ +-- +-- Sets @(res, len)@ to @(vec, len)@.+foreign import ccall "fmpq_vec.h _fmpq_vec_set_fmpz_vec"+ _fmpq_vec_set_fmpz_vec :: Ptr CFmpq -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpq_vec_get_fmpz_vec_fmpz/ /num/ /den/ /a/ /len/ +-- +-- Find a common denominator @den@ of the entries of @a@ and set+-- @(num, len)@ to the corresponding numerators.+foreign import ccall "fmpq_vec.h _fmpq_vec_get_fmpz_vec_fmpz"+ _fmpq_vec_get_fmpz_vec_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpq -> CLong -> IO ()++-- Dot product -----------------------------------------------------------------++-- | /_fmpq_vec_dot/ /res/ /vec1/ /vec2/ /len/ +-- +-- Sets @res@ to the dot product of the vectors @(vec1, len)@ and+-- @(vec2, len)@.+foreign import ccall "fmpq_vec.h _fmpq_vec_dot"+ _fmpq_vec_dot :: Ptr CFmpq -> Ptr CFmpq -> Ptr CFmpq -> CLong -> IO ()++-- Input and output ------------------------------------------------------------++foreign import ccall "fmpz_vec.h _fmpq_vec_get_str"+ _fmpq_vec_get_str :: CLong -> Ptr CFmpq -> IO (CString)++-- | /_fmpq_vec_fprint/ /file/ /vec/ /len/ +-- +-- Prints the vector of given length to the stream @file@. The format is+-- the length followed by two spaces, then a space separated list of+-- coefficients. If the length is zero, only \(0\) is printed.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpq_vec.h _fmpq_vec_fprint"+ _fmpq_vec_fprint :: Ptr CFile -> Ptr CFmpq -> CLong -> IO CInt++-- | /_fmpq_vec_print/ /vec/ /len/ +-- +-- Prints the vector of given length to @stdout@.+-- +-- For further details, see @_fmpq_vec_fprint()@.+_fmpq_vec_print :: Ptr CFmpq -> CLong -> IO CInt+_fmpq_vec_print x n = printCStr (_fmpq_vec_get_str n) x+
+ src/Data/Number/Flint/Fmpz.hs view
@@ -0,0 +1,69 @@+{-|+module : Data.Number.Flint.Fmpz+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++An `Fmpz` represents an integer.+This module implements operations on integers.++== Example++__Warning__: Instances like `Show` and `Num` are only+avaible for some types without context.++@+import Data.Number.Flint++main = do + let x, y :: Fmpz+ x = 7+ y = 8+ z = x * y+ print z+ print $ factor z+@++Running main yields:++>>> main +56+[(2,3),(7,1)]++== Using the @Flint@ library directly++@+import Data.Number.Flint++main = do + x <- newFmpz+ y <- newFmpz+ z <- newFmpz+ withFmpz x $ \\x -> do+ withFmpz y $ \\y -> do+ withFmpz z $ \\z -> do+ fmpz_set_ui x 7+ fmpz_set_ui y 8+ fmpz_mul z x y+ fmpz_print z+ fac <- newFmpzFactor+ putStr "\\n"+ withFmpzFactor fac $ \\fac -> do+ fmpz_factor fac z+ fmpz_factor_print fac+ putStr "\\n"+@++Running main yields:++>>> main +56+2^3 * 7++-}++module Data.Number.Flint.Fmpz (+ module Data.Number.Flint.Fmpz.FFI+) where++import Data.Number.Flint.Fmpz.FFI
+ src/Data/Number/Flint/Fmpz/Arith.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Arith (+ module Data.Number.Flint.Fmpz.Arith.FFI+ ) where++import Data.Number.Flint.Fmpz.Arith.FFI
+ src/Data/Number/Flint/Fmpz/Arith/FFI.hsc view
@@ -0,0 +1,726 @@+{-|+module : Data.Number.Flint.Fmpz.Arith.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Arith.FFI (+ -- * Arithmetic and special functions+ -- * Harmonic numbers+ _arith_harmonic_number+ -- * Stirling numbers+ , arith_stirling_number_1u+ , arith_stirling_number_1+ , arith_stirling_number_2+ , arith_stirling_number_1u_vec+ , arith_stirling_number_1_vec+ , arith_stirling_number_2_vec+ , arith_stirling_number_1u_vec_next+ , arith_stirling_number_1_vec_next+ , arith_stirling_number_2_vec_next+ , arith_stirling_matrix_1u+ , arith_stirling_matrix_1+ , arith_stirling_matrix_2+ -- * Bell numbers+ , arith_bell_number+ , arith_bell_number_vec+ , arith_bell_number_nmod+ , arith_bell_number_nmod_vec+ , arith_bell_number_size+ -- * Bernoulli numbers and polynomials+ , _arith_bernoulli_number+ , arith_bernoulli_number+ , _arith_bernoulli_number_vec+ , arith_bernoulli_number_vec+ , arith_bernoulli_number_denom+ , arith_bernoulli_number_size+ , arith_bernoulli_polynomial+ --, _arith_bernoulli_number_zeta+ , _arith_bernoulli_number_vec_recursive+ --, _arith_bernoulli_number_vec_zeta+ , _arith_bernoulli_number_vec_multi_mod+ -- * Euler numbers and polynomials+ , arith_euler_number+ , arith_euler_number_vec+ , arith_euler_number_size+ , arith_euler_polynomial+ --, _arith_euler_number_zeta+ -- * Multiplicative functions+ , arith_divisors+ , arith_ramanujan_tau+ , arith_ramanujan_tau_series+ -- * Cyclotomic polynomials+ -- , _arith_cos_minpoly+ -- , arith_cos_minpoly+ -- * Landau\'s function+ , arith_landau_function_vec+ -- * Number of partitions+ , arith_number_of_partitions_vec+ , arith_number_of_partitions_nmod_vec+ , arith_hrr_expsum_factored+ --, arith_number_of_partitions_mpfr+ , arith_number_of_partitions+ -- * Sums of squares+ , arith_sum_of_squares+ , arith_sum_of_squares_vec+) where ++-- arithmetic and special functions --------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fmpq.Poly+import Data.Number.Flint.NMod++-- trig_prod_t -----------------------------------------------------------------++data FTrigProd = FTrigProd {-# UNPACK #-} !(ForeignPtr CFTrigProd) +type CFTrigProd = CFlint FTrigProd++-- Harmonic numbers ------------------------------------------------------------++-- | /_arith_harmonic_number/ /num/ /den/ /n/ +-- +-- These are aliases for the functions in the fmpq module.+foreign import ccall "arith.h _arith_harmonic_number"+ _arith_harmonic_number :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- Stirling numbers ------------------------------------------------------------++foreign import ccall "arith.h arith_stirling_number_1u"+ arith_stirling_number_1u :: Ptr CFmpz -> CULong -> CULong -> IO ()++foreign import ccall "arith.h arith_stirling_number_1"+ arith_stirling_number_1 :: Ptr CFmpz -> CULong -> CULong -> IO ()++-- | /arith_stirling_number_2/ /s/ /n/ /k/ +-- +-- Sets \(s\) to \(S(n,k)\) where \(S(n,k)\) denotes an unsigned Stirling+-- number of the first kind \(|S_1(n, k)|\), a signed Stirling number of+-- the first kind \(S_1(n, k)\), or a Stirling number of the second kind+-- \(S_2(n, k)\). The Stirling numbers are defined using the generating+-- functions+-- +-- \[`\]+-- \[x_{(n)} = \sum_{k=0}^n S_1(n,k) x^k\]+-- \[x^{(n)} = \sum_{k=0}^n |S_1(n,k)| x^k\]+-- \[x^n = \sum_{k=0}^n S_2(n,k) x_{(k)}\]+-- +-- where \(x_{(n)} = x(x-1)(x-2) \dotsm (x-n+1)\) is a falling factorial+-- and \(x^{(n)} = x(x+1)(x+2) \dotsm (x+n-1)\) is a rising factorial.+-- \(S(n,k)\) is taken to be zero if \(n < 0\) or \(k < 0\).+-- +-- These three functions are useful for computing isolated Stirling numbers+-- efficiently. To compute a range of numbers, the vector or matrix+-- versions should generally be used.+foreign import ccall "arith.h arith_stirling_number_2"+ arith_stirling_number_2 :: Ptr CFmpz -> CULong -> CULong -> IO ()++foreign import ccall "arith.h arith_stirling_number_1u_vec"+ arith_stirling_number_1u_vec :: Ptr CFmpz -> CULong -> CLong -> IO ()++foreign import ccall "arith.h arith_stirling_number_1_vec"+ arith_stirling_number_1_vec :: Ptr CFmpz -> CULong -> CLong -> IO ()++-- | /arith_stirling_number_2_vec/ /row/ /n/ /klen/ +-- +-- Computes the row of Stirling numbers+-- @S(n,0), S(n,1), S(n,2), ..., S(n,klen-1)@.+-- +-- To compute a full row, this function can be called with @klen = n+1@. It+-- is assumed that @klen@ is at most \(n + 1\).+foreign import ccall "arith.h arith_stirling_number_2_vec"+ arith_stirling_number_2_vec :: Ptr CFmpz -> CULong -> CLong -> IO ()++foreign import ccall "arith.h arith_stirling_number_1u_vec_next"+ arith_stirling_number_1u_vec_next :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++foreign import ccall "arith.h arith_stirling_number_1_vec_next"+ arith_stirling_number_1_vec_next :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /arith_stirling_number_2_vec_next/ /row/ /prev/ /n/ /klen/ +-- +-- Given the vector @prev@ containing a row of Stirling numbers+-- @S(n-1,0), S(n-1,1), S(n-1,2), ..., S(n-1,klen-1)@, computes and stores+-- in the row argument @S(n,0), S(n,1), S(n,2), ..., S(n,klen-1)@.+-- +-- If @klen@ is greater than @n@, the output ends with @S(n,n) = 1@+-- followed by @S(n,n+1) = S(n,n+2) = ... = 0@. In this case, the input+-- only needs to have length @n-1@; only the input entries up to+-- @S(n-1,n-2)@ are read.+-- +-- The @row@ and @prev@ arguments are permitted to be the same, meaning+-- that the row will be updated in-place.+foreign import ccall "arith.h arith_stirling_number_2_vec_next"+ arith_stirling_number_2_vec_next :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++foreign import ccall "arith.h arith_stirling_matrix_1u"+ arith_stirling_matrix_1u :: Ptr CFmpzMat -> IO ()++foreign import ccall "arith.h arith_stirling_matrix_1"+ arith_stirling_matrix_1 :: Ptr CFmpzMat -> IO ()++-- | /arith_stirling_matrix_2/ /mat/ +-- +-- For an arbitrary \(m\)-by-n matrix, writes the truncation of the+-- infinite Stirling number matrix:+-- +-- > row 0 : S(0,0)+-- > row 1 : S(1,0), S(1,1)+-- > row 2 : S(2,0), S(2,1), S(2,2)+-- > row 3 : S(3,0), S(3,1), S(3,2), S(3,3)+-- +-- up to row \(m-1\) and column \(n-1\) inclusive. The upper triangular+-- part of the matrix is zeroed.+-- +-- For any \(n\), the \(S_1\) and \(S_2\) matrices thus obtained are+-- inverses of each other.+foreign import ccall "arith.h arith_stirling_matrix_2"+ arith_stirling_matrix_2 :: Ptr CFmpzMat -> IO ()++-- Bell numbers ----------------------------------------------------------------++-- | /arith_bell_number/ /b/ /n/ +-- +-- Sets \(b\) to the Bell number \(B_n\), defined as the number of+-- partitions of a set with \(n\) members. Equivalently,+-- \(B_n = \sum_{k=0}^n S_2(n,k)\) where \(S_2(n,k)\) denotes a Stirling+-- number of the second kind.+-- +-- The default version automatically selects between table lookup,+-- Dobinski\'s formula, and the multimodular algorithm.+-- +-- The @dobinski@ version evaluates a precise truncation of the series+-- \(B_n = e^{-1} \sum_{k=0}^{\infty} \frac{k^n}{k!}\) (Dobinski\'s+-- formula). In fact, we compute \(P = N! \sum_{k=0}^N \frac{k^n}{k!}\) and+-- \(Q = N! \sum_{k=0}^N \frac{1}{k!} \approx N! e\) and evaluate+-- \(B_n = \lceil P / Q \rceil\), avoiding the use of floating-point+-- arithmetic.+-- +-- The @multi_mod@ version computes the result modulo several limb-size+-- primes and reconstructs the integer value using the fast Chinese+-- remainder algorithm. A bound for the number of needed primes is computed+-- using @arith_bell_number_size@.+foreign import ccall "arith.h arith_bell_number"+ arith_bell_number :: Ptr CFmpz -> CULong -> IO ()++-- | /arith_bell_number_vec/ /b/ /n/ +-- +-- Sets \(b\) to the vector of Bell numbers \(B_0, B_1, \ldots, B_{n-1}\)+-- inclusive. The @recursive@ version uses the \(O(n^3 \log n)\) triangular+-- recurrence, while the @multi_mod@ version implements multimodular+-- evaluation of the exponential generating function, running in time+-- \(O(n^2 \log^{O(1)} n)\). The default version chooses an algorithm+-- automatically.+foreign import ccall "arith.h arith_bell_number_vec"+ arith_bell_number_vec :: Ptr CFmpz -> CLong -> IO ()++-- | /arith_bell_number_nmod/ /n/ /mod/ +-- +-- Computes the Bell number \(B_n\) modulo an integer given by @mod@.+-- +-- After handling special cases, we use the formula+-- +-- \[`\]+-- \[B_n = \sum_{k=0}^n \frac{(n-k)^n}{(n-k)!}+-- \sum_{j=0}^k \frac{(-1)^j}{j!}.\]+-- +-- We arrange the operations in such a way that we only have to multiply+-- (and not divide) in the main loop. As a further optimisation, we use+-- sieving to reduce the number of powers that need to be evaluated. This+-- results in \(O(n)\) memory usage.+-- +-- If the divisions by factorials are impossible, we fall back to calling+-- @arith_bell_number_nmod_vec@ and reading the last coefficient.+foreign import ccall "arith.h arith_bell_number_nmod"+ arith_bell_number_nmod :: CULong -> Ptr CNMod -> IO CMpLimb++-- | /arith_bell_number_nmod_vec/ /b/ /n/ /mod/ +-- +-- Sets \(b\) to the vector of Bell numbers \(B_0, B_1, \ldots, B_{n-1}\)+-- inclusive modulo an integer given by @mod@.+-- +-- The /recursive/ version uses the \(O(n^2)\) triangular recurrence. The+-- /ogf/ version expands the ordinary generating function using binary+-- splitting, which is \(O(n \log^2 n)\).+-- +-- The /series/ version uses the exponential generating function+-- \(\sum_{k=0}^{\infty} \frac{B_n}{n!} x^n = \exp(e^x-1)\), running in+-- \(O(n \log n)\). This only works if division by \(n!\) is possible, and+-- the function returns whether it is successful. All other versions+-- support any modulus.+-- +-- The default version of this function selects an algorithm automatically.+foreign import ccall "arith.h arith_bell_number_nmod_vec"+ arith_bell_number_nmod_vec :: Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /arith_bell_number_size/ /n/ +-- +-- Returns \(b\) such that \(B_n < 2^{\lfloor b \rfloor}\). A previous+-- version of this function used the inequality+-- @B_n \< \\left(\\frac{0.792n}{\\log(n+1)}\\right)^n@ which is given in+-- < [BerTas2010]>; we now use a slightly better bound based on an+-- asymptotic expansion.+foreign import ccall "arith.h arith_bell_number_size"+ arith_bell_number_size :: CULong -> IO CDouble++-- Bernoulli numbers and polynomials -------------------------------------------++-- | /_arith_bernoulli_number/ /num/ /den/ /n/ +-- +-- Sets @(num, den)@ to the reduced numerator and denominator of the+-- \(n\)-th Bernoulli number. As presently implemented, this function+-- simply calls\\ @_arith_bernoulli_number_zeta@.+foreign import ccall "arith.h _arith_bernoulli_number"+ _arith_bernoulli_number :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /arith_bernoulli_number/ /x/ /n/ +-- +-- Sets @x@ to the \(n\)-th Bernoulli number. This function is equivalent+-- to\\ @_arith_bernoulli_number@ apart from the output being a single+-- @fmpq_t@ variable.+-- +-- Warning: this function does not use proven precision bounds, and could+-- return the wrong results for very large \(n\). It is recommended to use+-- the Bernoulli number functions in Arb instead.+foreign import ccall "arith.h arith_bernoulli_number"+ arith_bernoulli_number :: Ptr CFmpq -> CULong -> IO ()++-- | /_arith_bernoulli_number_vec/ /num/ /den/ /n/ +-- +-- Sets the elements of @num@ and @den@ to the reduced numerators and+-- denominators of the Bernoulli numbers \(B_0, B_1, B_2, \ldots, B_{n-1}\)+-- inclusive. This function automatically chooses between the @recursive@,+-- @zeta@ and @multi_mod@ algorithms according to the size of \(n\).+foreign import ccall "arith.h _arith_bernoulli_number_vec"+ _arith_bernoulli_number_vec :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /arith_bernoulli_number_vec/ /x/ /n/ +-- +-- Sets the @x@ to the vector of Bernoulli numbers+-- \(B_0, B_1, B_2, \ldots, B_{n-1}\) inclusive. This function is+-- equivalent to @_arith_bernoulli_number_vec@ apart from the output being+-- a single @fmpq@ vector.+foreign import ccall "arith.h arith_bernoulli_number_vec"+ arith_bernoulli_number_vec :: Ptr CFmpq -> CLong -> IO ()++-- | /arith_bernoulli_number_denom/ /den/ /n/ +-- +-- Sets @den@ to the reduced denominator of the \(n\)-th Bernoulli number+-- \(B_n\). For even \(n\), the denominator is computed as the product of+-- all primes \(p\) for which \(p - 1\) divides \(n\); this property is a+-- consequence of the von Staudt-Clausen theorem. For odd \(n\), the+-- denominator is trivial (@den@ is set to 1 whenever \(B_n = 0\)). The+-- initial sequence of values smaller than \(2^{32}\) are looked up+-- directly from a table.+foreign import ccall "arith.h arith_bernoulli_number_denom"+ arith_bernoulli_number_denom :: Ptr CFmpz -> CULong -> IO ()++-- | /arith_bernoulli_number_size/ /n/ +-- +-- Returns \(b\) such that \(|B_n| < 2^{\lfloor b \rfloor}\), using the+-- inequality @|B_n| \< \\frac{4 n!}{(2\\pi)^n}@ and+-- \(n! \le (n+1)^{n+1} e^{-n}\). No special treatment is given to odd+-- \(n\). Accuracy is not guaranteed if \(n > 10^{14}\).+foreign import ccall "arith.h arith_bernoulli_number_size"+ arith_bernoulli_number_size :: CULong -> IO CDouble++-- | /arith_bernoulli_polynomial/ /poly/ /n/ +-- +-- Sets @poly@ to the Bernoulli polynomial of degree \(n\),+-- \(B_n(x) = \sum_{k=0}^n \binom{n}{k} B_k x^{n-k}\) where \(B_k\) is a+-- Bernoulli number. This function basically calls+-- @arith_bernoulli_number_vec@ and then rescales the coefficients+-- efficiently.+foreign import ccall "arith.h arith_bernoulli_polynomial"+ arith_bernoulli_polynomial :: Ptr CFmpqPoly -> CULong -> IO ()++-- -- | /_arith_bernoulli_number_zeta/ /num/ /den/ /n/ +-- -- +-- -- Sets @(num, den)@ to the reduced numerator and denominator of the+-- -- \(n\)-th Bernoulli number.+-- -- +-- -- This function first computes the exact denominator and a bound for the+-- -- size of the numerator. It then computes an approximation of+-- -- \(|B_n| = 2n! \zeta(n) / (2 \pi)^n\) as a floating-point number and+-- -- multiplies by the denominator to to obtain a real number that rounds to+-- -- the exact numerator. For tiny \(n\), the numerator is looked up from a+-- -- table to avoid unnecessary overhead.+-- -- +-- -- Warning: this function does not use proven precision bounds, and could+-- -- return the wrong results for very large \(n\). It is recommended to use+-- -- the Bernoulli number functions in Arb instead.+-- foreign import ccall "arith.h _arith_bernoulli_number_zeta"+-- _arith_bernoulli_number_zeta :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /_arith_bernoulli_number_vec_recursive/ /num/ /den/ /n/ +-- +-- Sets the elements of @num@ and @den@ to the reduced numerators and+-- denominators of \(B_0, B_1, B_2, \ldots, B_{n-1}\) inclusive.+-- +-- The first few entries are computed using @arith_bernoulli_number@, and+-- then Ramanujan\'s recursive formula expressing \(B_m\) as a sum over+-- \(B_k\) for \(k\) congruent to \(m\) modulo 6 is applied repeatedly.+-- +-- To avoid costly GCDs, the numerators are transformed internally to a+-- common denominator and all operations are performed using integer+-- arithmetic. This makes the algorithm fast for small \(n\), say+-- \(n < 1000\). The common denominator is calculated directly as the+-- primorial of \(n + 1\).+-- +-- %[1] <https://en.wikipedia.org/w/index.php>? %+-- title=Bernoulli_number&oldid=405938876+foreign import ccall "arith.h _arith_bernoulli_number_vec_recursive"+ _arith_bernoulli_number_vec_recursive :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- -- | /_arith_bernoulli_number_vec_zeta/ /num/ /den/ /n/ +-- -- +-- -- Sets the elements of @num@ and @den@ to the reduced numerators and+-- -- denominators of \(B_0, B_1, B_2, \ldots, B_{n-1}\) inclusive. Uses+-- -- repeated direct calls to\\ @_arith_bernoulli_number_zeta@.+-- foreign import ccall "arith.h _arith_bernoulli_number_vec_zeta"+-- _arith_bernoulli_number_vec_zeta :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_arith_bernoulli_number_vec_multi_mod/ /num/ /den/ /n/ +-- +-- Sets the elements of @num@ and @den@ to the reduced numerators and+-- denominators of \(B_0, B_1, B_2, \ldots, B_{n-1}\) inclusive. Uses the+-- generating function+-- +-- \[`\]+-- \[\frac{x^2}{\cosh(x)-1} = \sum_{k=0}^{\infty}+-- \frac{(2-4k) B_{2k}}{(2k)!} x^{2k}\]+-- +-- which is evaluated modulo several limb-size primes using @nmod_poly@+-- arithmetic to yield the numerators of the Bernoulli numbers after+-- multiplication by the denominators and CRT reconstruction. This formula,+-- given (incorrectly) in < [BuhlerCrandallSompolski1992]>, saves about+-- half of the time compared to the usual generating function \(x/(e^x-1)\)+-- since the odd terms vanish.+foreign import ccall "arith.h _arith_bernoulli_number_vec_multi_mod"+ _arith_bernoulli_number_vec_multi_mod :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- Euler numbers and polynomials -----------------------------------------------++-- Euler numbers are the integers \(E_n\) defined by frac{1}{cosh(t)} =+-- sum_{n=0}^{infty} frac{E_n}{n!} t^n. With this convention, the+-- odd-indexed numbers are zero and the even ones alternate signs, viz.+-- E_0, E_1, E_2, ldots = 1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, ldots. The+-- corresponding Euler polynomials are defined by frac{2e^{xt}}{e^t+1} =+-- sum_{n=0}^{infty} frac{E_n(x)}{n!} t^n.+--+-- | /arith_euler_number/ /res/ /n/ +-- +-- Sets @res@ to the Euler number \(E_n\). Currently calls+-- @_arith_euler_number_zeta@.+-- +-- Warning: this function does not use proven precision bounds, and could+-- return the wrong results for very large \(n\). It is recommended to use+-- the Euler number functions in Arb instead.+foreign import ccall "arith.h arith_euler_number"+ arith_euler_number :: Ptr CFmpz -> CULong -> IO ()++-- | /arith_euler_number_vec/ /res/ /n/ +-- +-- Computes the Euler numbers \(E_0, E_1, \dotsc, E_{n-1}\) for+-- \(n \geq 0\) and stores the result in @res@, which must be an+-- initialised @fmpz@ vector of sufficient size.+-- +-- This function evaluates the even-index \(E_k\) modulo several limb-size+-- primes using the generating function and @nmod_poly@ arithmetic. A tight+-- bound for the number of needed primes is computed using+-- @arith_euler_number_size@, and the final integer values are recovered+-- using balanced CRT reconstruction.+foreign import ccall "arith.h arith_euler_number_vec"+ arith_euler_number_vec :: Ptr CFmpz -> CLong -> IO ()++-- | /arith_euler_number_size/ /n/ +-- +-- Returns \(b\) such that \(|E_n| < 2^{\lfloor b \rfloor}\), using the+-- inequality @|E_n| \< \\frac{2^{n+2} n!}{\\pi^{n+1}}@ and+-- \(n! \le (n+1)^{n+1} e^{-n}\). No special treatment is given to odd+-- \(n\). Accuracy is not guaranteed if \(n > 10^{14}\).+foreign import ccall "arith.h arith_euler_number_size"+ arith_euler_number_size :: CULong -> IO CDouble++-- | /arith_euler_polynomial/ /poly/ /n/ +-- +-- Sets @poly@ to the Euler polynomial \(E_n(x)\). Uses the formula+-- +-- \[`\]+-- \[E_n(x) = \frac{2}{n+1}\left(B_{n+1}(x) - +-- 2^{n+1}B_{n+1}\left(\frac{x}{2}\right)\right),\]+-- +-- with the Bernoulli polynomial \(B_{n+1}(x)\) evaluated once using+-- @bernoulli_polynomial@ and then rescaled.+foreign import ccall "arith.h arith_euler_polynomial"+ arith_euler_polynomial :: Ptr CFmpqPoly -> CULong -> IO ()++-- -- | /_arith_euler_number_zeta/ /res/ /n/ +-- -- +-- -- Sets @res@ to the Euler number \(E_n\). For even \(n\), this function+-- -- uses the relation @|E_n| = \\frac{2^{n+2} n!}{\\pi^{n+1}} L(n+1)@ where+-- -- \(L(n+1)\) denotes the Dirichlet \(L\)-function with character+-- -- \(\chi = \{ 0, 1, 0, -1 \}\).+-- -- +-- -- Warning: this function does not use proven precision bounds, and could+-- -- return the wrong results for very large \(n\). It is recommended to use+-- -- the Euler number functions in Arb instead.+-- foreign import ccall "arith.h _arith_euler_number_zeta"+-- _arith_euler_number_zeta :: Ptr CFmpz -> CULong -> IO ()++-- Multiplicative functions ----------------------------------------------------++-- | /arith_divisors/ /res/ /n/ +-- +-- Set the coefficients of the polynomial @res@ to the divisors of \(n\),+-- including \(1\) and \(n\) itself, in ascending order.+foreign import ccall "arith.h arith_divisors"+ arith_divisors :: Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /arith_ramanujan_tau/ /res/ /n/ +-- +-- Sets @res@ to the Ramanujan tau function \(\tau(n)\) which is the+-- coefficient of \(q^n\) in the series expansion of+-- \(f(q) = q \prod_{k \geq 1} \bigl(1 - q^k\bigr)^{24}\).+-- +-- We factor \(n\) and use the identity \(\tau(pq) = \tau(p) \tau(q)\)+-- along with the recursion+-- \(\tau(p^{r+1}) = \tau(p) \tau(p^r) - p^{11} \tau(p^{r-1})\) for prime+-- powers.+-- +-- The base values \(\tau(p)\) are obtained using the function+-- @arith_ramanujan_tau_series()@. Thus the speed of+-- @arith_ramanujan_tau()@ depends on the largest prime factor of \(n\).+-- +-- Future improvement: optimise this function for small \(n\), which could+-- be accomplished using a lookup table or by calling+-- @arith_ramanujan_tau_series()@ directly.+foreign import ccall "arith.h arith_ramanujan_tau"+ arith_ramanujan_tau :: Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /arith_ramanujan_tau_series/ /res/ /n/ +-- +-- Sets @res@ to the polynomial with coefficients+-- \(\tau(0),\tau(1), \dotsc, \tau(n-1)\), giving the initial \(n\) terms+-- in the series expansion of+-- \(f(q) = q \prod_{k \geq 1} \bigl(1-q^k\bigr)^{24}\).+-- +-- We use the theta function identity+-- +-- \[`\]+-- \[f(q) = q \Biggl( \sum_{k \geq 0} (-1)^k (2k+1) q^{k(k+1)/2} \Biggr)^8\]+-- +-- which is evaluated using three squarings. The first squaring is done+-- directly since the polynomial is very sparse at this point.+foreign import ccall "arith.h arith_ramanujan_tau_series"+ arith_ramanujan_tau_series :: Ptr CFmpzPoly -> CLong -> IO ()++-- Cyclotomic polynomials ------------------------------------------------------++-- -- | /_arith_cos_minpoly/ /coeffs/ /d/ /n/ +-- -- +-- -- For \(n \ge 1\), sets @(coeffs, d+1)@ to the minimal polynomial+-- -- \(\Psi_n(x)\) of \(\cos(2 \pi / n)\), scaled to have integer+-- -- coefficients by multiplying by \(2^d\) (2^{d-1} when \(n\) is a power of+-- -- two).+-- -- +-- -- The polynomial \(\Psi_n(x)\) is described in < [WaktinsZeitlin1993]>. As+-- -- proved in that paper, the roots of \(\Psi_n(x)\) for \(n \ge 3\) are+-- -- \(\cos(2 \pi k / n)\) where \(0 \le k < d\) and where+-- -- \(\gcd(k, n) = 1\).+-- -- +-- -- To calculate \(\Psi_n(x)\), we compute the roots numerically with MPFR+-- -- and use a balanced product tree to form a polynomial with fixed-point+-- -- coefficients, i.e. an approximation of \(2^p 2^d \Psi_n(x)\).+-- -- +-- -- To determine the precision \(p\), we note that the coefficients in+-- -- \(\prod_{i=1}^d (x - \alpha)\) can be bounded by the central coefficient+-- -- in the binomial expansion of \((x+1)^d\).+-- -- +-- -- When \(n\) is an odd prime, we use a direct formula for the coefficients+-- -- (<https://mathworld.wolfram.com/TrigonometryAngles.html> ).+-- foreign import ccall "arith.h _arith_cos_minpoly"+-- _arith_cos_minpoly :: Ptr CFmpz -> CLong -> CULong -> IO ()++-- -- | /arith_cos_minpoly/ /poly/ /n/ +-- -- +-- -- Sets @poly@ to the minimal polynomial \(\Psi_n(x)\) of+-- -- \(\cos(2 \pi / n)\), scaled to have integer coefficients. This+-- -- polynomial has degree 1 if \(n = 1\) or \(n = 2\), and degree+-- -- \(\phi(n) / 2\) otherwise.+-- -- +-- -- We allow \(n = 0\) and define \(\Psi_0 = 1\).+-- foreign import ccall "arith.h arith_cos_minpoly"+-- arith_cos_minpoly :: Ptr CFmpzPoly -> CULong -> IO ()++-- Landau\'s function ----------------------------------------------------------++-- | /arith_landau_function_vec/ /res/ /len/ +-- +-- Computes the first @len@ values of Landau\'s function \(g(n)\) starting+-- with \(g(0)\). Landau\'s function gives the largest order of an element+-- of the symmetric group \(S_n\).+-- +-- Implements the \"basic algorithm\" given in+-- < [DelegliseNicolasZimmermann2009]>. The running time is+-- \(O(n^{3/2} / \sqrt{\log n})\).+foreign import ccall "arith.h arith_landau_function_vec"+ arith_landau_function_vec :: Ptr CFmpz -> CLong -> IO ()++-- Number of partitions --------------------------------------------------------++-- | /arith_number_of_partitions_vec/ /res/ /len/ +-- +-- Computes first @len@ values of the partition function \(p(n)\) starting+-- with \(p(0)\). Uses inversion of Euler\'s pentagonal series.+foreign import ccall "arith.h arith_number_of_partitions_vec"+ arith_number_of_partitions_vec :: Ptr CFmpz -> CLong -> IO ()++-- | /arith_number_of_partitions_nmod_vec/ /res/ /len/ /mod/ +-- +-- Computes first @len@ values of the partition function \(p(n)\) starting+-- with \(p(0)\), modulo the modulus defined by @mod@. Uses inversion of+-- Euler\'s pentagonal series.+foreign import ccall "arith.h arith_number_of_partitions_nmod_vec"+ arith_number_of_partitions_nmod_vec :: Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /arith_hrr_expsum_factored/ /prod/ /k/ /n/ +-- +-- Symbolically evaluates the exponential sum+-- +-- \[`\]+-- \[A_k(n) = \sum_{h=0}^{k-1}+-- \exp\left(\pi i \left[ s(h,k) - \frac{2hn}{k}\right]\right)\]+-- +-- appearing in the Hardy-Ramanujan-Rademacher formula, where \(s(h,k)\) is+-- a Dedekind sum.+-- +-- Rather than evaluating the sum naively, we factor \(A_k(n)\) into a+-- product of cosines based on the prime factorisation of \(k\). This+-- process is based on the identities given in < [Whiteman1956]>.+-- +-- The special @trig_prod_t@ structure @prod@ represents a product of+-- cosines of rational arguments, multiplied by an algebraic prefactor. It+-- must be pre-initialised with @trig_prod_init@.+-- +-- This function assumes that \(24k\) and \(24n\) do not overflow a single+-- limb. If \(n\) is larger, it can be pre-reduced modulo \(k\), since+-- \(A_k(n)\) only depends on the value of \(n \bmod k\).+foreign import ccall "arith.h arith_hrr_expsum_factored"+ arith_hrr_expsum_factored :: Ptr CFTrigProd -> CMpLimb -> CMpLimb -> IO ()++-- | /arith_number_of_partitions_mpfr/ /x/ /n/ +-- +-- Sets the pre-initialised MPFR variable \(x\) to the exact value of+-- \(p(n)\). The value is computed using the Hardy-Ramanujan-Rademacher+-- formula.+-- +-- The precision of \(x\) will be changed to allow \(p(n)\) to be+-- represented exactly. The interface of this function may be updated in+-- the future to allow computing an approximation of \(p(n)\) to smaller+-- precision.+-- +-- The Hardy-Ramanujan-Rademacher formula is given with error bounds in+-- < [Rademacher1937]>. We evaluate it in the form+-- +-- \[`\]+-- \[p(n) = \sum_{k=1}^N B_k(n) U(C/k) + R(n,N)\]+-- +-- where+-- +-- \[`\]+-- \[U(x) = \cosh(x) + \frac{\sinh(x)}{x},+-- \quad C = \frac{\pi}{6} \sqrt{24n-1}\]+-- \[B_k(n) = \sqrt{\frac{3}{k}} \frac{4}{24n-1} A_k(n)\]+-- +-- and where \(A_k(n)\) is a certain exponential sum. The remainder+-- satisfies+-- +-- \[`\]+-- \[|R(n,N)| < \frac{44 \pi^2}{225 \sqrt{3}} N^{-1/2} ++-- \frac{\pi \sqrt{2}}{75} \left(\frac{N}{n-1}\right)^{1/2}+-- \sinh\left(\pi \sqrt{\frac{2}{3}} \frac{\sqrt{n}}{N} \right).\]+-- +-- We choose \(N\) such that \(|R(n,N)| < 0.25\), and a working precision+-- at term \(k\) such that the absolute error of the term is expected to be+-- less than \(0.25 / N\). We also use a summation variable with increased+-- precision, essentially making additions exact. Thus the sum of errors+-- adds up to less than 0.5, giving the correct value of \(p(n)\) when+-- rounding to the nearest integer.+-- +-- The remainder estimate at step \(k\) provides an upper bound for the+-- size of the \(k\)-th term. We add \(\log_2 N\) bits to get low bits in+-- the terms below \(0.25 / N\) in magnitude.+-- -- +-- -- Using @arith_hrr_expsum_factored@, each \(B_k(n)\) evaluation is broken+-- -- down to a product of cosines of exact rational multiples of \(\pi\). We+-- -- transform all angles to \((0, \pi/4)\) for optimal accuracy.+-- -- +-- -- Since the evaluation of each term involves only \(O(\log k)\)+-- -- multiplications and evaluations of trigonometric functions of small+-- -- angles, the relative rounding error is at most a few bits. We therefore+-- -- just add an additional \(\log_2 (C/k)\) bits for the \(U(x)\) when \(x\)+-- -- is large. The cancellation of terms in \(U(x)\) is of no concern, since+-- -- Rademacher\'s bound allows us to terminate before \(x\) becomes small.+-- -- +-- -- This analysis should be performed in more detail to give a rigorous+-- -- error bound, but the precision currently implemented is almost certainly+-- -- sufficient, not least considering that Rademacher\'s remainder bound+-- -- significantly overshoots the actual values.+-- -- +-- -- To improve performance, we switch to doubles when the working precision+-- -- becomes small enough. We also use a separate accumulator variable which+-- -- gets added to the main sum periodically, in order to avoid costly+-- -- updates of the full-precision result when \(n\) is large.+-- foreign import ccall "arith.h arith_number_of_partitions_mpfr"+-- arith_number_of_partitions_mpfr :: Ptr CMpfr -> CULong -> IO ()++-- | /arith_number_of_partitions/ /x/ /n/ +-- +-- Sets \(x\) to \(p(n)\), the number of ways that \(n\) can be written as+-- a sum of positive integers without regard to order.+-- +-- This function uses a lookup table for \(n < 128\) (where+-- \(p(n) < 2^{32}\)), and otherwise calls+-- @arith_number_of_partitions_mpfr@.+foreign import ccall "arith.h arith_number_of_partitions"+ arith_number_of_partitions :: Ptr CFmpz -> CULong -> IO ()++-- Sums of squares -------------------------------------------------------------++-- | /arith_sum_of_squares/ /r/ /k/ /n/ +-- +-- Sets \(r\) to the number of ways \(r_k(n)\) in which \(n\) can be+-- represented as a sum of \(k\) squares.+-- +-- If \(k = 2\) or \(k = 4\), we write \(r_k(n)\) as a divisor sum.+-- +-- Otherwise, we either recurse on \(k\) or compute the theta function+-- expansion up to \(O(x^{n+1})\) and read off the last coefficient. This+-- is generally optimal.+foreign import ccall "arith.h arith_sum_of_squares"+ arith_sum_of_squares :: Ptr CFmpz -> CULong -> Ptr CFmpz -> IO ()++-- | /arith_sum_of_squares_vec/ /r/ /k/ /n/ +-- +-- For \(i = 0, 1, \ldots, n-1\), sets \(r_i\) to the number of+-- representations of \(i\) a sum of \(k\) squares, \(r_k(i)\). This+-- effectively computes the \(q\)-expansion of \(\vartheta_3(q)\) raised to+-- the \(k\)-th power, i.e.+-- +-- \[`\]+-- \[\vartheta_3^k(q) = \left( \sum_{i=-\infty}^{\infty} q^{i^2} \right)^k.\]+foreign import ccall "arith.h arith_sum_of_squares_vec"+ arith_sum_of_squares_vec :: Ptr CFmpz -> CULong -> CLong -> IO ()+
+ src/Data/Number/Flint/Fmpz/FFI.hsc view
@@ -0,0 +1,2380 @@+{-|+module : Data.Number.Flint.Fmpz.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.FFI (+ -- * Integers @Fmpz@+ Fmpz+ , CFmpz+ -- * Constructors+ , newFmpz+ , withFmpz+ , withNewFmpz+ -- * Precomputed inverse+ , FmpzPreInvN (..)+ , CFmpzPreInvN (..)+ -- * Factorization structure @FmpzFactor@+ , FmpzFactor (..)+ , CFmpzFactor (..)+ -- * Memory management mpz+ , _fmpz_new_mpz+ , _fmpz_cleanup_mpz_content+ , _fmpz_cleanup+ , _fmpz_promote+ , _fmpz_promote_val+ , _fmpz_demote+ , _fmpz_demote_val+ -- * Memory management+ , fmpz_init+ , fmpz_init2+ , fmpz_clear+ , fmpz_init_set+ , fmpz_init_set_ui+ , fmpz_init_set_si+ -- * Random generation+ , fmpz_randbits+ , fmpz_randtest+ , fmpz_randtest_unsigned+ , fmpz_randtest_not_zero+ , fmpz_randm+ , fmpz_randtest_mod+ , fmpz_randtest_mod_signed+ , fmpz_randprime+ -- * Conversion+ , fmpz_get_si+ , fmpz_get_ui+ , fmpz_get_uiui+ , fmpz_get_nmod+ , fmpz_get_d+ , fmpz_set_mpf+ , fmpz_get_mpf+ , fmpz_get_mpfr+ , fmpz_get_d_2exp+ , fmpz_get_mpz+ , fmpz_get_mpn+ , fmpz_get_str+ , fmpz_set_si+ , fmpz_set_ui+ , fmpz_set_d+ , fmpz_set_d_2exp+ , fmpz_neg_ui+ , fmpz_set_uiui+ , fmpz_neg_uiui+ , fmpz_set_signed_uiui+ , fmpz_set_signed_uiuiui+ , fmpz_set_ui_array+ , fmpz_set_signed_ui_array+ , fmpz_get_ui_array+ , fmpz_get_signed_ui_array+ , fmpz_get_signed_uiui+ , fmpz_set_mpz+ , fmpz_set_str+ , fmpz_set_ui_smod+ , flint_mpz_init_set_readonly+ , flint_mpz_clear_readonly+ , fmpz_init_set_readonly+ , fmpz_clear_readonly+ -- * Input and output+ , fmpz_read+ , fmpz_fread+ , fmpz_inp_raw+ , fmpz_print+ , fmpz_fprint+ , fmpz_out_raw+ -- * Basic properties and manipulation+ , fmpz_sizeinbase+ , fmpz_bits+ , fmpz_size+ , fmpz_sgn+ , fmpz_val2+ , fmpz_swap+ , fmpz_set+ , fmpz_zero+ , fmpz_one+ , fmpz_abs_fits_ui+ , fmpz_fits_si+ , fmpz_setbit+ , fmpz_tstbit+ , fmpz_abs_lbound_ui_2exp+ , fmpz_abs_ubound_ui_2exp+ -- * Comparison+ , fmpz_cmp+ , fmpz_cmp_ui+ , fmpz_cmp_si+ , fmpz_cmpabs+ , fmpz_cmp2abs+ , fmpz_equal+ , fmpz_equal_ui+ , fmpz_equal_si+ , fmpz_is_zero+ , fmpz_is_one+ , fmpz_is_pm1+ , fmpz_is_even+ , fmpz_is_odd+ -- * Basic arithmetic+ , fmpz_neg+ , fmpz_abs+ , fmpz_add+ , fmpz_add_ui + , fmpz_add_si + , fmpz_sub+ , fmpz_sub_ui+ , fmpz_sub_si+ , fmpz_mul+ , fmpz_mul_ui+ , fmpz_mul_si+ , fmpz_mul2_uiui+ , fmpz_mul_2exp+ , fmpz_one_2exp+ , fmpz_addmul+ , fmpz_addmul_ui+ , fmpz_addmul_si+ , fmpz_submul+ , fmpz_submul_ui+ , fmpz_submul_si+ , fmpz_fmma+ , fmpz_fmms+ , fmpz_cdiv_qr+ , fmpz_fdiv_qr+ , fmpz_tdiv_qr+ , fmpz_ndiv_qr+ , fmpz_cdiv_q+ , fmpz_fdiv_q+ , fmpz_tdiv_q+ , fmpz_cdiv_q_si+ , fmpz_fdiv_q_si+ , fmpz_tdiv_q_si+ , fmpz_cdiv_q_ui+ , fmpz_fdiv_q_ui+ , fmpz_tdiv_q_ui+ , fmpz_cdiv_q_2exp+ , fmpz_fdiv_q_2exp+ , fmpz_tdiv_q_2exp+ , fmpz_fdiv_r+ , fmpz_cdiv_r_2exp+ , fmpz_fdiv_r_2exp+ , fmpz_tdiv_r_2exp+ , fmpz_cdiv_ui+ , fmpz_fdiv_ui+ , fmpz_tdiv_ui+ , fmpz_divexact+ , fmpz_divexact_si+ , fmpz_divexact_ui+ , fmpz_divexact2_uiui+ , fmpz_divisible+ , fmpz_divisible_si+ , fmpz_divides+ , fmpz_mod+ , fmpz_mod_ui+ , fmpz_smod+ , fmpz_preinvn_init+ , fmpz_preinvn_clear+ , fmpz_fdiv_qr_preinvn+ , fmpz_pow_ui+ , fmpz_pow_fmpz+ , fmpz_powm_ui+ , fmpz_powm+ , fmpz_clog+ , fmpz_flog+ , fmpz_dlog+ , fmpz_sqrtmod+ , fmpz_sqrt+ , fmpz_sqrtrem+ , fmpz_is_square+ , fmpz_root+ , fmpz_is_perfect_power+ , fmpz_fac_ui+ , fmpz_fib_ui+ , fmpz_bin_uiui+ , _fmpz_rfac_ui+ , fmpz_rfac_ui+ , fmpz_rfac_uiui+ , fmpz_mul_tdiv_q_2exp+ , fmpz_mul_si_tdiv_q_2exp+ -- * Greatest common divisor+ , fmpz_gcd_ui+ , fmpz_gcd+ , fmpz_gcd3+ , fmpz_lcm+ , fmpz_gcdinv+ , fmpz_xgcd+ , fmpz_xgcd_canonical_bezout+ , fmpz_xgcd_partial+ -- * Modular arithmetic+ , _fmpz_remove+ , fmpz_remove+ , fmpz_invmod+ , fmpz_negmod+ , fmpz_jacobi+ , fmpz_kronecker+ , fmpz_divides_mod_list+ -- * Bit packing and unpacking+ , fmpz_bit_pack+ , fmpz_bit_unpack+ , fmpz_bit_unpack_unsigned+ -- * Logic Operations+ , fmpz_complement+ , fmpz_clrbit+ , fmpz_combit+ , fmpz_and+ , fmpz_or+ , fmpz_xor+ , fmpz_popcnt+ -- * Chinese remaindering+ , fmpz_CRT_ui+ , fmpz_CRT+ , fmpz_multi_mod_ui+ , fmpz_multi_CRT_ui+ -- ** Comb for multi CRT+ , FmpzComb (..)+ , CFmpzComb (..)+ , FmpzCombTemp (..)+ , CFmpzCombTemp (..)+ , newFmpzComb+ , withFmpzComb+ , fmpz_comb_init+ , newFmpzCombTemp+ , withFmpzCombTemp+ , fmpz_comb_temp_init+ , fmpz_comb_clear+ , fmpz_comb_temp_clear+ -- ** Multi CRT+ , FmpzMultiCRT (..)+ , CFmpzMultiCRT(..)+ , newFmpzMultiCRT+ , withFmpzMultiCRT+ , fmpz_multi_CRT_init+ , fmpz_multi_CRT_precompute+ , fmpz_multi_CRT_precomp+ , fmpz_multi_CRT+ , fmpz_multi_CRT_clear+ -- * Primality testing+ , fmpz_is_strong_probabprime+ , fmpz_is_probabprime_lucas+ , fmpz_is_probabprime_BPSW+ , fmpz_is_probabprime+ , fmpz_is_prime_pseudosquare+ , fmpz_is_prime_pocklington+ , _fmpz_nm1_trial_factors+ , fmpz_is_prime_morrison+ , _fmpz_np1_trial_factors+ , fmpz_is_prime+ , fmpz_lucas_chain+ , fmpz_lucas_chain_full+ , fmpz_lucas_chain_double+ , fmpz_lucas_chain_add+ , fmpz_lucas_chain_mul+ , fmpz_lucas_chain_VtoU+ , fmpz_divisor_in_residue_class_lenstra+ , fmpz_nextprime+ -- * Special functions+ , fmpz_primorial+ , fmpz_factor_euler_phi+ , fmpz_euler_phi+ , fmpz_factor_moebius_mu+ , fmpz_moebius_mu+ , fmpz_factor_divisor_sigma+ , fmpz_divisor_sigma+) where++-- Integers --------------------------------------------------------------------++import System.IO.Unsafe++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, nullPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Int ( Int64 )+import Data.Bits+import Data.Functor ((<&>))++import Data.Number.Flint.Flint+import Data.Number.Flint.NMod+import Data.Number.Flint.NMod.Types++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_factor.h>++-- fmpz_t ----------------------------------------------------------------------++-- | Integer (opaque pointer)+data Fmpz = Fmpz {-# UNPACK #-} !(ForeignPtr CFmpz)+type CFmpz = CFlint Fmpz++instance Storable CFmpz where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_t}+ peek = error "CFmpz.peek: Not defined"+ poke = error "CFmpz.poke: Not defined"++-- fmpz_preinv_t --------------------------------------------------++-- | Data structure containing the /CFmpz/ pointer+data FmpzPreInvN = FmpzPreInvN {-# UNPACK #-} !(ForeignPtr CFmpzPreInvN) +type CFmpzPreInvN = CFlint FmpzPreInvN ++-- fmpz_comb_t -----------------------------------------------------------------++-- | Data structure containing /CFmpzComb/ pointer+data FmpzComb = FmpzComb {-# UNPACK #-} !(ForeignPtr CFmpzComb)+type CFmpzComb = CFlint FmpzComb++instance Storable CFmpzComb where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_comb_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_comb_t}+ peek = error "CFmpzComb.peek: Not defined"+ poke = error "CFmpzComb.poke: Not defined"++-- fmpz_comb_temp_t ------------------------------------------------------------++-- | Data structure containing /CFmpzCombTemp/ pointer+data FmpzCombTemp = FmpzCombTemp {-# UNPACK #-} !(ForeignPtr CFmpzCombTemp)+type CFmpzCombTemp = CFlint FmpzCombTemp++instance Storable CFmpzCombTemp where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_comb_temp_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_comb_temp_t}+ peek = error "CFmpzCombTemp.peek: Not defined"+ poke = error "CFmpzCombTemp.poke: Not defined"++-- fmpz_multi_crt_t ------------------------------------------------------------++-- | Data structure containing /CFmpzMultiCRT/ pointer+data FmpzMultiCRT = FmpzMultiCRT {-# UNPACK #-} !(ForeignPtr CFmpzMultiCRT)+type CFmpzMultiCRT = CFlint FmpzMultiCRT++instance Storable CFmpzMultiCRT where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_multi_CRT_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_multi_CRT_t}+ peek = error "CFmpzMultiCRT.peek: Not defined"+ poke = error "CFmpzMultiCRT.poke: Not defined"++-- fmpz_factor_t ---------------------------------------------------------------++-- | Data structure containing /CFmpzFactor/ pointer+data FmpzFactor = FmpzFactor {-# UNPACK #-} !(ForeignPtr CFmpzFactor)+data CFmpzFactor = CFmpzFactor CInt (Ptr CFmpz) (Ptr CULong) CLong CLong++instance Storable CFmpzFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_factor_t}+ peek ptr = CFmpzFactor+ <$> #{peek fmpz_factor_struct, sign } ptr+ <*> #{peek fmpz_factor_struct, p } ptr+ <*> #{peek fmpz_factor_struct, exp } ptr+ <*> #{peek fmpz_factor_struct, alloc} ptr+ <*> #{peek fmpz_factor_struct, num } ptr+ poke = error "CFmpzFactor.poke: Not defined"++-- Fmpz ------------------------------------------------------------------------++-- | /newFmpz/+--+-- Create a new `Fmpz`.+newFmpz = do+ x <- mallocForeignPtr+ withForeignPtr x fmpz_init+ addForeignPtrFinalizer p_fmpz_clear x+ return $ Fmpz x++-- | /withFmpz/ /x/ /f/+--+-- Apply /f/ to /x/.+{-# INLINE withFmpz #-}+withFmpz (Fmpz x) f = withForeignPtr x $ \xp -> f xp <&> (Fmpz x,)++-- | /withNewFmpz/ /f/+--+-- Apply /f/ to a new `Fmpz`.+{-# INLINE withNewFmpz #-}+withNewFmpz f = newFmpz >>= flip withFmpz f++--------------------------------------------------------------------------------++-- | /_fmpz_new_mpz/ +-- +-- initialises a new @mpz_t@ and returns a pointer to it. This is only used+-- internally.+foreign import ccall "fmpz.h _fmpz_new_mpz"+ _fmpz_new_mpz :: IO (Ptr CMpz)++-- | /_fmpz_cleanup_mpz_content/ +-- +-- this function does nothing in the reentrant version of @fmpz@.+foreign import ccall "fmpz.h _fmpz_cleanup_mpz_content"+ _fmpz_cleanup_mpz_content :: IO ()++-- | /_fmpz_cleanup/ +-- +-- this function does nothing in the reentrant version of @fmpz@.+foreign import ccall "fmpz.h _fmpz_cleanup"+ _fmpz_cleanup :: IO ()++-- | /_fmpz_promote/ /f/ +-- +-- if \(f\) doesn\'t represent an @mpz_t@, initialise one and associate it+-- to \(f\).+foreign import ccall "fmpz.h _fmpz_promote"+ _fmpz_promote :: Ptr CFmpz -> IO (Ptr CMpz)++-- | /_fmpz_promote_val/ /f/ +-- +-- if \(f\) doesn\'t represent an @mpz_t@, initialise one and associate it+-- to \(f\), but preserve the value of \(f\).+-- +-- This function is for internal use. The resulting @fmpz@ will be backed+-- by an @mpz_t@ that can be passed to GMP, but the @fmpz@ will be in an+-- inconsistent state with respect to the other Flint @fmpz@ functions such+-- as @fmpz_is_zero@, etc.+foreign import ccall "fmpz.h _fmpz_promote_val"+ _fmpz_promote_val :: Ptr CFmpz -> IO (Ptr CMpz)++-- | /_fmpz_demote/ /f/ +-- +-- if \(f\) represents an @mpz_t@ clear it and make \(f\) just represent an+-- @slong@.+foreign import ccall "fmpz.h _fmpz_demote"+ _fmpz_demote :: Ptr CFmpz -> IO ()++-- | /_fmpz_demote_val/ /f/ +-- +-- if \(f\) represents an @mpz_t@ and its value will fit in an @slong@,+-- preserve the value in \(f\) which we make to represent an @slong@, and+-- clear the @mpz_t@.+foreign import ccall "fmpz.h _fmpz_demote_val"+ _fmpz_demote_val :: Ptr CFmpz -> IO ()++-- Memory management -----------------------------------------------------------++-- | /fmpz_init/ /f/ +-- +-- A small @fmpz_t@ is initialised, i.e.just a @slong@. The value is set to+-- zero.+foreign import ccall "fmpz.h fmpz_init"+ fmpz_init :: Ptr CFmpz -> IO ()++foreign import ccall "p_fmpz_init"+ p_fmpz_init :: Ptr CFmpz -> IO ()++-- | /fmpz_init2/ /f/ /limbs/ +-- +-- Initialises the given @fmpz_t@ to have space for the given number of+-- limbs.+-- +-- If @limbs@ is zero then a small @fmpz_t@ is allocated, i.e.just a+-- @slong@. The value is also set to zero. It is not necessary to call this+-- function except to save time. A call to @fmpz_init@ will do just fine.+foreign import ccall "fmpz.h fmpz_init2"+ fmpz_init2 :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_clear/ /f/ +-- +-- Clears the given @fmpz_t@, releasing any memory associated with it,+-- either back to the stack or the OS, depending on whether the reentrant+-- or non-reentrant version of FLINT is built.+foreign import ccall "fmpz.h fmpz_clear"+ fmpz_clear :: Ptr CFmpz -> IO ()++-- foreign import ccall "fmpz.h &fmpz_clear"+foreign import ccall "&p_fmpz_clear"+ p_fmpz_clear :: FunPtr (Ptr CFmpz -> IO ())++foreign import ccall "fmpz.h fmpz_init_set"+ fmpz_init_set :: Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_init_set_ui"+ fmpz_init_set_ui :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_init_set_si/ /f/ /g/ +-- +-- Initialises \(f\) and sets it to the value of \(g\).+foreign import ccall "fmpz.h fmpz_init_set_si"+ fmpz_init_set_si :: Ptr CFmpz -> CLong -> IO ()++-- Random generation -----------------------------------------------------------++-- For thread-safety, the randomisation methods take as one of their+-- parameters an object of type @flint_rand_t@. Before calling any of the+-- randomisation functions such an object first has to be initialised with+-- a call to @flint_randinit@. When one is finished generating random+-- numbers, one should call @flint_randclear@ to clean up.+--+-- | /fmpz_randbits/ /f/ /state/ /bits/ +-- +-- Generates a random signed integer whose absolute value has precisely the+-- given number of bits.+foreign import ccall "fmpz.h fmpz_randbits"+ fmpz_randbits :: Ptr CFmpz -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /fmpz_randtest/ /f/ /state/ /bits/ +-- +-- Generates a random signed integer whose absolute value has a number of+-- bits which is random from \(0\) up to @bits@ inclusive.+foreign import ccall "fmpz.h fmpz_randtest"+ fmpz_randtest :: Ptr CFmpz -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /fmpz_randtest_unsigned/ /f/ /state/ /bits/ +-- +-- Generates a random unsigned integer whose value has a number of bits+-- which is random from \(0\) up to @bits@ inclusive.+foreign import ccall "fmpz.h fmpz_randtest_unsigned"+ fmpz_randtest_unsigned :: Ptr CFmpz -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /fmpz_randtest_not_zero/ /f/ /state/ /bits/ +-- +-- As per @fmpz_randtest@, but the result will not be \(0\). If @bits@ is+-- set to \(0\), an exception will result.+foreign import ccall "fmpz.h fmpz_randtest_not_zero"+ fmpz_randtest_not_zero :: Ptr CFmpz -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /fmpz_randm/ /f/ /state/ /m/ +-- +-- Generates a random integer in the range \(0\) to \(m - 1\) inclusive.+foreign import ccall "fmpz.h fmpz_randm"+ fmpz_randm :: Ptr CFmpz -> Ptr CFRandState -> Ptr CFmpz -> IO ()++-- | /fmpz_randtest_mod/ /f/ /state/ /m/ +-- +-- Generates a random integer in the range \(0\) to \(m - 1\) inclusive,+-- with an increased probability of generating values close to the+-- endpoints.+foreign import ccall "fmpz.h fmpz_randtest_mod"+ fmpz_randtest_mod :: Ptr CFmpz -> Ptr CFRandState -> Ptr CFmpz -> IO ()++-- | /fmpz_randtest_mod_signed/ /f/ /state/ /m/ +-- +-- Generates a random integer in the range \((-m/2, m/2]\), with an+-- increased probability of generating values close to the endpoints or+-- close to zero.+foreign import ccall "fmpz.h fmpz_randtest_mod_signed"+ fmpz_randtest_mod_signed :: Ptr CFmpz -> Ptr CFRandState -> Ptr CFmpz -> IO ()++-- | /fmpz_randprime/ /f/ /state/ /bits/ /proved/ +-- +-- Generates a random prime number with the given number of bits.+-- +-- The generation is performed by choosing a random number and then finding+-- the next largest prime, and therefore does not quite give a uniform+-- distribution over the set of primes with that many bits.+-- +-- Random number generation is performed using the standard Flint random+-- number generator, which is not suitable for cryptographic use.+-- +-- If @proved@ is nonzero, then the integer returned is guaranteed to+-- actually be prime.+foreign import ccall "fmpz.h fmpz_randprime"+ fmpz_randprime :: Ptr CFmpz -> Ptr CFRandState -> CFBitCnt -> CInt -> IO ()++-- Conversion ------------------------------------------------------------------++-- | /fmpz_get_si/ /f/ +-- +-- Returns \(f\) as a @slong@. The result is undefined if \(f\) does not+-- fit into a @slong@.+foreign import ccall "fmpz.h fmpz_get_si"+ fmpz_get_si :: Ptr CFmpz -> IO CLong++-- | /fmpz_get_ui/ /f/ +-- +-- Returns \(f\) as an @ulong@. The result is undefined if \(f\) does not+-- fit into an @ulong@ or is negative.+foreign import ccall "fmpz.h fmpz_get_ui"+ fmpz_get_ui :: Ptr CFmpz -> IO CULong++-- | /fmpz_get_uiui/ /hi/ /low/ /f/ +-- +-- If \(f\) consists of two limbs, then @*hi@ and @*low@ are set to the+-- high and low limbs, otherwise @*low@ is set to the low limb and @*hi@ is+-- set to \(0\).+foreign import ccall "fmpz.h fmpz_get_uiui"+ fmpz_get_uiui :: Ptr CMpLimb -> Ptr CMpLimb -> Ptr CFmpz -> IO ()++-- | /fmpz_get_nmod/ /f/ /mod/ +-- +-- Returns \(f \mod n\).+foreign import ccall "fmpz.h fmpz_get_nmod"+ fmpz_get_nmod :: Ptr CFmpz -> Ptr CNMod -> IO CMpLimb++-- | /fmpz_get_d/ /f/ +-- +-- Returns \(f\) as a @double@, rounding down towards zero if \(f\) cannot+-- be represented exactly. The outcome is undefined if \(f\) is too large+-- to fit in the normal range of a double.+foreign import ccall "fmpz.h fmpz_get_d"+ fmpz_get_d :: Ptr CFmpz -> IO CDouble++-- | /fmpz_set_mpf/ /f/ /x/ +-- +-- Sets \(f\) to the @mpf_t@ \(x\), rounding down towards zero if the value+-- of \(x\) is fractional.+foreign import ccall "fmpz.h fmpz_set_mpf"+ fmpz_set_mpf :: Ptr CFmpz -> Ptr CMpf -> IO ()++-- | /fmpz_get_mpf/ /x/ /f/ +-- +-- Sets the value of the @mpf_t@ \(x\) to the value of \(f\).+foreign import ccall "fmpz.h fmpz_get_mpf"+ fmpz_get_mpf :: Ptr CMpf -> Ptr CFmpz -> IO ()++-- | /fmpz_get_mpfr/ /x/ /f/ /rnd/ +-- +-- Sets the value of \(x\) from \(f\), rounded toward the given direction+-- @rnd@.+foreign import ccall "fmpz.h fmpz_get_mpfr"+ fmpz_get_mpfr :: Ptr CMpfr -> Ptr CFmpz -> CMpfrRnd -> IO ()++-- | /fmpz_get_d_2exp/ /exp/ /f/ +-- +-- Returns \(f\) as a normalized @double@ along with a \(2\)-exponent+-- @exp@, i.e.if \(r\) is the return value then \(f = r 2^{exp}\), to+-- within 1 ULP.+foreign import ccall "fmpz.h fmpz_get_d_2exp"+ fmpz_get_d_2exp :: Ptr CLong -> Ptr CFmpz -> IO CDouble++-- | /fmpz_get_mpz/ /x/ /f/ +-- +-- Sets the @mpz_t@ \(x\) to the same value as \(f\).+foreign import ccall "fmpz.h fmpz_get_mpz"+ fmpz_get_mpz :: Ptr CMpz -> Ptr CFmpz -> IO ()++-- | /fmpz_get_mpn/ /n/ /n_in/ +-- +-- Sets the @mp_ptr@ \(n\) to the same value as \(n_{in}\). Returned+-- integer is number of limbs allocated to \(n\), minimum number of limbs+-- required to hold the value stored in \(n_{in}\).+foreign import ccall "fmpz.h fmpz_get_mpn"+ fmpz_get_mpn :: Ptr CMp -> Ptr CFmpz -> IO CInt++-- | /fmpz_get_str/ /str/ /b/ /f/ +-- +-- Returns the representation of \(f\) in base \(b\), which can vary+-- between \(2\) and \(62\), inclusive.+-- +-- If @str@ is @NULL@, the result string is allocated by the function.+-- Otherwise, it is up to the caller to ensure that the allocated block of+-- memory is sufficiently large.+foreign import ccall "fmpz.h fmpz_get_str"+ fmpz_get_str :: CString -> CInt -> Ptr CFmpz -> IO CString++-- | /fmpz_set_si/ /f/ /val/ +-- +-- Sets \(f\) to the given @slong@ value.+foreign import ccall "fmpz.h fmpz_set_si"+ fmpz_set_si :: Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_set_ui/ /f/ /val/ +-- +-- Sets \(f\) to the given @ulong@ value.+foreign import ccall "fmpz.h fmpz_set_ui"+ fmpz_set_ui :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_set_d/ /f/ /c/ +-- +-- Sets \(f\) to the @double@ \(c\), rounding down towards zero if the+-- value of \(c\) is fractional. The outcome is undefined if \(c\) is+-- infinite, not-a-number, or subnormal.+foreign import ccall "fmpz.h fmpz_set_d"+ fmpz_set_d :: Ptr CFmpz -> CDouble -> IO ()++-- | /fmpz_set_d_2exp/ /f/ /d/ /exp/ +-- +-- Sets \(f\) to the nearest integer to \(d 2^{exp}\).+foreign import ccall "fmpz.h fmpz_set_d_2exp"+ fmpz_set_d_2exp :: Ptr CFmpz -> CDouble -> CLong -> IO ()++-- | /fmpz_neg_ui/ /f/ /val/ +-- +-- Sets \(f\) to the given @ulong@ value, and then negates \(f\).+foreign import ccall "fmpz.h fmpz_neg_ui"+ fmpz_neg_ui :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_set_uiui/ /f/ /hi/ /lo/ +-- +-- Sets \(f\) to @lo@, plus @hi@ shifted to the left by @FLINT_BITS@.+foreign import ccall "fmpz.h fmpz_set_uiui"+ fmpz_set_uiui :: Ptr CFmpz -> CMpLimb -> CMpLimb -> IO ()++-- | /fmpz_neg_uiui/ /f/ /hi/ /lo/ +-- +-- Sets \(f\) to @lo@, plus @hi@ shifted to the left by @FLINT_BITS@, and+-- then negates \(f\).+foreign import ccall "fmpz.h fmpz_neg_uiui"+ fmpz_neg_uiui :: Ptr CFmpz -> CMpLimb -> CMpLimb -> IO ()++-- | /fmpz_set_signed_uiui/ /f/ /hi/ /lo/ +-- +-- Sets \(f\) to @lo@, plus @hi@ shifted to the left by @FLINT_BITS@,+-- interpreted as a signed two\'s complement integer with @2 * FLINT_BITS@+-- bits.+foreign import ccall "fmpz.h fmpz_set_signed_uiui"+ fmpz_set_signed_uiui :: Ptr CFmpz -> CULong -> CULong -> IO ()++-- | /fmpz_set_signed_uiuiui/ /f/ /hi/ /mid/ /lo/ +-- +-- Sets \(f\) to @lo@, plus @mid@ shifted to the left by @FLINT_BITS@, plus+-- @hi@ shifted to the left by @2*FLINT_BITS@ bits, interpreted as a signed+-- two\'s complement integer with @3 * FLINT_BITS@ bits.+foreign import ccall "fmpz.h fmpz_set_signed_uiuiui"+ fmpz_set_signed_uiuiui :: Ptr CFmpz -> CULong -> CULong -> CULong -> IO ()++-- | /fmpz_set_ui_array/ /out/ /in/ /n/ +-- +-- Sets @out@ to the nonnegative integer+-- @in[0] + in[1]*X + ... + in[n - 1]*X^(n - 1)@ where @X = 2^FLINT_BITS@.+-- It is assumed that @n > 0@.+foreign import ccall "fmpz.h fmpz_set_ui_array"+ fmpz_set_ui_array :: Ptr CFmpz -> Ptr CULong -> CLong -> IO ()++-- | /fmpz_set_signed_ui_array/ /out/ /in/ /n/ +-- +-- Sets @out@ to the integer represented in @in[0], ..., in[n - 1]@ as a+-- signed two\'s complement integer with @n * FLINT_BITS@ bits. It is+-- assumed that @n > 0@. The function operates as a call to+-- @fmpz_set_ui_array@ followed by a symmetric remainder modulo+-- \(2^(n*FLINT\_BITS)\).+foreign import ccall "fmpz.h fmpz_set_signed_ui_array"+ fmpz_set_signed_ui_array :: Ptr CFmpz -> Ptr CULong -> CLong -> IO ()++-- | /fmpz_get_ui_array/ /out/ /n/ /in/ +-- +-- Assuming that the nonnegative integer @in@ can be represented in the+-- form @out[0] + out[1]*X + ... + out[n - 1]*X^(n - 1)@, where+-- \(X = 2^{FLINT\_BITS}\), sets the corresponding elements of @out@ so+-- that this is true. It is assumed that @n > 0@.+foreign import ccall "fmpz.h fmpz_get_ui_array"+ fmpz_get_ui_array :: Ptr CULong -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_get_signed_ui_array/ /out/ /n/ /in/ +-- +-- Retrieves the value of \(in\) modulo \(2^{n * FLINT\_BITS}\) and puts+-- the \(n\) words of the result in @out[0], ..., out[n-1]@. This will give+-- a signed two\'s complement representation of \(in\) (assuming \(in\)+-- doesn\'t overflow the array).+foreign import ccall "fmpz.h fmpz_get_signed_ui_array"+ fmpz_get_signed_ui_array :: Ptr CULong -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_get_signed_uiui/ /hi/ /lo/ /in/ +-- +-- Retrieves the value of \(in\) modulo \(2^{2 * FLINT\_BITS}\) and puts+-- the high and low words into @*hi@ and @*lo@ respectively.+foreign import ccall "fmpz.h fmpz_get_signed_uiui"+ fmpz_get_signed_uiui :: Ptr CULong -> Ptr CULong -> Ptr CFmpz -> IO ()++-- | /fmpz_set_mpz/ /f/ /x/ +-- +-- Sets \(f\) to the given @mpz_t@ value.+foreign import ccall "fmpz.h fmpz_set_mpz"+ fmpz_set_mpz :: Ptr CFmpz -> Ptr CMpz -> IO ()++-- | /fmpz_set_str/ /f/ /str/ /b/ +-- +-- Sets \(f\) to the value given in the null-terminated string @str@, in+-- base \(b\). The base \(b\) can vary between \(2\) and \(62\), inclusive.+-- Returns \(0\) if the string contains a valid input and \(-1\) otherwise.+foreign import ccall "fmpz.h fmpz_set_str"+ fmpz_set_str :: Ptr CFmpz -> CString -> CInt -> IO CInt++-- | /fmpz_set_ui_smod/ /f/ /x/ /m/ +-- +-- Sets \(f\) to the signed remainder \(y \equiv x \bmod m\) satisfying+-- \(-m/2 < y \leq m/2\), given \(x\) which is assumed to satisfy+-- \(0 \leq x < m\).+foreign import ccall "fmpz.h fmpz_set_ui_smod"+ fmpz_set_ui_smod :: Ptr CFmpz -> CMpLimb -> CMpLimb -> IO ()++-- | /flint_mpz_init_set_readonly/ /z/ /f/ +-- +-- Sets the uninitialised @mpz_t@ \(z\) to the value of the readonly+-- @fmpz_t@ \(f\).+-- +-- Note that it is assumed that \(f\) does not change during the lifetime+-- of \(z\).+-- +-- The integer \(z\) has to be cleared by a call to+-- @flint_mpz_clear_readonly@.+-- +-- The suggested use of the two functions is as follows:+-- +-- > fmpz_t f;+-- > ...+-- > {+-- > mpz_t z;+-- >+-- > flint_mpz_init_set_readonly(z, f);+-- > foo(..., z);+-- > flint_mpz_clear_readonly(z);+-- > }+-- +-- This provides a convenient function for user code, only requiring to+-- work with the types @fmpz_t@ and @mpz_t@.+-- +-- In critical code, the following approach may be favourable:+-- +-- > fmpz_t f;+-- > ...+-- > {+-- > __mpz_struct *z;+-- >+-- > z = _fmpz_promote_val(f);+-- > foo(..., z);+-- > _fmpz_demote_val(f);+-- > }+foreign import ccall "fmpz.h flint_mpz_init_set_readonly"+ flint_mpz_init_set_readonly :: Ptr CMpz -> Ptr CFmpz -> IO ()++-- | /flint_mpz_clear_readonly/ /z/ +-- +-- Clears the readonly @mpz_t@ \(z\).+foreign import ccall "fmpz.h flint_mpz_clear_readonly"+ flint_mpz_clear_readonly :: Ptr CMpz -> IO ()++-- | /fmpz_init_set_readonly/ /f/ /z/ +-- +-- Sets the uninitialised @fmpz_t@ \(f\) to a readonly version of the+-- integer \(z\).+-- +-- Note that the value of \(z\) is assumed to remain constant throughout+-- the lifetime of \(f\).+-- +-- The @fmpz_t@ \(f\) has to be cleared by calling the function+-- @fmpz_clear_readonly@.+-- +-- The suggested use of the two functions is as follows:+-- +-- > mpz_t z;+-- > ...+-- > {+-- > fmpz_t f;+-- >+-- > fmpz_init_set_readonly(f, z);+-- > foo(..., f);+-- > fmpz_clear_readonly(f);+-- > }+foreign import ccall "fmpz.h fmpz_init_set_readonly"+ fmpz_init_set_readonly :: Ptr CFmpz -> Ptr CMpz -> IO ()++-- | /fmpz_clear_readonly/ /f/ +-- +-- Clears the readonly @fmpz_t@ \(f\).+foreign import ccall "fmpz.h fmpz_clear_readonly"+ fmpz_clear_readonly :: Ptr CFmpz -> IO ()++-- Input and output ------------------------------------------------------------++-- | /fmpz_read/ /f/ +-- +-- Reads a multiprecision integer from @stdin@. The format is an optional+-- minus sign, followed by one or more digits. The first digit should be+-- non-zero unless it is the only digit.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive number.+-- +-- This convention is adopted in light of the return values of @scanf@ from+-- the standard library and @mpz_inp_str@ from MPIR.+foreign import ccall "fmpz.h fmpz_read"+ fmpz_read :: Ptr CFmpz -> IO CInt++-- | /fmpz_fread/ /file/ /f/ +-- +-- Reads a multiprecision integer from the stream @file@. The format is an+-- optional minus sign, followed by one or more digits. The first digit+-- should be non-zero unless it is the only digit.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive number.+-- +-- This convention is adopted in light of the return values of @scanf@ from+-- the standard library and @mpz_inp_str@ from MPIR.+foreign import ccall "fmpz.h fmpz_fread"+ fmpz_fread :: Ptr CFile -> Ptr CFmpz -> IO CInt++-- | /fmpz_inp_raw/ /x/ /fin/ +-- +-- Reads a multiprecision integer from the stream @file@. The format is raw+-- binary format write by @fmpz_out_raw@.+-- +-- In case of success, return a positive number, indicating number of bytes+-- read. In case of failure 0.+-- +-- This function calls the @mpz_inp_raw@ function in library gmp. So that+-- it can read the raw data written by @mpz_inp_raw@ directly.+foreign import ccall "fmpz.h fmpz_inp_raw"+ fmpz_inp_raw :: Ptr CFmpz -> Ptr CFile -> IO (Ptr CSize)++-- | /fmpz_print/ /x/ +-- +-- Prints the value \(x\) to @stdout@, without a carriage return(CR). The+-- value is printed as either \(0\), the decimal digits of a positive+-- integer, or a minus sign followed by the digits of a negative integer.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive number.+-- +-- This convention is adopted in light of the return values of+-- @flint_printf@ from the standard library and @mpz_out_str@ from MPIR.+fmpz_print :: Ptr CFmpz -> IO CInt+fmpz_print x = printCStr (fmpz_get_str nullPtr 10) x++-- | /fmpz_fprint/ /file/ /x/ +-- +-- Prints the value \(x\) to @file@, without a carriage return(CR). The+-- value is printed as either \(0\), the decimal digits of a positive+-- integer, or a minus sign followed by the digits of a negative integer.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive number.+-- +-- This convention is adopted in light of the return values of+-- @flint_printf@ from the standard library and @mpz_out_str@ from MPIR.+foreign import ccall "fmpz.h fmpz_fprint"+ fmpz_fprint :: Ptr CFile -> Ptr CFmpz -> IO CInt++-- | /fmpz_out_raw/ /fout/ /x/ +-- +-- Writes the value \(x\) to @file@. The value is written in raw binary+-- format. The integer is written in portable format, with 4 bytes of size+-- information, and that many bytes of limbs. Both the size and the limbs+-- are written in decreasing significance order (i.e., in big-endian).+-- +-- The output can be read with @fmpz_inp_raw@.+-- +-- In case of success, return a positive number, indicating number of bytes+-- written. In case of failure, return 0.+-- +-- The output of this can also be read by @mpz_inp_raw@ from GMP >= 2,+-- Since this function calls the @mpz_inp_raw@ function in library gmp.+foreign import ccall "fmpz.h fmpz_out_raw"+ fmpz_out_raw :: Ptr CFile -> Ptr CFmpz -> IO (Ptr CSize)++-- Basic properties and manipulation -------------------------------------------++-- | /fmpz_sizeinbase/ /f/ /b/ +-- +-- Returns the size of the absolute value of \(f\) in base \(b\), measured+-- in numbers of digits. The base \(b\) can be between \(2\) and \(62\),+-- inclusive.+foreign import ccall "fmpz.h fmpz_sizeinbase"+ fmpz_sizeinbase :: Ptr CFmpz -> CInt -> IO (Ptr CSize)++-- | /fmpz_bits/ /f/ +-- +-- Returns the number of bits required to store the absolute value of+-- \(f\). If \(f\) is \(0\) then \(0\) is returned.+foreign import ccall "fmpz.h fmpz_bits"+ fmpz_bits :: Ptr CFmpz -> IO CFBitCnt++-- | /fmpz_size/ /f/ +-- +-- Returns the number of limbs required to store the absolute value of+-- \(f\). If \(f\) is zero then \(0\) is returned.+foreign import ccall "fmpz.h fmpz_size"+ fmpz_size :: Ptr CFmpz -> IO CMpSize++-- | /fmpz_sgn/ /f/ +-- +-- Returns \(-1\) if the sign of \(f\) is negative, \(+1\) if it is+-- positive, otherwise returns \(0\).+foreign import ccall "fmpz.h fmpz_sgn"+ fmpz_sgn :: Ptr CFmpz -> IO CInt++-- | /fmpz_val2/ /f/ +-- +-- Returns the exponent of the largest power of two dividing \(f\), or+-- equivalently the number of trailing zeros in the binary expansion of+-- \(f\). If \(f\) is zero then \(0\) is returned.+foreign import ccall "fmpz.h fmpz_val2"+ fmpz_val2 :: Ptr CFmpz -> IO CFBitCnt++-- | /fmpz_swap/ /f/ /g/ +-- +-- Efficiently swaps \(f\) and \(g\). No data is copied.+foreign import ccall "fmpz.h fmpz_swap"+ fmpz_swap :: Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_set/ /f/ /g/ +-- +-- Sets \(f\) to the same value as \(g\).+foreign import ccall "fmpz.h fmpz_set"+ fmpz_set :: Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_zero/ /f/ +-- +-- Sets \(f\) to zero.+foreign import ccall "fmpz.h fmpz_zero"+ fmpz_zero :: Ptr CFmpz -> IO ()++-- | /fmpz_one/ /f/ +-- +-- Sets \(f\) to one.+foreign import ccall "fmpz.h fmpz_one"+ fmpz_one :: Ptr CFmpz -> IO ()++-- | /fmpz_abs_fits_ui/ /f/ +-- +-- Returns whether the absolute value of \(f\) fits into an @ulong@.+foreign import ccall "fmpz.h fmpz_abs_fits_ui"+ fmpz_abs_fits_ui :: Ptr CFmpz -> IO CInt++-- | /fmpz_fits_si/ /f/ +-- +-- Returns whether the value of \(f\) fits into a @slong@.+foreign import ccall "fmpz.h fmpz_fits_si"+ fmpz_fits_si :: Ptr CFmpz -> IO CInt++-- | /fmpz_setbit/ /f/ /i/ +-- +-- Sets bit index \(i\) of \(f\).+foreign import ccall "fmpz.h fmpz_setbit"+ fmpz_setbit :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_tstbit/ /f/ /i/ +-- +-- Test bit index \(i\) of \(f\) and return \(0\) or \(1\), accordingly.+foreign import ccall "fmpz.h fmpz_tstbit"+ fmpz_tstbit :: Ptr CFmpz -> CULong -> IO CInt++-- | /fmpz_abs_lbound_ui_2exp/ /exp/ /x/ /bits/ +-- +-- For nonzero \(x\), returns a mantissa \(m\) with exactly @bits@ bits and+-- sets @exp@ to an exponent \(e\), such that \(|x| \ge m 2^e\). The number+-- of bits must be between 1 and @FLINT_BITS@ inclusive. The mantissa is+-- guaranteed to be correctly rounded.+foreign import ccall "fmpz.h fmpz_abs_lbound_ui_2exp"+ fmpz_abs_lbound_ui_2exp :: Ptr CLong -> Ptr CFmpz -> CInt -> IO CMpLimb++-- | /fmpz_abs_ubound_ui_2exp/ /exp/ /x/ /bits/ +-- +-- For nonzero \(x\), returns a mantissa \(m\) with exactly @bits@ bits and+-- sets @exp@ to an exponent \(e\), such that \(|x| \le m 2^e\). The number+-- of bits must be between 1 and @FLINT_BITS@ inclusive. The mantissa is+-- either correctly rounded or one unit too large (possibly meaning that+-- the exponent is one too large, if the mantissa is a power of two).+foreign import ccall "fmpz.h fmpz_abs_ubound_ui_2exp"+ fmpz_abs_ubound_ui_2exp :: Ptr CLong -> Ptr CFmpz -> CInt -> IO CMpLimb++-- Comparison ------------------------------------------------------------------++foreign import ccall "fmpz.h fmpz_cmp"+ fmpz_cmp :: Ptr CFmpz -> Ptr CFmpz -> IO CInt++foreign import ccall "fmpz.h fmpz_cmp_ui"+ fmpz_cmp_ui :: Ptr CFmpz -> CULong -> IO CInt++-- | /fmpz_cmp_si/ /f/ /g/ +-- +-- Returns a negative value if \(f < g\), positive value if \(g < f\),+-- otherwise returns \(0\).+foreign import ccall "fmpz.h fmpz_cmp_si"+ fmpz_cmp_si :: Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_cmpabs/ /f/ /g/ +-- +-- Returns a negative value if \(\lvert f\rvert < \lvert g\rvert\),+-- positive value if \(\lvert g\rvert < \lvert f \rvert\), otherwise+-- returns \(0\).+foreign import ccall "fmpz.h fmpz_cmpabs"+ fmpz_cmpabs :: Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- | /fmpz_cmp2abs/ /f/ /g/ +-- +-- Returns a negative value if \(\lvert f\rvert < \lvert 2g\rvert\),+-- positive value if \(\lvert 2g\rvert < \lvert f \rvert\), otherwise+-- returns \(0\).+foreign import ccall "fmpz.h fmpz_cmp2abs"+ fmpz_cmp2abs :: Ptr CFmpz -> Ptr CFmpz -> IO CInt++foreign import ccall "fmpz.h fmpz_equal"+ fmpz_equal :: Ptr CFmpz -> Ptr CFmpz -> IO CInt++foreign import ccall "fmpz.h fmpz_equal_ui"+ fmpz_equal_ui :: Ptr CFmpz -> CULong -> IO CInt++-- | /fmpz_equal_si/ /f/ /g/ +-- +-- Returns \(1\) if \(f\) is equal to \(g\), otherwise returns \(0\).+foreign import ccall "fmpz.h fmpz_equal_si"+ fmpz_equal_si :: Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_is_zero/ /f/ +-- +-- Returns \(1\) if \(f\) is \(0\), otherwise returns \(0\).+foreign import ccall "fmpz.h fmpz_is_zero"+ fmpz_is_zero :: Ptr CFmpz -> IO CInt++-- | /fmpz_is_one/ /f/ +-- +-- Returns \(1\) if \(f\) is equal to one, otherwise returns \(0\).+foreign import ccall "fmpz.h fmpz_is_one"+ fmpz_is_one :: Ptr CFmpz -> IO CInt++-- | /fmpz_is_pm1/ /f/ +-- +-- Returns \(1\) if \(f\) is equal to one or minus one, otherwise returns+-- \(0\).+foreign import ccall "fmpz.h fmpz_is_pm1"+ fmpz_is_pm1 :: Ptr CFmpz -> IO CInt++-- | /fmpz_is_even/ /f/ +-- +-- Returns whether the integer \(f\) is even.+foreign import ccall "fmpz.h fmpz_is_even"+ fmpz_is_even :: Ptr CFmpz -> IO CInt++-- | /fmpz_is_odd/ /f/ +-- +-- Returns whether the integer \(f\) is odd.+foreign import ccall "fmpz.h fmpz_is_odd"+ fmpz_is_odd :: Ptr CFmpz -> IO CInt++-- Basic arithmetic ------------------------------------------------------------++-- | /fmpz_neg/ /f1/ /f2/ +-- +-- Sets \(f_1\) to \(-f_2\).+foreign import ccall "fmpz.h fmpz_neg"+ fmpz_neg :: Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_abs/ /f1/ /f2/ +-- +-- Sets \(f_1\) to the absolute value of \(f_2\).+foreign import ccall "fmpz.h fmpz_abs"+ fmpz_abs :: Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_add/ /f/ /g/ /h/ +-- +-- Sets \(f\) to \(g + h\).+foreign import ccall "fmpz.h fmpz_add"+ fmpz_add :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_add_ui"+ fmpz_add_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_add_si"+ fmpz_add_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_sub/ /f/ /g/ /h/ +-- +-- Sets \(f\) to \(g - h\).+foreign import ccall "fmpz.h fmpz_sub"+ fmpz_sub :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_sub_ui"+ fmpz_sub_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_sub_si"+ fmpz_sub_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_mul/ /f/ /g/ /h/ +-- +-- Sets \(f\) to \(g \times h\).+foreign import ccall "fmpz.h fmpz_mul"+ fmpz_mul :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_mul_ui"+ fmpz_mul_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_mul_si"+ fmpz_mul_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()+ +-- | /fmpz_mul2_uiui/ /f/ /g/ /x/ /y/ +-- +-- Sets \(f\) to \(g \times x \times y\) where \(x\) and \(y\) are of type+-- @ulong@.+foreign import ccall "fmpz.h fmpz_mul2_uiui"+ fmpz_mul2_uiui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CULong -> IO ()++-- | /fmpz_mul_2exp/ /f/ /g/ /e/ +-- +-- Sets \(f\) to \(g \times 2^e\).+-- +-- Note: Assumes that @e + FLINT_BITS@ does not overflow.+foreign import ccall "fmpz.h fmpz_mul_2exp"+ fmpz_mul_2exp :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_one_2exp/ /f/ /e/ +-- +-- Sets \(f\) to \(2^e\).+foreign import ccall "fmpz.h fmpz_one_2exp"+ fmpz_one_2exp :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_addmul/ /f/ /g/ /h/ +-- +-- Sets \(f\) to \(f + g \times h\).+foreign import ccall "fmpz.h fmpz_addmul"+ fmpz_addmul :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_addmul_ui"+ fmpz_addmul_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_addmul_si"+ fmpz_addmul_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_submul/ /f/ /g/ /h/ +-- +-- Sets \(f\) to \(f - g \times h\).+foreign import ccall "fmpz.h fmpz_submul"+ fmpz_submul :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_submul_ui"+ fmpz_submul_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_submul_si"+ fmpz_submul_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_fmma/ /f/ /a/ /b/ /c/ /d/ +-- +-- Sets \(f\) to \(a \times b + c \times d\).+foreign import ccall "fmpz.h fmpz_fmma"+ fmpz_fmma :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_fmms/ /f/ /a/ /b/ /c/ /d/ +-- +-- Sets \(f\) to \(a \times b - c \times d\).+foreign import ccall "fmpz.h fmpz_fmms"+ fmpz_fmms :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_cdiv_qr"+ fmpz_cdiv_qr :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_fdiv_qr"+ fmpz_fdiv_qr :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_tdiv_qr"+ fmpz_tdiv_qr :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_ndiv_qr"+ fmpz_ndiv_qr :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_cdiv_q"+ fmpz_cdiv_q :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_fdiv_q"+ fmpz_fdiv_q :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_tdiv_q"+ fmpz_tdiv_q :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_cdiv_q_si"+ fmpz_cdiv_q_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "fmpz.h fmpz_fdiv_q_si"+ fmpz_fdiv_q_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "fmpz.h fmpz_tdiv_q_si"+ fmpz_tdiv_q_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++foreign import ccall "fmpz.h fmpz_cdiv_q_ui"+ fmpz_cdiv_q_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_fdiv_q_ui"+ fmpz_fdiv_q_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_tdiv_q_ui"+ fmpz_tdiv_q_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_cdiv_q_2exp"+ fmpz_cdiv_q_2exp :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_fdiv_q_2exp"+ fmpz_fdiv_q_2exp :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_tdiv_q_2exp"+ fmpz_tdiv_q_2exp :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_fdiv_r"+ fmpz_fdiv_r :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_cdiv_r_2exp"+ fmpz_cdiv_r_2exp :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_fdiv_r_2exp"+ fmpz_fdiv_r_2exp :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_tdiv_r_2exp/ /s/ /g/ /exp/ +-- +-- Sets \(f\) to the quotient of \(g\) by \(h\) and\/or \(s\) to the+-- remainder. For the @2exp@ functions, @g = 2^exp@. \(If :math:`h\) is+-- \(0\) an exception is raised.+-- +-- Rounding is made in the following way:+-- +-- - @fdiv@ rounds the quotient via floor rounding.+-- - @cdiv@ rounds the quotient via ceil rounding.+-- - @tdiv@ rounds the quotient via truncation, i.e. rounding towards+-- zero.+-- - @ndiv@ rounds the quotient such that the remainder has the smallest+-- absolute value. In case of ties, it rounds the quotient towards+-- zero.+foreign import ccall "fmpz.h fmpz_tdiv_r_2exp"+ fmpz_tdiv_r_2exp :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_cdiv_ui"+ fmpz_cdiv_ui :: Ptr CFmpz -> CULong -> IO CULong++foreign import ccall "fmpz.h fmpz_fdiv_ui"+ fmpz_fdiv_ui :: Ptr CFmpz -> CULong -> IO CULong++-- | /fmpz_tdiv_ui/ /g/ /h/ +-- +-- Returns the absolute value remainder of \(g\) divided by \(h\),+-- following the convention of rounding as seen above. If \(h\) is zero an+-- exception is raised.+foreign import ccall "fmpz.h fmpz_tdiv_ui"+ fmpz_tdiv_ui :: Ptr CFmpz -> CULong -> IO CULong++foreign import ccall "fmpz.h fmpz_divexact"+ fmpz_divexact :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++foreign import ccall "fmpz.h fmpz_divexact_si"+ fmpz_divexact_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_divexact_ui/ /f/ /g/ /h/ +-- +-- Sets \(f\) to the quotient of \(g\) and \(h\), assuming that the+-- division is exact, i.e.\(g\) is a multiple of \(h\). If \(h\) is \(0\)+-- an exception is raised.+foreign import ccall "fmpz.h fmpz_divexact_ui"+ fmpz_divexact_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_divexact2_uiui/ /f/ /g/ /x/ /y/ +-- +-- Sets \(f\) to the quotient of \(g\) and \(h = x \times y\), assuming+-- that the division is exact, i.e.\(g\) is a multiple of \(h\). If \(x\)+-- or \(y\) is \(0\) an exception is raised.+foreign import ccall "fmpz.h fmpz_divexact2_uiui"+ fmpz_divexact2_uiui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CULong -> IO ()++foreign import ccall "fmpz.h fmpz_divisible"+ fmpz_divisible :: Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- | /fmpz_divisible_si/ /f/ /g/ +-- +-- Returns \(1\) if there is an integer \(q\) with \(f = q g\) and \(0\) if+-- there is none.+foreign import ccall "fmpz.h fmpz_divisible_si"+ fmpz_divisible_si :: Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_divides/ /q/ /g/ /h/ +-- +-- Returns \(1\) if there is an integer \(q\) with \(f = q g\) and sets+-- \(q\) to the quotient. Otherwise returns \(0\) and sets \(q\) to \(0\).+foreign import ccall "fmpz.h fmpz_divides"+ fmpz_divides :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- | /fmpz_mod/ /f/ /g/ /h/ +-- +-- Sets \(f\) to the remainder of \(g\) divided by \(h\) such that the+-- remainder is positive. Assumes that \(h\) is not zero.+foreign import ccall "fmpz.h fmpz_mod"+ fmpz_mod :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_ui/ /f/ /g/ /h/ +-- +-- Sets \(f\) to the remainder of \(g\) divided by \(h\) such that the+-- remainder is positive and also returns this value. Raises an exception+-- if \(h\) is zero.+foreign import ccall "fmpz.h fmpz_mod_ui"+ fmpz_mod_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO CULong++-- | /fmpz_smod/ /f/ /g/ /h/ +-- +-- Sets \(f\) to the signed remainder \(y \equiv g \bmod h\) satisfying+-- \(-\lvert h \rvert/2 < y \leq \lvert h\rvert/2\).+foreign import ccall "fmpz.h fmpz_smod"+ fmpz_smod :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_preinvn_init/ /inv/ /f/ +-- +-- Compute a precomputed inverse @inv@ of @f@ for use in the @preinvn@+-- functions listed below.+foreign import ccall "fmpz.h fmpz_preinvn_init"+ fmpz_preinvn_init :: Ptr CFmpzPreInvN -> Ptr CFmpz -> IO ()++-- | /fmpz_preinvn_clear/ /inv/ +-- +-- Clean up the resources used by a precomputed inverse created with the+-- @fmpz_preinvn_init@ function.+foreign import ccall "fmpz.h fmpz_preinvn_clear"+ fmpz_preinvn_clear :: Ptr CFmpzPreInvN -> IO ()++-- | /fmpz_fdiv_qr_preinvn/ /f/ /s/ /g/ /h/ /hinv/ +-- +-- As per @fmpz_fdiv_qr@, but takes a precomputed inverse @hinv@ of \(h\)+-- constructed using @fmpz_preinvn@.+-- +-- This function will be faster than @fmpz_fdiv_qr_preinvn@ when the number+-- of limbs of \(h\) is at least @PREINVN_CUTOFF@.+foreign import ccall "fmpz.h fmpz_fdiv_qr_preinvn"+ fmpz_fdiv_qr_preinvn :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzPreInvN -> IO ()++-- | /fmpz_pow_ui/ /f/ /g/ /x/ +-- +-- Sets \(f\) to \(g^x\). Defines \(0^0 = 1\).+foreign import ccall "fmpz.h fmpz_pow_ui"+ fmpz_pow_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_pow_fmpz/ /f/ /g/ /x/ +-- +-- Sets \(f\) to \(g^x\). Defines \(0^0 = 1\). Return \(1\) for success and+-- \(0\) for failure. The function throws only if \(x\) is negative.+foreign import ccall "fmpz.h fmpz_pow_fmpz"+ fmpz_pow_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO CInt++foreign import ccall "fmpz.h fmpz_powm_ui"+ fmpz_powm_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> Ptr CFmpz -> IO ()++-- | /fmpz_powm/ /f/ /g/ /e/ /m/ +-- +-- Sets \(f\) to \(g^e \bmod{m}\). If \(e = 0\), sets \(f\) to \(1\).+-- +-- Assumes that \(m \neq 0\), raises an @abort@ signal otherwise.+foreign import ccall "fmpz.h fmpz_powm"+ fmpz_powm :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_clog/ /x/ /b/ +-- +-- Returns \(\lceil\log_b x\rceil\).+-- +-- Assumes that \(x \geq 1\) and \(b \geq 2\) and that the return value+-- fits into a signed @slong@.+foreign import ccall "fmpz.h fmpz_clog"+ fmpz_clog :: Ptr CFmpz -> Ptr CFmpz -> IO CLong++-- | /fmpz_flog/ /x/ /b/ +-- +-- Returns \(\lfloor\log_b x\rfloor\).+-- +-- Assumes that \(x \geq 1\) and \(b \geq 2\) and that the return value+-- fits into a signed @slong@.+foreign import ccall "fmpz.h fmpz_flog"+ fmpz_flog :: Ptr CFmpz -> Ptr CFmpz -> IO CLong++-- | /fmpz_dlog/ /x/ +-- +-- Returns a double precision approximation of the natural logarithm of+-- \(x\).+-- +-- The accuracy depends on the implementation of the floating-point+-- logarithm provided by the C standard library. The result can typically+-- be expected to have a relative error no greater than 1-2 bits.+foreign import ccall "fmpz.h fmpz_dlog"+ fmpz_dlog :: Ptr CFmpz -> IO CDouble++-- | /fmpz_sqrtmod/ /b/ /a/ /p/ +-- +-- If \(p\) is prime, set \(b\) to a square root of \(a\) modulo \(p\) if+-- \(a\) is a quadratic residue modulo \(p\) and return \(1\), otherwise+-- return \(0\).+-- +-- If \(p\) is not prime the return value is with high probability \(0\),+-- indicating that \(p\) is not prime, or \(a\) is not a square modulo+-- \(p\). If \(p\) is not prime and the return value is \(1\), the value of+-- \(b\) is meaningless.+foreign import ccall "fmpz.h fmpz_sqrtmod"+ fmpz_sqrtmod :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- | /fmpz_sqrt/ /f/ /g/ +-- +-- Sets \(f\) to the integer part of the square root of \(g\), where \(g\)+-- is assumed to be non-negative. If \(g\) is negative, an exception is+-- raised.+foreign import ccall "fmpz.h fmpz_sqrt"+ fmpz_sqrt :: Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_sqrtrem/ /f/ /r/ /g/ +-- +-- Sets \(f\) to the integer part of the square root of \(g\), where \(g\)+-- is assumed to be non-negative, and sets \(r\) to the remainder, that is,+-- the difference \(g - f^2\). If \(g\) is negative, an exception is+-- raised. The behaviour is undefined if \(f\) and \(r\) are aliases.+foreign import ccall "fmpz.h fmpz_sqrtrem"+ fmpz_sqrtrem :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_is_square/ /f/ +-- +-- Returns nonzero if \(f\) is a perfect square and zero otherwise.+foreign import ccall "fmpz.h fmpz_is_square"+ fmpz_is_square :: Ptr CFmpz -> IO CInt++-- | /fmpz_root/ /r/ /f/ /n/ +-- +-- Set \(r\) to the integer part of the \(n\)-th root of \(f\). Requires+-- that \(n > 0\) and that if \(n\) is even then \(f\) be non-negative,+-- otherwise an exception is raised. The function returns \(1\) if the root+-- was exact, otherwise \(0\).+foreign import ccall "fmpz.h fmpz_root"+ fmpz_root :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_is_perfect_power/ /root/ /f/ +-- +-- If \(f\) is a perfect power \(r^k\) set @root@ to \(r\) and return+-- \(k\), otherwise return \(0\). Note that \(-1, 0, 1\) are all considered+-- perfect powers. No guarantee is made about \(r\) or \(k\) being the+-- smallest possible value. Negative values of \(f\) are permitted.+foreign import ccall "fmpz.h fmpz_is_perfect_power"+ fmpz_is_perfect_power :: Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- | /fmpz_fac_ui/ /f/ /n/ +-- +-- Sets \(f\) to the factorial \(n!\) where \(n\) is an @ulong@.+foreign import ccall "fmpz.h fmpz_fac_ui"+ fmpz_fac_ui :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_fib_ui/ /f/ /n/ +-- +-- Sets \(f\) to the Fibonacci number \(F_n\) where \(n\) is an @ulong@.+foreign import ccall "fmpz.h fmpz_fib_ui"+ fmpz_fib_ui :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_bin_uiui/ /f/ /n/ /k/ +-- +-- Sets \(f\) to the binomial coefficient \({n \choose k}\).+foreign import ccall "fmpz.h fmpz_bin_uiui"+ fmpz_bin_uiui :: Ptr CFmpz -> CULong -> CULong -> IO ()++-- | /_fmpz_rfac_ui/ /r/ /x/ /a/ /b/ +-- +-- Sets \(r\) to the rising factorial+-- \((x+a) (x+a+1) (x+a+2) \cdots (x+b-1)\). Assumes \(b > a\).+foreign import ccall "fmpz.h _fmpz_rfac_ui"+ _fmpz_rfac_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CULong -> IO ()++-- | /fmpz_rfac_ui/ /r/ /x/ /k/ +-- +-- Sets \(r\) to the rising factorial \(x (x+1) (x+2) \cdots (x+k-1)\).+foreign import ccall "fmpz.h fmpz_rfac_ui"+ fmpz_rfac_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_rfac_uiui/ /r/ /x/ /k/ +-- +-- Sets \(r\) to the rising factorial \(x (x+1) (x+2) \cdots (x+k-1)\).+foreign import ccall "fmpz.h fmpz_rfac_uiui"+ fmpz_rfac_uiui :: Ptr CFmpz -> CULong -> CULong -> IO ()++-- | /fmpz_mul_tdiv_q_2exp/ /f/ /g/ /h/ /exp/ +-- +-- Sets \(f\) to the product \(g\) and \(h\) divided by @2^exp@, rounding+-- down towards zero.+foreign import ccall "fmpz.h fmpz_mul_tdiv_q_2exp"+ fmpz_mul_tdiv_q_2exp :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_mul_si_tdiv_q_2exp/ /f/ /g/ /x/ /exp/ +-- +-- Sets \(f\) to the product \(g\) and \(x\) divided by @2^exp@, rounding+-- down towards zero.+foreign import ccall "fmpz.h fmpz_mul_si_tdiv_q_2exp"+ fmpz_mul_si_tdiv_q_2exp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- Greatest common divisor -----------------------------------------------------++foreign import ccall "fmpz.h fmpz_gcd_ui"+ fmpz_gcd_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_gcd/ /f/ /g/ /h/ +-- +-- Sets \(f\) to the greatest common divisor of \(g\) and \(h\). The result+-- is always positive, even if one of \(g\) and \(h\) is negative.+foreign import ccall "fmpz.h fmpz_gcd"+ fmpz_gcd :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_gcd3/ /f/ /a/ /b/ /c/ +-- +-- Sets \(f\) to the greatest common divisor of \(a\), \(b\) and \(c\).+-- This is equivalent to calling @fmpz_gcd@ twice, but may be faster.+foreign import ccall "fmpz.h fmpz_gcd3"+ fmpz_gcd3 :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_lcm/ /f/ /g/ /h/ +-- +-- Sets \(f\) to the least common multiple of \(g\) and \(h\). The result+-- is always nonnegative, even if one of \(g\) and \(h\) is negative.+foreign import ccall "fmpz.h fmpz_lcm"+ fmpz_lcm :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_gcdinv/ /d/ /a/ /f/ /g/ +-- +-- Given integers \(f, g\) with \(0 \leq f < g\), computes the greatest+-- common divisor \(d = \gcd(f, g)\) and the modular inverse+-- \(a = f^{-1} \pmod{g}\), whenever \(f \neq 0\).+-- +-- Assumes that \(d\) and \(a\) are not aliased.+foreign import ccall "fmpz.h fmpz_gcdinv"+ fmpz_gcdinv :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_xgcd/ /d/ /a/ /b/ /f/ /g/ +-- +-- Computes the extended GCD of \(f\) and \(g\), i.e. the values \(a\) and+-- \(b\) such that \(af + bg = d\), where \(d = \gcd(f, g)\). Here \(a\)+-- will be the same as calling @fmpz_gcdinv@ when \(f < g\) (or vice versa+-- for \(b\) when \(g < f\)).+-- +-- To obtain the canonical solution to Bézout\'s identity, call+-- @fmpz_xgcd_canonical_bezout@ instead. This is also faster.+-- +-- Assumes that there is no aliasing among the outputs.+foreign import ccall "fmpz.h fmpz_xgcd"+ fmpz_xgcd :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_xgcd_canonical_bezout/ /d/ /a/ /b/ /f/ /g/ +-- +-- Computes the extended GCD \(\mathrm{xgcd}(f, g) = (d, a, b)\) such+-- that the solution is the canonical solution to Bézout\'s identity. We+-- define the canonical solution to satisfy one of the following if one of+-- the given conditions apply:+--+-- \[\begin{aligned}+-- \operatorname{xgcd}(\pm g, g) &= \bigl(|g|, 0, \operatorname{sgn}(g)\bigr)\\+-- \operatorname{xgcd}(f, 0) &= \bigl(|f|, \operatorname{sgn}(f), 0\bigr)\\+-- \operatorname{xgcd}(0, g) &= \bigl(|g|, 0, \operatorname{sgn}(g)\bigr)\\+-- \operatorname{xgcd}(f, \mp 1) &= (1, 0, \mp 1)\\+-- \operatorname{xgcd}(\mp 1, g) &= (1, \mp 1, 0)\quad g \neq 0, \pm 1\\+-- \operatorname{xgcd}(\mp 2 d, g) &=+-- \bigl(d, {\textstyle\frac{d - |g|}{\mp 2 d}}, \operatorname{sgn}(g)\bigr)\\+-- \operatorname{xgcd}(f, \mp 2 d) &=+-- \bigl(d, \operatorname{sgn}(f), {\textstyle\frac{d - |g|}{\mp 2 d}}\bigr).+-- \end{aligned}\]+-- +-- If the pair \((f, g)\) does not satisfy any of these conditions, the+-- solution \((d, a, b)\) will satisfy the following:+-- +-- \[`\]+-- \[|a| < \Bigl| \frac{g}{2 d} \Bigr|,+-- \qquad |b| < \Bigl| \frac{f}{2 d} \Bigr|.\]+-- +-- Assumes that there is no aliasing among the outputs.+foreign import ccall "fmpz.h fmpz_xgcd_canonical_bezout"+ fmpz_xgcd_canonical_bezout :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_xgcd_partial/ /co2/ /co1/ /r2/ /r1/ /L/ +-- +-- This function is an implementation of Lehmer extended GCD with early+-- termination, as used in the @qfb@ module. It terminates early when+-- remainders fall below the specified bound. The initial values @r1@ and+-- @r2@ are treated as successive remainders in the Euclidean algorithm and+-- are replaced with the last two remainders computed. The values @co1@ and+-- @co2@ are the last two cofactors and satisfy the identity+-- @co2*r1 - co1*r2 == +\/- r2_orig@ upon termination, where @r2_orig@ is+-- the starting value of @r2@ supplied, and @r1@ and @r2@ are the final+-- values.+-- +-- Aliasing of inputs is not allowed. Similarly aliasing of inputs and+-- outputs is not allowed.+foreign import ccall "fmpz.h fmpz_xgcd_partial"+ fmpz_xgcd_partial :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- Modular arithmetic ----------------------------------------------------------++-- | /_fmpz_remove/ /x/ /f/ /finv/ +-- +-- Removes all factors \(f\) from \(x\) and returns the number of such.+-- +-- Assumes that \(x\) is non-zero, that \(f > 1\) and that @finv@ is the+-- precomputed @double@ inverse of \(f\) whenever \(f\) is a small integer+-- and \(0\) otherwise.+-- +-- Does not support aliasing.+foreign import ccall "fmpz.h _fmpz_remove"+ _fmpz_remove :: Ptr CFmpz -> Ptr CFmpz -> CDouble -> IO CLong++-- | /fmpz_remove/ /rop/ /op/ /f/ +-- +-- Remove all occurrences of the factor \(f > 1\) from the integer @op@ and+-- sets @rop@ to the resulting integer.+-- +-- If @op@ is zero, sets @rop@ to @op@ and returns \(0\).+-- +-- Returns an @abort@ signal if any of the assumptions are violated.+foreign import ccall "fmpz.h fmpz_remove"+ fmpz_remove :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO CLong++-- | /fmpz_invmod/ /f/ /g/ /h/ +-- +-- Sets \(f\) to the inverse of \(g\) modulo \(h\). The value of \(h\) may+-- not be \(0\) otherwise an exception results. If the inverse exists the+-- return value will be non-zero, otherwise the return value will be \(0\)+-- and the value of \(f\) undefined. As a special case, we consider any+-- number invertible modulo \(h = \pm 1\), with inverse 0.+foreign import ccall "fmpz.h fmpz_invmod"+ fmpz_invmod :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- | /fmpz_negmod/ /f/ /g/ /h/ +-- +-- Sets \(f\) to \(-g \pmod{h}\), assuming \(g\) is reduced modulo \(h\).+foreign import ccall "fmpz.h fmpz_negmod"+ fmpz_negmod :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_jacobi/ /a/ /n/ +-- +-- Computes the Jacobi symbol \(\left(\frac{a}{n}\right)\) for any \(a\)+-- and odd positive \(n\).+foreign import ccall "fmpz.h fmpz_jacobi"+ fmpz_jacobi :: Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- | /fmpz_kronecker/ /a/ /n/ +-- +-- Computes the Kronecker symbol \(\left(\frac{a}{n}\right)\) for any \(a\)+-- and any \(n\).+foreign import ccall "fmpz.h fmpz_kronecker"+ fmpz_kronecker :: Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- | /fmpz_divides_mod_list/ /xstart/ /xstride/ /xlength/ /a/ /b/ /n/ +-- +-- Set \(xstart\), \(xstride\), and \(xlength\) so that the solution set+-- for x modulo \(n\) in \(a x = b mod n\) is exactly+-- \(\{xstart + xstride i | 0 \le i < xlength\}\). This function+-- essentially gives a list of possibilities for the fraction \(a/b\)+-- modulo \(n\). The outputs may not be aliased, and \(n\) should be+-- positive.+foreign import ccall "fmpz.h fmpz_divides_mod_list"+ fmpz_divides_mod_list :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- Bit packing and unpacking ---------------------------------------------------++-- | /fmpz_bit_pack/ /arr/ /shift/ /bits/ /coeff/ /negate/ /borrow/ +-- +-- Shifts the given coefficient to the left by @shift@ bits and adds it to+-- the integer in @arr@ in a field of the given number of bits:+-- +-- > shift bits --------------+-- >+-- > X X X C C C C 0 0 0 0 0 0 0+-- +-- An optional borrow of \(1\) can be subtracted from @coeff@ before it is+-- packed. If @coeff@ is negative after the borrow, then a borrow will be+-- returned by the function.+-- +-- The value of @shift@ is assumed to be less than @FLINT_BITS@. All but+-- the first @shift@ bits of @arr@ are assumed to be zero on entry to the+-- function.+-- +-- The value of @coeff@ may also be optionally (and notionally) negated+-- before it is used, by setting the @negate@ parameter to \(-1\).+foreign import ccall "fmpz.h fmpz_bit_pack"+ fmpz_bit_pack :: Ptr CMpLimb -> CFBitCnt -> CFBitCnt -> Ptr CFmpz -> CInt -> CInt -> IO CInt++-- | /fmpz_bit_unpack/ /coeff/ /arr/ /shift/ /bits/ /negate/ /borrow/ +-- +-- A bit field of the given number of bits is extracted from @arr@,+-- starting after @shift@ bits, and placed into @coeff@. An optional borrow+-- of \(1\) may be added to the coefficient. If the result is negative, a+-- borrow of \(1\) is returned. Finally, the resulting @coeff@ may be+-- negated by setting the @negate@ parameter to \(-1\).+-- +-- The value of @shift@ is expected to be less than @FLINT_BITS@.+foreign import ccall "fmpz.h fmpz_bit_unpack"+ fmpz_bit_unpack :: Ptr CFmpz -> Ptr CMpLimb -> CFBitCnt -> CFBitCnt -> CInt -> CInt -> IO CInt++-- | /fmpz_bit_unpack_unsigned/ /coeff/ /arr/ /shift/ /bits/ +-- +-- A bit field of the given number of bits is extracted from @arr@,+-- starting after @shift@ bits, and placed into @coeff@.+-- +-- The value of @shift@ is expected to be less than @FLINT_BITS@.+foreign import ccall "fmpz.h fmpz_bit_unpack_unsigned"+ fmpz_bit_unpack_unsigned :: Ptr CFmpz -> Ptr CMpLimb -> CFBitCnt -> CFBitCnt -> IO ()++-- Logic Operations ------------------------------------------------------------++-- | /fmpz_complement/ /r/ /f/ +-- +-- The variable @r@ is set to the ones-complement of @f@.+foreign import ccall "fmpz.h fmpz_complement"+ fmpz_complement :: Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_clrbit/ /f/ /i/ +-- +-- Sets the @i@th bit in @f@ to zero.+foreign import ccall "fmpz.h fmpz_clrbit"+ fmpz_clrbit :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_combit/ /f/ /i/ +-- +-- Complements the @i@th bit in @f@.+foreign import ccall "fmpz.h fmpz_combit"+ fmpz_combit :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_and/ /r/ /a/ /b/ +-- +-- Sets @r@ to the bit-wise logical @and@ of @a@ and @b@.+foreign import ccall "fmpz.h fmpz_and"+ fmpz_and :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_or/ /r/ /a/ /b/ +-- +-- Sets @r@ to the bit-wise logical (inclusive) @or@ of @a@ and @b@.+foreign import ccall "fmpz.h fmpz_or"+ fmpz_or :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_xor/ /r/ /a/ /b/ +-- +-- Sets @r@ to the bit-wise logical exclusive @or@ of @a@ and @b@.+foreign import ccall "fmpz.h fmpz_xor"+ fmpz_xor :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_popcnt/ /a/ +-- +-- Returns the number of \'1\' bits in the given Z (aka Hamming weight or+-- population count). The return value is undefined if the input is+-- negative.+foreign import ccall "fmpz.h fmpz_popcnt"+ fmpz_popcnt :: Ptr CFmpz -> IO CInt++-- FmpzComb --------------------------------------------------------------------++newFmpzComb primes num_primes = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p -> fmpz_comb_init p primes num_primes+ addForeignPtrFinalizer p_fmpz_comb_clear p+ return $ FmpzComb p++{-# INLINE withFmpzCombTemp #-}+withFmpzComb (FmpzComb p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpzComb p,)++-- FmpzCombTemp ----------------------------------------------------------------++newFmpzCombTemp comb = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p -> fmpz_comb_temp_init p comb+ addForeignPtrFinalizer p_fmpz_comb_temp_clear p+ return $ FmpzCombTemp p++{-# INLINE withFmpzComb #-}+withFmpzCombTemp (FmpzCombTemp p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpzCombTemp p,)++-- Chinese remaindering --------------------------------------------------------++-- The following functions can be used to reconstruct an integer from its+-- residues modulo a set of small (word-size) prime numbers. The first two+-- functions, @fmpz_CRT_ui@ and @fmpz_CRT@, are easy to use and allow+-- building the result one residue at a time, which is useful when the+-- number of needed primes is not known in advance. The remaining functions+-- support performing the modular reductions and reconstruction using+-- balanced subdivision. This greatly improves efficiency for large+-- integers but assumes that the basis of primes is known in advance. The+-- user must precompute a @comb@ structure and temporary working space with+-- @fmpz_comb_init@ and @fmpz_comb_temp_init@, and free this data+-- afterwards. For simple demonstration programs showing how to use the CRT+-- functions, see @crt.c@ and @multi_crt.c@ in the @examples@ directory.+-- The @fmpz_multi_crt@ class is similar to @fmpz_multi_CRT_ui@ except that+-- it performs error checking and works with arbitrary moduli.+--+-- | /fmpz_CRT_ui/ /out/ /r1/ /m1/ /r2/ /m2/ /sign/ +-- +-- Uses the Chinese Remainder Theorem to compute the unique integer+-- \(0 \le x < M\) (if sign = 0) or \(-M/2 < x \le M/2\) (if sign = 1)+-- congruent to \(r_1\) modulo \(m_1\) and \(r_2\) modulo \(m_2\), where+-- where \(M = m_1 \times m_2\). The result \(x\) is stored in @out@.+-- +-- It is assumed that \(m_1\) and \(m_2\) are positive integers greater+-- than \(1\) and coprime.+-- +-- If sign = 0, it is assumed that \(0 \le r_1 < m_1\) and+-- \(0 \le r_2 < m_2\). Otherwise, it is assumed that+-- \(-m_1 \le r_1 < m_1\) and \(0 \le r_2 < m_2\).+foreign import ccall "fmpz.h fmpz_CRT_ui"+ fmpz_CRT_ui :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CULong -> CULong -> CInt -> IO ()++-- | /fmpz_CRT/ /out/ /r1/ /m1/ /r2/ /m2/ /sign/ +-- +-- Use the Chinese Remainder Theorem to set @out@ to the unique value+-- \(0 \le x < M\) (if sign = 0) or \(-M/2 < x \le M/2\) (if sign = 1)+-- congruent to \(r_1\) modulo \(m_1\) and \(r_2\) modulo \(m_2\), where+-- where \(M = m_1 \times m_2\).+-- +-- It is assumed that \(m_1\) and \(m_2\) are positive integers greater+-- than \(1\) and coprime.+-- +-- If sign = 0, it is assumed that \(0 \le r_1 < m_1\) and+-- \(0 \le r_2 < m_2\). Otherwise, it is assumed that+-- \(-m_1 \le r_1 < m_1\) and \(0 \le r_2 < m_2\).+foreign import ccall "fmpz.h fmpz_CRT"+ fmpz_CRT :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CInt -> IO ()++-- | /fmpz_multi_mod_ui/ /out/ /in/ /comb/ /temp/ +-- +-- Reduces the multiprecision integer @in@ modulo each of the primes stored+-- in the @comb@ structure. The array @out@ will be filled with the+-- residues modulo these primes. The structure @temp@ is temporary space+-- which must be provided by @fmpz_comb_temp_init@ and cleared by+-- @fmpz_comb_temp_clear@.+foreign import ccall "fmpz.h fmpz_multi_mod_ui"+ fmpz_multi_mod_ui :: Ptr CMpLimb -> Ptr CFmpz -> Ptr CFmpzComb -> Ptr CFmpzCombTemp -> IO ()++-- | /fmpz_multi_CRT_ui/ /output/ /residues/ /comb/ /ctemp/ /sign/ +-- +-- This function takes a set of residues modulo the list of primes+-- contained in the @comb@ structure and reconstructs a multiprecision+-- integer modulo the product of the primes which has these residues modulo+-- the corresponding primes.+-- +-- If \(N\) is the product of all the primes then @out@ is normalised to be+-- in the range \([0, N)\) if sign = 0 and the range \([-(N-1)/2, N/2]\) if+-- sign = 1. The array @temp@ is temporary space which must be provided by+-- @fmpz_comb_temp_init@ and cleared by @fmpz_comb_temp_clear@.+foreign import ccall "fmpz.h fmpz_multi_CRT_ui"+ fmpz_multi_CRT_ui :: Ptr CFmpz -> Ptr CMp -> Ptr CFmpzComb -> Ptr CFmpzCombTemp -> CInt -> IO ()++--------------------------------------------------------------------------------++-- | /fmpz_comb_init/ /comb/ /primes/ /num_primes/ +-- +-- Initialises a @comb@ structure for multimodular reduction and+-- recombination. The array @primes@ is assumed to contain @num_primes@+-- primes each of @FLINT_BITS - 1@ bits. Modular reductions and+-- recombinations will be done modulo this list of primes. The @primes@+-- array must not be @free@\'d until the @comb@ structure is no longer+-- required and must be cleared by the user.+foreign import ccall "fmpz.h fmpz_comb_init"+ fmpz_comb_init :: Ptr CFmpzComb -> Ptr CMp -> CLong -> IO ()++-- | /fmpz_comb_temp_init/ /temp/ /comb/ +-- +-- Creates temporary space to be used by multimodular and CRT functions+-- based on an initialised @comb@ structure.+foreign import ccall "fmpz.h fmpz_comb_temp_init"+ fmpz_comb_temp_init :: Ptr CFmpzCombTemp -> Ptr CFmpzComb -> IO ()++-- | /fmpz_comb_clear/ /comb/ +-- +-- Clears the given @comb@ structure, releasing any memory it uses.+foreign import ccall "fmpz.h fmpz_comb_clear"+ fmpz_comb_clear :: Ptr CFmpzComb -> IO ()++foreign import ccall "fmpz.h &fmpz_comb_clear"+ p_fmpz_comb_clear :: FunPtr (Ptr CFmpzComb -> IO ())++-- | /fmpz_comb_temp_clear/ /temp/ +-- +-- Clears temporary space @temp@ used by multimodular and CRT functions+-- using the given @comb@ structure.+foreign import ccall "fmpz.h fmpz_comb_temp_clear"+ fmpz_comb_temp_clear :: Ptr CFmpzCombTemp -> IO ()++foreign import ccall "fmpz.h &fmpz_comb_temp_clear"+ p_fmpz_comb_temp_clear :: FunPtr (Ptr CFmpzCombTemp -> IO ())++-- FmpzMultiCRT ----------------------------------------------------------------++newFmpzMultiCRT = do+ p <- mallocForeignPtr+ withForeignPtr p fmpz_multi_CRT_init+ addForeignPtrFinalizer p_fmpz_multi_CRT_clear p+ return $ FmpzMultiCRT p++{-# INLINE withFmpzMultiCRT #-}+withFmpzMultiCRT (FmpzMultiCRT p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpzMultiCRT p,)++-- | /fmpz_multi_CRT_init/ /CRT/ +-- +-- Initialize @CRT@ for Chinese remaindering.+foreign import ccall "fmpz.h fmpz_multi_CRT_init"+ fmpz_multi_CRT_init :: Ptr CFmpzMultiCRT -> IO ()++-- | /fmpz_multi_CRT_precompute/ /CRT/ /moduli/ /len/ +-- +-- Configure @CRT@ for repeated Chinese remaindering of @moduli@. The+-- number of moduli, @len@, should be positive. A return of @0@ indicates+-- that the compilation failed and future calls to @fmpz_crt_precomp@ will+-- leave the output undefined. A return of @1@ indicates that the+-- compilation was successful, which occurs if and only if either (1)+-- @len == 1@ and @modulus + 0@ is nonzero, or (2) no modulus is \(0,1,-1\)+-- and all moduli are pairwise relatively prime.+foreign import ccall "fmpz.h fmpz_multi_CRT_precompute"+ fmpz_multi_CRT_precompute :: Ptr CFmpzMultiCRT -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_multi_CRT_precomp/ /output/ /P/ /inputs/ +-- +-- Set @output@ to an integer of smallest absolute value that is congruent+-- to @values + i@ modulo the @moduli + i@ in @fmpz_crt_precompute@.+foreign import ccall "fmpz.h fmpz_multi_CRT_precomp"+ fmpz_multi_CRT_precomp :: Ptr CFmpz -> Ptr CFmpzMultiCRT -> Ptr CFmpz -> IO ()++-- | /fmpz_multi_CRT/ /output/ /moduli/ /values/ /len/ +-- +-- Perform the same operation as @fmpz_multi_CRT_precomp@ while internally+-- constructing and destroying the precomputed data. All of the remarks in+-- @fmpz_multi_CRT_precompute@ apply.+foreign import ccall "fmpz.h fmpz_multi_CRT"+ fmpz_multi_CRT :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_multi_CRT_clear/ /P/ +-- +-- Free all space used by @CRT@.+foreign import ccall "fmpz.h fmpz_multi_CRT_clear"+ fmpz_multi_CRT_clear :: Ptr CFmpzMultiCRT -> IO ()++foreign import ccall "fmpz.h &fmpz_multi_CRT_clear"+ p_fmpz_multi_CRT_clear :: FunPtr (Ptr CFmpzMultiCRT -> IO ())++-- not presentin fmpz.h in flintlib 2.9.0 --------------------------------------+-- -- | /_nmod_poly_crt_local_size/ /CRT/ +-- -- +-- -- Return the required length of the output for @_nmod_poly_crt_run@.+-- foreign import ccall "fmpz.h _nmod_poly_crt_local_size"+-- _nmod_poly_crt_local_size :: Ptr CNModPolyCRT -> IO CLong++-- not present in flintlib 2.9.0 -----------------------------------------------+-- -- | /_fmpz_multi_CRT_run/ /outputs/ /CRT/ /inputs/ +-- -- +-- -- Perform the same operation as fmpz::fmpz_multi_CRT_precomp using+-- -- supplied temporary space. The actual output is placed in @outputs + 0@,+-- -- and @outputs@ should contain space for all temporaries and should be at+-- -- least as long as @_fmpz_multi_CRT_local_size(CRT)@.+-- foreign import ccall "fmpz.h _fmpz_multi_CRT_run"+-- _fmpz_multi_CRT_run :: Ptr CFmpz -> Ptr CFmpzMultiCRT -> Ptr CFmpz -> IO ()++-- Primality testing -----------------------------------------------------------++-- | /fmpz_is_strong_probabprime/ /n/ /a/ +-- +-- Returns \(1\) if \(n\) is a strong probable prime to base \(a\),+-- otherwise it returns \(0\).+foreign import ccall "fmpz.h fmpz_is_strong_probabprime"+ fmpz_is_strong_probabprime :: Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- | /fmpz_is_probabprime_lucas/ /n/ +-- +-- Performs a Lucas probable prime test with parameters chosen by+-- Selfridge\'s method \(A\) as per < [BaiWag1980]>.+-- +-- Return \(1\) if \(n\) is a Lucas probable prime, otherwise return \(0\).+-- This function declares some composites probably prime, but no primes+-- composite.+foreign import ccall "fmpz.h fmpz_is_probabprime_lucas"+ fmpz_is_probabprime_lucas :: Ptr CFmpz -> IO CInt++-- | /fmpz_is_probabprime_BPSW/ /n/ +-- +-- Perform a Baillie-PSW probable prime test with parameters chosen by+-- Selfridge\'s method \(A\) as per < [BaiWag1980]>.+-- +-- Return \(1\) if \(n\) is a Lucas probable prime, otherwise return \(0\).+-- +-- There are no known composites passed as prime by this test, though+-- infinitely many probably exist. The test will declare no primes+-- composite.+foreign import ccall "fmpz.h fmpz_is_probabprime_BPSW"+ fmpz_is_probabprime_BPSW :: Ptr CFmpz -> IO CInt++-- | /fmpz_is_probabprime/ /p/ +-- +-- Performs some trial division and then some probabilistic primality+-- tests. If \(p\) is definitely composite, the function returns \(0\),+-- otherwise it is declared probably prime, i.e. prime for most practical+-- purposes, and the function returns \(1\). The chance of declaring a+-- composite prime is very small.+-- +-- Subsequent calls to the same function do not increase the probability of+-- the number being prime.+foreign import ccall "fmpz.h fmpz_is_probabprime"+ fmpz_is_probabprime :: Ptr CFmpz -> IO CInt++-- | /fmpz_is_prime_pseudosquare/ /n/ +-- +-- Return \(0\) is \(n\) is composite. If \(n\) is too large (greater than+-- about \(94\) bits) the function fails silently and returns \(-1\),+-- otherwise, if \(n\) is proven prime by the pseudosquares method, return+-- \(1\).+-- +-- Tests if \(n\) is a prime according to [Theorem 2.7] < [LukPatWil1996]>.+-- +-- We first factor \(N\) using trial division up to some limit \(B\). In+-- fact, the number of primes used in the trial factoring is at most+-- @FLINT_PSEUDOSQUARES_CUTOFF@.+-- +-- Next we compute \(N/B\) and find the next pseudosquare \(L_p\) above+-- this value, using a static table as per+-- <https://oeis.org/A002189/b002189.txt>.+-- +-- As noted in the text, if \(p\) is prime then Step 3 will pass. This test+-- rejects many composites, and so by this time we suspect that \(p\) is+-- prime. If \(N\) is \(3\) or \(7\) modulo \(8\), we are done, and \(N\)+-- is prime.+-- +-- We now run a probable prime test, for which no known counterexamples are+-- known, to reject any composites. We then proceed to prove \(N\) prime by+-- executing Step 4. In the case that \(N\) is \(1\) modulo \(8\), if Step+-- 4 fails, we extend the number of primes \(p_i\) at Step 3 and hope to+-- find one which passes Step 4. We take the test one past the largest+-- \(p\) for which we have pseudosquares \(L_p\) tabulated, as this already+-- corresponds to the next \(L_p\) which is bigger than \(2^{64}\) and+-- hence larger than any prime we might be testing.+-- +-- As explained in the text, Condition 4 cannot fail if \(N\) is prime.+-- +-- The possibility exists that the probable prime test declares a composite+-- prime. However in that case an error is printed, as that would be of+-- independent interest.+foreign import ccall "fmpz.h fmpz_is_prime_pseudosquare"+ fmpz_is_prime_pseudosquare :: Ptr CFmpz -> IO CInt++-- | /fmpz_is_prime_pocklington/ /F/ /R/ /n/ /pm1/ /num_pm1/ +-- +-- Applies the Pocklington primality test. The test computes a product+-- \(F\) of prime powers which divide \(n - 1\).+-- +-- The function then returns either \(0\) if \(n\) is definitely composite+-- or it returns \(1\) if all factors of \(n\) are \(1 \pmod{F}\). Also in+-- that case, \(R\) is set to \((n - 1)/F\).+-- +-- N.B: a return value of \(1\) only proves \(n\) prime if+-- \(F \ge \sqrt{n}\).+-- +-- The function does not compute which primes divide \(n - 1\). Instead,+-- these must be supplied as an array @pm1@ of length @num_pm1@. It does+-- not matter how many prime factors are supplied, but the more that are+-- supplied, the larger F will be.+-- +-- There is a balance between the amount of time spent looking for factors+-- of \(n - 1\) and the usefulness of the output (F may be as low as \(2\)+-- in some cases).+-- +-- A reasonable heuristic seems to be to choose @limit@ to be some small+-- multiple of \(\log^3(n)/10\) (e.g. \(1, 2, 5\) or \(10\)) depending on+-- how long one is prepared to wait, then to trial factor up to the limit.+-- (See @_fmpz_nm1_trial_factors@.)+-- +-- Requires \(n\) to be odd.+foreign import ccall "fmpz.h fmpz_is_prime_pocklington"+ fmpz_is_prime_pocklington :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CMp -> CLong -> IO CInt++-- | /_fmpz_nm1_trial_factors/ /n/ /pm1/ /num_pm1/ /limit/ +-- +-- Trial factors \(n - 1\) up to the given limit (approximately) and stores+-- the factors in an array @pm1@ whose length is written out to @num_pm1@.+-- +-- One can use \(\log(n) + 2\) as a bound on the number of factors which+-- might be produced (and hence on the length of the array that needs to be+-- supplied).+foreign import ccall "fmpz.h _fmpz_nm1_trial_factors"+ _fmpz_nm1_trial_factors :: Ptr CFmpz -> Ptr CMp -> Ptr CLong -> CULong -> IO ()++-- | /fmpz_is_prime_morrison/ /F/ /R/ /n/ /pp1/ /num_pp1/ +-- +-- Applies the Morrison \(p + 1\) primality test. The test computes a+-- product \(F\) of primes which divide \(n + 1\).+-- +-- The function then returns either \(0\) if \(n\) is definitely composite+-- or it returns \(1\) if all factors of \(n\) are \(\pm 1 \pmod{F}\). Also+-- in that case, \(R\) is set to \((n + 1)/F\).+-- +-- N.B: a return value of \(1\) only proves \(n\) prime if+-- \(F > \sqrt{n} + 1\).+-- +-- The function does not compute which primes divide \(n + 1\). Instead,+-- these must be supplied as an array @pp1@ of length @num_pp1@. It does+-- not matter how many prime factors are supplied, but the more that are+-- supplied, the larger \(F\) will be.+-- +-- There is a balance between the amount of time spent looking for factors+-- of \(n + 1\) and the usefulness of the output (F may be as low as \(2\)+-- in some cases).+-- +-- A reasonable heuristic seems to be to choose @limit@ to be some small+-- multiple of \(\log^3(n)/10\) (e.g. \(1, 2, 5\) or \(10\)) depending on+-- how long one is prepared to wait, then to trial factor up to the limit.+-- (See @_fmpz_np1_trial_factors@.)+-- +-- Requires \(n\) to be odd and non-square.+foreign import ccall "fmpz.h fmpz_is_prime_morrison"+ fmpz_is_prime_morrison :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CMp -> CLong -> IO CInt++-- | /_fmpz_np1_trial_factors/ /n/ /pp1/ /num_pp1/ /limit/ +-- +-- Trial factors \(n + 1\) up to the given limit (approximately) and stores+-- the factors in an array @pp1@ whose length is written out to @num_pp1@.+-- +-- One can use \(\log(n) + 2\) as a bound on the number of factors which+-- might be produced (and hence on the length of the array that needs to be+-- supplied).+foreign import ccall "fmpz.h _fmpz_np1_trial_factors"+ _fmpz_np1_trial_factors :: Ptr CFmpz -> Ptr CMp -> Ptr CLong -> CULong -> IO ()++-- | /fmpz_is_prime/ /n/ +-- +-- Attempts to prove \(n\) prime. If \(n\) is proven prime, the function+-- returns \(1\). If \(n\) is definitely composite, the function returns+-- \(0\).+-- +-- This function calls @n_is_prime@ for \(n\) that fits in a single word.+-- For \(n\) larger than one word, it tests divisibility by a few small+-- primes and whether \(n\) is a perfect square to rule out trivial+-- composites. For \(n\) up to about 81 bits, it then uses a strong+-- probable prime test (Miller-Rabin test) with the first 13 primes as+-- witnesses. This has been shown to prove primality < [SorWeb2016]>.+-- +-- For larger \(n\), it does a single base-2 strong probable prime test to+-- eliminate most composite numbers. If \(n\) passes, it does a combination+-- of Pocklington, Morrison and Brillhart, Lehmer, Selfridge tests. If any+-- of these tests fails to give a proof, it falls back to performing an+-- APRCL test.+-- +-- The APRCL test could theoretically fail to prove that \(n\) is prime or+-- composite. In that case, the program aborts. This is not expected to+-- occur in practice.+foreign import ccall "fmpz.h fmpz_is_prime"+ fmpz_is_prime :: Ptr CFmpz -> IO CInt++-- | /fmpz_lucas_chain/ /Vm/ /Vm1/ /A/ /m/ /n/ +-- +-- Given \(V_0 = 2\), \(V_1 = A\) compute \(V_m, V_{m + 1} \pmod{n}\) from+-- the recurrences \(V_j = AV_{j - 1} - V_{j - 2} \pmod{n}\).+-- +-- This is computed efficiently using \(V_{2j} = V_j^2 - 2 \pmod{n}\) and+-- \(V_{2j + 1} = V_jV_{j + 1} - A \pmod{n}\).+-- +-- No aliasing is permitted.+foreign import ccall "fmpz.h fmpz_lucas_chain"+ fmpz_lucas_chain :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_lucas_chain_full/ /Vm/ /Vm1/ /A/ /B/ /m/ /n/ +-- +-- Given \(V_0 = 2\), \(V_1 = A\) compute \(V_m, V_{m + 1} \pmod{n}\) from+-- the recurrences \(V_j = AV_{j - 1} - BV_{j - 2} \pmod{n}\).+-- +-- This is computed efficiently using double and add formulas.+-- +-- No aliasing is permitted.+foreign import ccall "fmpz.h fmpz_lucas_chain_full"+ fmpz_lucas_chain_full :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_lucas_chain_double/ /U2m/ /U2m1/ /Um/ /Um1/ /A/ /B/ /n/ +-- +-- Given \(U_m, U_{m + 1} \pmod{n}\) compute+-- \(U_{2m}, U_{2m + 1} \pmod{n}\).+-- +-- Aliasing of \(U_{2m}\) and \(U_m\) and aliasing of \(U_{2m + 1}\) and+-- \(U_{m + 1}\) is permitted. No other aliasing is allowed.+foreign import ccall "fmpz.h fmpz_lucas_chain_double"+ fmpz_lucas_chain_double :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_lucas_chain_add/ /Umn/ /Umn1/ /Um/ /Um1/ /Un/ /Un1/ /A/ /B/ /n/ +-- +-- Given \(U_m, U_{m + 1} \pmod{n}\) and \(U_n, U_{n + 1} \pmod{n}\)+-- compute \(U_{m + n}, U_{m + n + 1} \pmod{n}\).+-- +-- Aliasing of \(U_{m + n}\) with \(U_m\) or \(U_n\) and aliasing of+-- \(U_{m + n + 1}\) with \(U_{m + 1}\) or \(U_{n + 1}\) is permitted. No+-- other aliasing is allowed.+foreign import ccall "fmpz.h fmpz_lucas_chain_add"+ fmpz_lucas_chain_add :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_lucas_chain_mul/ /Ukm/ /Ukm1/ /Um/ /Um1/ /A/ /B/ /k/ /n/ +-- +-- Given \(U_m, U_{m + 1} \pmod{n}\) compute+-- \(U_{km}, U_{km + 1} \pmod{n}\).+-- +-- Aliasing of \(U_{km}\) and \(U_m\) and aliasing of \(U_{km + 1}\) and+-- \(U_{m + 1}\) is permitted. No other aliasing is allowed.+foreign import ccall "fmpz.h fmpz_lucas_chain_mul"+ fmpz_lucas_chain_mul :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_lucas_chain_VtoU/ /Um/ /Um1/ /Vm/ /Vm1/ /A/ /B/ /Dinv/ /n/ +-- +-- Given \(V_m, V_{m + 1} \pmod{n}\) compute \(U_m, U_{m + 1} \pmod{n}\).+-- +-- Aliasing of \(V_m\) and \(U_m\) and aliasing of \(V_{m + 1}\) and+-- \(U_{m + 1}\) is permitted. No other aliasing is allowed.+foreign import ccall "fmpz.h fmpz_lucas_chain_VtoU"+ fmpz_lucas_chain_VtoU :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_divisor_in_residue_class_lenstra/ /fac/ /n/ /r/ /s/ +-- +-- If there exists a proper divisor of \(n\) which is \(r \pmod{s}\) for+-- \(0 < r < s < n\), this function returns \(1\) and sets @fac@ to such a+-- divisor. Otherwise the function returns \(0\) and the value of @fac@ is+-- undefined.+-- +-- We require \(\gcd(r, s) = 1\).+-- +-- This is efficient if \(s^3 > n\).+foreign import ccall "fmpz.h fmpz_divisor_in_residue_class_lenstra"+ fmpz_divisor_in_residue_class_lenstra :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO CInt++-- | /fmpz_nextprime/ /res/ /n/ /proved/ +-- +-- Finds the next prime number larger than \(n\).+-- +-- If @proved@ is nonzero, then the integer returned is guaranteed to+-- actually be prime. Otherwise if \(n\) fits in @FLINT_BITS - 3@ bits+-- @n_nextprime@ is called, and if not then the GMP @mpz_nextprime@+-- function is called. Up to an including GMP 6.1.2 this used Miller-Rabin+-- iterations, and thereafter uses a BPSW test.+foreign import ccall "fmpz.h fmpz_nextprime"+ fmpz_nextprime :: Ptr CFmpz -> Ptr CFmpz -> CInt -> IO ()++-- Special functions -----------------------------------------------------------++-- | /fmpz_primorial/ /res/ /n/ +-- +-- Sets @res@ to @n@ primorial or \(n \#\), the product of all prime+-- numbers less than or equal to \(n\).+foreign import ccall "fmpz.h fmpz_primorial"+ fmpz_primorial :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_factor_euler_phi/ /res/ /fac/ +-- +-- Sets @res@ to the Euler totient function \(\phi(n)\), counting the+-- number of positive integers less than or equal to \(n\) that are coprime+-- to \(n\). The factor version takes a precomputed factorisation of \(n\).+foreign import ccall "fmpz.h fmpz_factor_euler_phi"+ fmpz_factor_euler_phi :: Ptr CFmpz -> Ptr CFmpzFactor -> IO ()++foreign import ccall "fmpz.h fmpz_euler_phi"+ fmpz_euler_phi :: Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_factor_moebius_mu/ /fac/ +-- +-- Computes the Moebius function \(\mu(n)\), which is defined as+-- \(\mu(n) = 0\) if \(n\) has a prime factor of multiplicity greater than+-- \(1\), \(\mu(n) = -1\) if \(n\) has an odd number of distinct prime+-- factors, and \(\mu(n) = 1\) if \(n\) has an even number of distinct+-- prime factors. By convention, \(\mu(0) = 0\). The factor version takes a+-- precomputed factorisation of \(n\).+foreign import ccall "fmpz.h fmpz_factor_moebius_mu"+ fmpz_factor_moebius_mu :: Ptr CFmpzFactor -> IO CInt++foreign import ccall "fmpz.h fmpz_moebius_mu"+ fmpz_moebius_mu :: Ptr CFmpz -> Ptr CFmpz -> CInt++-- | /fmpz_factor_divisor_sigma/ /res/ /k/ /fac/ +-- +-- Sets @res@ to \(\sigma_k(n)\), the sum of \(k`th powers of all +-- divisors of :math:`n\). The factor version takes a precomputed+-- factorisation of \(n\).+foreign import ccall "fmpz.h fmpz_factor_divisor_sigma"+ fmpz_factor_divisor_sigma :: Ptr CFmpz -> CULong -> Ptr CFmpzFactor -> IO ()++foreign import ccall "fmpz.h fmpz_divisor_sigma"+ fmpz_divisor_sigma :: Ptr CFmpz -> CULong -> Ptr CFmpz -> IO ()++-- | /nmod_pow_fmpz/ /a/ /e/ /mod/ +-- +-- Returns \(a^e\) modulo @mod.n@. No assumptions are made about @mod.n@.+-- It is assumed that \(a\) is already reduced modulo @mod.n@ and that+-- \(e\) is not negative.+foreign import ccall "nmod.h nmod_pow_fmpz"+ nmod_pow_fmpz :: CMpLimb -> Ptr CFmpz -> Ptr CNMod -> IO CMpLimb
+ src/Data/Number/Flint/Fmpz/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Factor (+ module Data.Number.Flint.Fmpz.Factor.FFI+ ) where++import Data.Number.Flint.Fmpz.Factor.FFI
+ src/Data/Number/Flint/Fmpz/Factor/FFI.hsc view
@@ -0,0 +1,451 @@+{-|+module : Data.Number.Flint.Fmpz.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Factor.FFI (+ -- * Integer factorisation+ -- * Memory management+ newFmpzFactor+ , withFmpzFactor+ , withNewFmpzFactor+ , fmpz_factor_init+ , fmpz_factor_clear+ -- * Output+ , fmpz_factor_get_str+ , fmpz_factor_print+ , fmpz_factor_fprint+ -- * Modification+ , _fmpz_factor_append_ui+ , _fmpz_factor_append+ -- * Factoring integers+ , fmpz_factor+ , fmpz_factor_smooth+ , fmpz_factor_si+ , fmpz_factor_trial_range+ , fmpz_factor_trial+ , fmpz_factor_refine+ , fmpz_factor_expand_iterative+ , fmpz_factor_pp1+ , fmpz_factor_pollard_brent_single+ , fmpz_factor_pollard_brent+ -- * Elliptic curve (ECM) method+ , Ecm (..)+ , CEcm (..)+ , fmpz_factor_ecm_init+ , fmpz_factor_ecm_clear+ , fmpz_factor_ecm_addmod+ , fmpz_factor_ecm_submod+ , fmpz_factor_ecm_double+ , fmpz_factor_ecm_add+ , fmpz_factor_ecm_mul_montgomery_ladder+ , fmpz_factor_ecm_select_curve+ , fmpz_factor_ecm_stage_I+ , fmpz_factor_ecm_stage_II+ , fmpz_factor_ecm+) where++-- Integer factorisation -------------------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_factor.h>++-- FmpzFactor ------------------------------------------------------------------++newFmpzFactor = do+ x <- mallocForeignPtr+ withForeignPtr x fmpz_factor_init+ addForeignPtrFinalizer p_fmpz_factor_clear x+ return $ FmpzFactor x++{-# INLINE withFmpzFactor #-}+withFmpzFactor (FmpzFactor x) f = do+ withForeignPtr x $ \xp -> f xp >>= return . (FmpzFactor x,)++{-# INLINE withNewFmpzFactor #-}+withNewFmpzFactor f = do+ x <- newFmpzFactor+ withFmpzFactor x f++-- Ecm -------------------------------------------------------------------------++data Ecm = Ecm {-# UNPACK #-} !(ForeignPtr CEcm)+type CEcm = CFlint Ecm++-- Factoring integers ----------------------------------------------------------++-- An integer may be represented in factored form using the @fmpz_factor_t@+-- data structure. This consists of two @fmpz@ vectors representing bases+-- and exponents, respectively. Canonically, the bases will be prime+-- numbers sorted in ascending order and the exponents will be positive. A+-- separate @int@ field holds the sign, which may be \(-1\), \(0\) or+-- \(1\).+--++-- | /fmpz_factor_init/ /factor/ +-- +-- Initialises an @fmpz_factor_t@ structure.+foreign import ccall "fmpz_factor.h fmpz_factor_init"+ fmpz_factor_init :: Ptr CFmpzFactor -> IO ()++-- | /fmpz_factor_clear/ /factor/ +-- +-- Clears an @fmpz_factor_t@ structure.+foreign import ccall "fmpz_factor.h fmpz_factor_clear"+ fmpz_factor_clear :: Ptr CFmpzFactor -> IO ()++foreign import ccall "fmpz_factor.h &fmpz_factor_clear"+ p_fmpz_factor_clear :: FunPtr (Ptr CFmpzFactor -> IO ())++-- Output ----------------------------------------------------------------------++-- | /fmpz_factor_get_str/ /factor/+--+-- Get string representation of factorization+foreign import ccall "fmpz_factor_get_str"+ fmpz_factor_get_str :: Ptr CFmpzFactor -> IO CString++-- | /fmpz_factor_print/ /factor/+--+-- Print factorization+fmpz_factor_print = printCStr fmpz_factor_get_str++-- | /fmpz_factor_fprint/ /factor/+--+-- Print factorization to file+foreign import ccall "fmpz_factor_fprint"+ fmpz_factor_fprint :: Ptr CFile -> Ptr CFmpzFactor -> IO ()++--------------------------------------------------------------------------------++-- | /_fmpz_factor_append_ui/ /factor/ /p/ /exp/ +-- +-- Append a factor \(p\) to the given exponent to the @fmpz_factor_t@+-- structure @factor@.+foreign import ccall "fmpz_factor.h _fmpz_factor_append_ui"+ _fmpz_factor_append_ui :: Ptr CFmpzFactor -> CMpLimb -> CULong -> IO ()++-- | /_fmpz_factor_append/ /factor/ /p/ /exp/ +-- +-- Append a factor \(p\) to the given exponent to the @fmpz_factor_t@+-- structure @factor@.+foreign import ccall "fmpz_factor.h _fmpz_factor_append"+ _fmpz_factor_append :: Ptr CFmpzFactor -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_factor/ /factor/ /n/ +-- +-- Factors \(n\) into prime numbers. If \(n\) is zero or negative, the sign+-- field of the @factor@ object will be set accordingly.+foreign import ccall "fmpz_factor.h fmpz_factor"+ fmpz_factor :: Ptr CFmpzFactor -> Ptr CFmpz -> IO ()++-- | /fmpz_factor_smooth/ /factor/ /n/ /bits/ /proved/ +-- +-- Factors \(n\) into prime numbers up to approximately the given number of+-- bits and possibly one additional cofactor, which may or may not be+-- prime.+-- +-- If the number is definitely factored fully, the return value is \(1\),+-- otherwise the final factor (which may have exponent greater than \(1\))+-- is composite and needs to be factored further.+-- +-- If the number has a factor of around the given number of bits, there is+-- at least a two-thirds chance of finding it. Smaller factors should be+-- found with a much higher probability.+-- +-- The amount of time spent factoring can be controlled by lowering or+-- increasing @bits@. However, the quadratic sieve may be faster if @bits@+-- is set to more than one third of the number of bits of \(n\).+-- +-- The function uses trial factoring up to @bits = 15@, followed by a+-- primality test and a perfect power test to check if the factorisation is+-- complete. If @bits@ is at least 16, it proceeds to use the elliptic+-- curve method to look for larger factors.+-- +-- The behavior of primality testing is determined by the @proved@+-- parameter:+-- +-- If @proved@ is set to \(1\) the function will prove all factors prime+-- (other than the last factor, if the return value is \(0\)).+-- +-- If @proved@ is set to \(0\), the function will only check that factors+-- are probable primes.+-- +-- If @proved@ is set to \(-1\), the function will not test primality after+-- performing trial division. A perfect power test is still performed.+-- +-- As an exception to the rules stated above, this function will call+-- @n_factor@ internally if \(n\) or the remainder after trial division is+-- smaller than one word, guaranteeing a complete factorisation.+foreign import ccall "fmpz_factor.h fmpz_factor_smooth"+ fmpz_factor_smooth :: Ptr CFmpzFactor -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /fmpz_factor_si/ /factor/ /n/ +-- +-- Like @fmpz_factor@, but takes a machine integer \(n\) as input.+foreign import ccall "fmpz_factor.h fmpz_factor_si"+ fmpz_factor_si :: Ptr CFmpzFactor -> CLong -> IO ()++-- | /fmpz_factor_trial_range/ /factor/ /n/ /start/ /num_primes/ +-- +-- Factors \(n\) into prime factors using trial division. If \(n\) is zero+-- or negative, the sign field of the @factor@ object will be set+-- accordingly.+-- +-- The algorithm starts with the given start index in the @flint_primes@+-- table and uses at most @num_primes@ primes from that point.+-- +-- The function returns 1 if \(n\) is completely factored, otherwise it+-- returns \(0\).+foreign import ccall "fmpz_factor.h fmpz_factor_trial_range"+ fmpz_factor_trial_range :: Ptr CFmpzFactor -> Ptr CFmpz -> CULong -> CULong -> IO CInt++-- | /fmpz_factor_trial/ /factor/ /n/ /num_primes/ +-- +-- Factors \(n\) into prime factors using trial division. If \(n\) is zero+-- or negative, the sign field of the @factor@ object will be set+-- accordingly.+-- +-- The algorithm uses the given number of primes, which must be in the+-- range \([0, 3512]\). An exception is raised if a number outside this+-- range is passed.+-- +-- The function returns 1 if \(n\) is completely factored, otherwise it+-- returns \(0\).+-- +-- The final entry in the factor struct is set to the cofactor after+-- removing prime factors, if this is not \(1\).+foreign import ccall "fmpz_factor.h fmpz_factor_trial"+ fmpz_factor_trial :: Ptr CFmpzFactor -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_factor_refine/ /res/ /f/ +-- +-- Attempts to improve a partial factorization of an integer by+-- \"refining\" the factorization @f@ to a more complete factorization+-- @res@ whose bases are pairwise relatively prime.+-- +-- This function does not require its input to be in canonical form, nor+-- does it guarantee that the resulting factorization will be canonical.+foreign import ccall "fmpz_factor.h fmpz_factor_refine"+ fmpz_factor_refine :: Ptr CFmpzFactor -> Ptr CFmpzFactor -> IO ()++-- | /fmpz_factor_expand_iterative/ /n/ /factor/ +-- +-- Evaluates an integer in factored form back to an @fmpz_t@.+-- +-- This currently exponentiates the bases separately and multiplies them+-- together one by one, although much more efficient algorithms exist.+foreign import ccall "fmpz_factor.h fmpz_factor_expand_iterative"+ fmpz_factor_expand_iterative :: Ptr CFmpz -> Ptr CFmpzFactor -> IO ()++-- | /fmpz_factor_pp1/ /factor/ /n/ /B1/ /B2_sqrt/ /c/ +-- +-- Use Williams\' \(p + 1\) method to factor \(n\), using a prime bound in+-- stage 1 of @B1@ and a prime limit in stage 2 of at least the square of+-- @B2_sqrt@. If a factor is found, the function returns \(1\) and @factor@+-- is set to the factor that is found. Otherwise, the function returns+-- \(0\).+-- +-- The value \(c\) should be a random value greater than \(2\). Successive+-- calls to the function with different values of \(c\) give additional+-- chances to factor \(n\) with roughly exponentially decaying probability+-- of finding a factor which has been missed (if \(p+1\) or \(p-1\) is not+-- smooth for any prime factors \(p\) of \(n\) then the function will not+-- ever succeed).+foreign import ccall "fmpz_factor.h fmpz_factor_pp1"+ fmpz_factor_pp1 :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CULong -> CULong -> IO CInt++-- | /fmpz_factor_pollard_brent_single/ /p_factor/ /n_in/ /yi/ /ai/ /max_iters/ +-- +-- Pollard Rho algorithm for integer factorization. Assumes that the \(n\)+-- is not prime. @factor@ is set as the factor if found. Takes as input the+-- initial value \(y\), to start polynomial evaluation and \(a\), the+-- constant of the polynomial used. It is not assured that the factor found+-- will be prime. Does not compute the complete factorization, just one+-- factor. Returns the number of limbs of factor if factorization is+-- successful (non trivial factor is found), else returns 0.+-- +-- @max_iters@ is the number of iterations tried in process of finding the+-- cycle. If the algorithm fails to find a non trivial factor in one call,+-- it tries again (this time with a different set of random values).+foreign import ccall "fmpz_factor.h fmpz_factor_pollard_brent_single"+ fmpz_factor_pollard_brent_single :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CMpLimb -> IO CInt++-- | /fmpz_factor_pollard_brent/ /factor/ /state/ /n/ /max_tries/ /max_iters/ +-- +-- Pollard Rho algorithm for integer factorization. Assumes that the \(n\)+-- is not prime. @factor@ is set as the factor if found. It is not assured+-- that the factor found will be prime. Does not compute the complete+-- factorization, just one factor. Returns the number of limbs of factor if+-- factorization is successful (non trivial factor is found), else returns+-- 0.+-- +-- @max_iters@ is the number of iterations tried in process of finding the+-- cycle. If the algorithm fails to find a non trivial factor in one call,+-- it tries again (this time with a different set of random values). This+-- process is repeated a maximum of @max_tries@ times.+-- +-- The algorithm used is a modification of the original Pollard Rho+-- algorithm, suggested by Richard Brent. It can be found in the paper+-- available at <https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf>+foreign import ccall "fmpz_factor.h fmpz_factor_pollard_brent"+ fmpz_factor_pollard_brent :: Ptr CFmpz -> Ptr CFRandState -> Ptr CFmpz -> CMpLimb -> CMpLimb -> IO CInt++-- Elliptic curve (ECM) method -------------------------------------------------++-- Factoring of @fmpz@ integers using ECM+--+-- | /fmpz_factor_ecm_init/ /ecm_inf/ /sz/ +-- +-- Initializes the @ecm_t@ struct. This is needed in some functions and+-- carries data between subsequent calls.+foreign import ccall "fmpz_factor.h fmpz_factor_ecm_init"+ fmpz_factor_ecm_init :: Ptr CEcm -> CMpLimb -> IO ()++-- | /fmpz_factor_ecm_clear/ /ecm_inf/ +-- +-- Clears the @ecm_t@ struct.+foreign import ccall "fmpz_factor.h fmpz_factor_ecm_clear"+ fmpz_factor_ecm_clear :: Ptr CEcm -> IO ()++-- | /fmpz_factor_ecm_addmod/ /a/ /b/ /c/ /n/ /n_size/ +-- +-- Sets \(a\) to \((b + c)\) @%@ \(n\). This is not a normal add mod+-- function, it assumes \(n\) is normalized (highest bit set) and \(b\) and+-- \(c\) are reduced modulo \(n\).+-- +-- Used for arithmetic operations in @fmpz_factor_ecm@.+foreign import ccall "fmpz_factor.h fmpz_factor_ecm_addmod"+ fmpz_factor_ecm_addmod :: Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> CMpLimb -> IO ()++-- | /fmpz_factor_ecm_submod/ /x/ /a/ /b/ /n/ /n_size/ +-- +-- Sets \(x\) to \((a - b)\) @%@ \(n\). This is not a normal subtract mod+-- function, it assumes \(n\) is normalized (highest bit set) and \(b\) and+-- \(c\) are reduced modulo \(n\).+-- +-- Used for arithmetic operations in @fmpz_factor_ecm@.+foreign import ccall "fmpz_factor.h fmpz_factor_ecm_submod"+ fmpz_factor_ecm_submod :: Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> CMpLimb -> IO ()++-- | /fmpz_factor_ecm_double/ /x/ /z/ /x0/ /z0/ /n/ /ecm_inf/ +-- +-- Sets the point \((x : z)\) to two times \((x_0 : z_0)\) modulo \(n\)+-- according to the formula+-- +-- \[`\]+-- \[x = (x_0 + z_0)^2 \cdot (x_0 - z_0)^2 \mod n,\]+-- +-- \[`\]+-- \[z = 4 x_0 z_0 \left((x_0 - z_0)^2 + 4a_{24}x_0z_0\right) \mod n.\]+-- +-- @ecm_inf@ is used just to use temporary @mp_ptr@\'s in the structure.+-- This group doubling is valid only for points expressed in Montgomery+-- projective coordinates.+foreign import ccall "fmpz_factor.h fmpz_factor_ecm_double"+ fmpz_factor_ecm_double :: Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CEcm -> IO ()++-- | /fmpz_factor_ecm_add/ /x/ /z/ /x1/ /z1/ /x2/ /z2/ /x0/ /z0/ /n/ /ecm_inf/ +-- +-- Sets the point \((x : z)\) to the sum of \((x_1 : z_1)\) and+-- \((x_2 : z_2)\) modulo \(n\), given the difference \((x_0 : z_0)\)+-- according to the formula+-- +-- \[`\]+-- \[\begin{aligned}+-- x = 4z_0(x_1x_2 - z_1z_2)^2 \mod n, \\ z = 4x_0(x_2z_1 - x_1z_2)^2 \mod n.+-- \end{aligned}\]+-- +-- @ecm_inf@ is used just to use temporary @mp_ptr@\'s in the structure.+-- This group addition is valid only for points expressed in Montgomery+-- projective coordinates.+foreign import ccall "fmpz_factor.h fmpz_factor_ecm_add"+ fmpz_factor_ecm_add :: Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CEcm -> IO ()++-- | /fmpz_factor_ecm_mul_montgomery_ladder/ /x/ /z/ /x0/ /z0/ /k/ /n/ /ecm_inf/ +-- +-- Montgomery ladder algorithm for scalar multiplication of elliptic+-- points.+-- +-- Sets the point \((x : z)\) to \(k(x_0 : z_0)\) modulo \(n\).+-- +-- @ecm_inf@ is used just to use temporary @mp_ptr@\'s in the structure.+-- Valid only for points expressed in Montgomery projective coordinates.+foreign import ccall "fmpz_factor.h fmpz_factor_ecm_mul_montgomery_ladder"+ fmpz_factor_ecm_mul_montgomery_ladder :: Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> CMpLimb -> Ptr CMp -> Ptr CEcm -> IO ()++-- | /fmpz_factor_ecm_select_curve/ /f/ /sigma/ /n/ /ecm_inf/ +-- +-- Selects a random elliptic curve given a random integer @sigma@,+-- according to Suyama\'s parameterization. If the factor is found while+-- selecting the curve, the number of limbs required to store the factor is+-- returned, otherwise \(0\).+-- +-- It could be possible that the selected curve is unsuitable for further+-- computations, in such a case, \(-1\) is returned.+-- +-- Also selects the initial point \(x_0\), and the value of \((a + 2)/4\),+-- where \(a\) is a curve parameter. Sets \(z_0\) as \(1\). All these are+-- stored in the @ecm_t@ struct.+-- +-- The curve selected is of Montgomery form, the points selected satisfy+-- the curve and are projective coordinates.+foreign import ccall "fmpz_factor.h fmpz_factor_ecm_select_curve"+ fmpz_factor_ecm_select_curve :: Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CEcm -> IO CInt++-- | /fmpz_factor_ecm_stage_I/ /f/ /prime_array/ /num/ /B1/ /n/ /ecm_inf/ +-- +-- Stage I implementation of the ECM algorithm.+-- +-- @f@ is set as the factor if found. @num@ is number of prime numbers+-- \(\le\) the bound @B1@. @prime_array@ is an array of first @B1@ primes.+-- \(n\) is the number being factored.+-- +-- If the factor is found, number of words required to store the factor is+-- returned, otherwise \(0\).+foreign import ccall "fmpz_factor.h fmpz_factor_ecm_stage_I"+ fmpz_factor_ecm_stage_I :: Ptr CMp -> Ptr CMpLimb -> CMpLimb -> CMpLimb -> Ptr CMp -> Ptr CEcm -> IO CInt++-- | /fmpz_factor_ecm_stage_II/ /f/ /B1/ /B2/ /P/ /n/ /ecm_inf/ +-- +-- Stage II implementation of the ECM algorithm.+-- +-- @f@ is set as the factor if found. @B1@, @B2@ are the two bounds. @P@ is+-- the primorial (approximately equal to \(\sqrt{B2}\)). \(n\) is the+-- number being factored.+-- +-- If the factor is found, number of words required to store the factor is+-- returned, otherwise \(0\).+foreign import ccall "fmpz_factor.h fmpz_factor_ecm_stage_II"+ fmpz_factor_ecm_stage_II :: Ptr CMp -> CMpLimb -> CMpLimb -> CMpLimb -> Ptr CMp -> Ptr CEcm -> IO CInt++-- | /fmpz_factor_ecm/ /f/ /curves/ /B1/ /B2/ /state/ /n_in/ +-- +-- Outer wrapper function for the ECM algorithm. In case @f@ can fit in a+-- single unsigned word, a call to @n_factor_ecm@ is made.+-- +-- The function calls stage I and II, and the precomputations (builds+-- @prime_array@ for stage I, @GCD_table@ and @prime_table@ for stage II).+-- +-- @f@ is set as the factor if found. @curves@ is the number of random+-- curves being tried. @B1@, @B2@ are the two bounds or stage I and stage+-- II. \(n\) is the number being factored.+-- +-- If a factor is found in stage I, \(1\) is returned. If a factor is found+-- in stage II, \(2\) is returned. If a factor is found while selecting the+-- curve, \(-1\) is returned. Otherwise \(0\) is returned.+foreign import ccall "fmpz_factor.h fmpz_factor_ecm"+ fmpz_factor_ecm :: Ptr CFmpz -> CMpLimb -> CMpLimb -> CMpLimb -> Ptr CFRandState -> Ptr CFmpz -> IO CInt+
+ src/Data/Number/Flint/Fmpz/Instances.hs view
@@ -0,0 +1,139 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Fmpz.Instances (+ Fmpz (..)+, UFD (..)+) where++import Test.QuickCheck+import System.IO.Unsafe+import Control.Monad++import Data.Ratio++import Foreign.Storable+import Foreign.C.Types+import Foreign.C.String+import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Marshal.Alloc+import Foreign.Marshal.Array (advancePtr)++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Factor+import Data.Number.Flint.UFD++instance Show Fmpz where+ show x = snd $ unsafePerformIO $ do+ let base = 10 :: CInt+ withFmpz x $ \x -> do+ cString <- fmpz_get_str nullPtr base x+ result <- peekCString cString+ free cString+ return result++instance Read Fmpz where+ readsPrec d s = unsafePerformIO $ do+ let n :: Integer+ [(n, r)] = readsPrec d s+ result <- newFmpz+ (_, flag) <- withFmpz result $ \result -> + withCString (show n) $ \s -> + fmpz_set_str result s 10+ if flag == 0 then + return [(result, r)]+ else+ return []++instance Eq Fmpz where+ (==) x y = snd $ snd $ unsafePerformIO $ + withFmpz x $ \x ->+ withFmpz y $ \y -> do+ result <- fmpz_equal x y+ return $ result == 1++instance Ord Fmpz where+ compare x y = snd $ snd $ unsafePerformIO $+ withFmpz x $ \x ->+ withFmpz y $ \y -> do+ ord <- fmpz_cmp x y+ return $ if ord > 0 then GT else (if ord < 0 then LT else EQ)++instance Enum Fmpz where+ toEnum = fromInteger . fromIntegral+ fromEnum = fromIntegral . toInteger+ succ x = unsafePerformIO $ do+ y <- newFmpz + withFmpz x $ \x -> withFmpz y $ \y -> fmpz_add_ui y x 1+ return y+ +instance Num Fmpz where+ {-# INLINE (+) #-}+ (+) = lift2 fmpz_add+ {-# INLINE (-) #-}+ (-) = lift2 fmpz_sub+ {-# INLINE (*) #-}+ (*) = lift2 fmpz_mul+ negate = lift1 fmpz_neg+ abs = lift1 fmpz_abs+ fromInteger x = read (show x) :: Fmpz+ signum = lift1 sgn where+ sgn result x = do+ s <- fmpz_sgn x+ fmpz_set_si result (fromIntegral s)++instance Real Fmpz where+ toRational x = (toInteger x) % 1++instance Integral Fmpz where+ mod x y = unsafePerformIO $ do+ result <- newFmpz+ withFmpz result $ \result ->+ withFmpz x $ \x ->+ withFmpz y $ \y -> fmpz_mod result x y+ return result+ quotRem x y = unsafePerformIO $ do+ quot <- newFmpz+ rem <- newFmpz+ withFmpz x $ \x -> + withFmpz y $ \y -> + withFmpz quot $ \quot -> + withFmpz rem $ \rem -> + fmpz_tdiv_qr quot rem x y+ return (quot, rem)+ toInteger x = read (show x) :: Integer++instance UFD Fmpz where+ factor x = snd $ snd $ unsafePerformIO $+ withFmpz x $ \y -> do+ is_one <- fmpz_is_one y+ f <- newFmpzFactor+ withFmpzFactor f $ \f -> do+ if not (is_one == 1) then do+ fmpz_factor f y+ CFmpzFactor s d e _ n <- peek f+ result <- forM [0 .. fromIntegral n-1] $ \j -> do+ f <- newFmpz+ m <- peek (e `advancePtr` j)+ withFmpz f $ \f -> fmpz_set f (d `advancePtr` j)+ return (f, fromIntegral m)+ return $ if s < 1 then (-1, 1) : result else result+ else do+ return [(1, 1)]++instance Arbitrary Fmpz where+ arbitrary = do+ x <- arbitrary+ return $ fromInteger x+ +lift1 f x = unsafePerformIO $ do+ z <- newFmpz+ withFmpz x $ \x ->+ withFmpz z $ \z -> f z x+ return z+ +lift2 f x y = unsafePerformIO $ do+ z <- newFmpz+ withFmpz x $ \x ->+ withFmpz y $ \y ->+ withFmpz z $ \z -> f z x y+ return z
+ src/Data/Number/Flint/Fmpz/LLL.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.LLL (+ module Data.Number.Flint.Fmpz.LLL.FFI+ ) where++import Data.Number.Flint.Fmpz.LLL.FFI
+ src/Data/Number/Flint/Fmpz/LLL/FFI.hsc view
@@ -0,0 +1,496 @@+{-|+module : Data.Number.Flint.Fmpz.LLL.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.LLL.FFI (+ -- * LLL reduction+ FmpzLLL (..)+ , CFmpzLLL (..)+ , newFmpzLLL+ , newFmpzLLLDefault+ , withFmpzLLL+ , withNewFmpzLLLDefault+ -- * Parameter manipulation+ , fmpz_lll_context_init_default+ , fmpz_lll_context_init+ -- ** Representation type+ , gram+ , z_basis+ -- ** Gram type+ , approx+ , exact+ -- * Random parameter generation+ , fmpz_lll_randtest+ -- * Heuristic dot product+ , fmpz_lll_heuristic_dot+ -- * The various Babai\'s+ , fmpz_lll_check_babai+ , fmpz_lll_check_babai_heuristic_d+ , fmpz_lll_check_babai_heuristic+ , fmpz_lll_advance_check_babai+ , fmpz_lll_advance_check_babai_heuristic_d+ -- * Shift+ , fmpz_lll_shift+ -- * Varieties of LLL+ , fmpz_lll_d+ , fmpz_lll_d_heuristic+ , fmpz_lll_mpf2+ , fmpz_lll_mpf+ , fmpz_lll_wrapper+ , fmpz_lll_d_with_removal+ , fmpz_lll_d_heuristic_with_removal+ , fmpz_lll_mpf2_with_removal+ , fmpz_lll_mpf_with_removal+ , fmpz_lll_wrapper_with_removal+ , fmpz_lll_d_with_removal_knapsack+ , fmpz_lll_wrapper_with_removal_knapsack+ -- * ULLL+ , fmpz_lll_with_removal_ulll+ -- * LLL-reducedness+ , fmpz_lll_is_reduced_d+ , fmpz_lll_is_reduced+ -- * Modified ULLL+ , fmpz_lll_storjohann_ulll+ -- * Main LLL functions+ , fmpz_lll+ , fmpz_lll_with_removal+) where ++-- LLL reduction ---------------------------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Support.D.Mat+import Data.Number.Flint.Support.Mpf.Mat++#include <flint/flint.h>++#include <flint/fmpz.h>+#include <flint/fmpz_lll.h>++-- representation type ---------------------------------------------------------++newtype Rep = Rep { _Rep :: CInt }++#{enum Rep, Rep+ , gram = GRAM+ , z_basis = Z_BASIS+ }++newtype Gram = Gram { _Gram :: CInt }++#{enum Gram, Gram+ , approx = APPROX+ , exact = EXACT+ }+ +-- fmpz__lll_t -----------------------------------------------------------------++data FmpzLLL = FmpzLLL {-# UNPACK #-} !(ForeignPtr CFmpzLLL)+data CFmpzLLL = CFmpzLLL {+ delta :: CDouble,+ eta :: CDouble,+ rt :: Rep,+ gt :: Gram+ }++instance Storable CFmpzLLL where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_lll_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_lll_t}+ peek = error "CFmpzLLL.peek: Not defined"+ poke = error "CFmpzLLL.poke: Not defined"++newFmpzLLL delta eta rt gt = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p -> fmpz_lll_context_init p delta eta rt gt+ -- addForeignPtrFinalizer free p+ return $ FmpzLLL p++newFmpzLLLDefault = do+ p <- mallocForeignPtr+ withForeignPtr p fmpz_lll_context_init_default+ -- addForeignPtrFinalizer free p+ return $ FmpzLLL p++{-# INLINE withFmpzLLL #-}+withFmpzLLL (FmpzLLL p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpzLLL p,)++withNewFmpzLLLDefault f = do+ x <- newFmpzLLLDefault+ withFmpzLLL x $ \x -> f x++-- fmpz_gram_t -----------------------------------------------------------------++data FmpzGram = FmpzGram {-# UNPACK #-} !(ForeignPtr CFmpzGram)+data CFmpzGram = CFlintLib CFmpzGram++-- Parameter manipulation ------------------------------------------------------++-- These functions are used to initialise LLL context objects which are of+-- the type @fmpz_lll_t@. These objects contain all information about the+-- options governing the reduction using this module\'s functions including+-- the LLL parameters delta and eta, the representation type of the input+-- matrix (whether it is a lattice basis or a Gram matrix), and the type of+-- Gram matrix to be used during L^2 (approximate or exact).+--+-- | /fmpz_lll_context_init_default/ /fl/ +-- +-- Sets @fl->delta@, @fl->eta@, @fl->rt@ and @fl->gt@ to their default+-- values, 0.99, 0.51, \(Z\_BASIS\) and \(APPROX\) respectively.+foreign import ccall "fmpz_lll.h fmpz_lll_context_init_default"+ fmpz_lll_context_init_default :: Ptr CFmpzLLL -> IO ()++-- | /fmpz_lll_context_init/ /fl/ /delta/ /eta/ /rt/ /gt/ +-- +-- Sets @fl->delta@, @fl->eta@, @fl->rt@ and @fl->gt@ to @delta@, @eta@,+-- @rt@ and @gt@ (given as input) respectively. @delta@ and @eta@ are the+-- L^2 parameters. @delta@ and @eta@ must lie in the intervals+-- \((0.25, 1)\) and (0.5, sqrt{@delta@}) respectively. The representation+-- type is input using @rt@ and can have the values \(Z\_BASIS\) for a+-- lattice basis and \(GRAM\) for a Gram matrix. The Gram type to be used+-- during computation can be specified using @gt@ which can assume the+-- values \(APPROX\) and \(EXACT\). Note that @gt@ has meaning only when+-- @rt@ is \(Z\_BASIS\).+foreign import ccall "fmpz_lll.h fmpz_lll_context_init"+ fmpz_lll_context_init :: Ptr CFmpzLLL -> CDouble -> CDouble -> Rep -> Gram -> IO ()++-- Random parameter generation -------------------------------------------------++-- | /fmpz_lll_randtest/ /fl/ /state/ +-- +-- Sets @fl->delta@ and @fl->eta@ to random values in the interval+-- \((0.25, 1)\) and (0.5, sqrt{@delta@}) respectively. @fl->rt@ is set to+-- \(GRAM\) or \(Z\_BASIS\) and @fl->gt@ is set to \(APPROX\) or \(EXACT\)+-- in a pseudo random way.+foreign import ccall "fmpz_lll.h fmpz_lll_randtest"+ fmpz_lll_randtest :: Ptr CFmpzLLL -> Ptr CFRandState -> IO ()++-- Heuristic dot product -------------------------------------------------------++-- | /fmpz_lll_heuristic_dot/ /vec1/ /vec2/ /len2/ /B/ /k/ /j/ /exp_adj/ +-- +-- Computes the dot product of two vectors of doubles @vec1@ and @vec2@,+-- which are respectively @double@ approximations (up to scaling by a power+-- of 2) to rows @k@ and @j@ in the exact integer matrix @B@. If massive+-- cancellation is detected an exact computation is made.+-- +-- The exact computation is scaled by @2^{-exp_adj@}, where+-- @exp_adj = r2 + r1@ where \(r2\) is the exponent for row @j@ and \(r1\)+-- is the exponent for row @k@ (i.e. row @j@ is notionally thought of as+-- being multiplied by \(2^{r2}\), etc.).+-- +-- The final dot product computed by this function is then notionally the+-- return value times @2^{exp_adj@}.+foreign import ccall "fmpz_lll.h fmpz_lll_heuristic_dot"+ fmpz_lll_heuristic_dot :: Ptr CDouble -> Ptr CDouble -> CLong -> Ptr CFmpzMat -> CLong -> CLong -> CLong -> IO CDouble++-- The various Babai\'s --------------------------------------------------------++-- | /fmpz_lll_check_babai/ /kappa/ /B/ /U/ /mu/ /r/ /s/ /appB/ /expo/ /A/ /a/ /zeros/ /kappamax/ /n/ /fl/ +-- +-- Performs floating point size reductions of the @kappa@-th row of @B@ by+-- all of the previous rows, uses d_mats @mu@ and @r@ for storing the GSO+-- data. @U@ is used to capture the unimodular transformations if it is not+-- \(NULL\). The @double@ array @s@ will contain the size of the @kappa@-th+-- row if it were moved into position \(i\). The d_mat @appB@ is an+-- approximation of @B@ with each row receiving an exponent stored in+-- @expo@ which gets populated only when needed. The d_mat @A->appSP@ is an+-- approximation of the Gram matrix whose entries are scalar products of+-- the rows of @B@ and is used when @fl->gt@ == \(APPROX\). When @fl->gt@+-- == \(EXACT\) the fmpz_mat @A->exactSP@ (the exact Gram matrix) is used.+-- The index @a@ is the smallest row index which will be reduced from the+-- @kappa@-th row. Index @zeros@ is the number of zero rows in the matrix.+-- @kappamax@ is the highest index which has been size-reduced so far, and+-- @n@ is the number of columns you want to consider. @fl@ is an LLL (L^2)+-- context object. The output is the value -1 if the process fails (usually+-- due to insufficient precision) or 0 if everything was successful. These+-- descriptions will be true for the future Babai procedures as well.+foreign import ccall "fmpz_lll.h fmpz_lll_check_babai"+ fmpz_lll_check_babai :: CInt -> Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CDMat -> Ptr CDMat -> Ptr CDouble -> Ptr CDMat -> Ptr CInt -> Ptr CFmpzGram -> CInt -> CInt -> CInt -> CInt -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_check_babai_heuristic_d/ /kappa/ /B/ /U/ /mu/ /r/ /s/ /appB/ /expo/ /A/ /a/ /zeros/ /kappamax/ /n/ /fl/ +-- +-- Same as @fmpz_lll_check_babai@ but using the heuristic inner product+-- rather than a purely floating point inner product. The heuristic will+-- compute at full precision when there is cancellation.+foreign import ccall "fmpz_lll.h fmpz_lll_check_babai_heuristic_d"+ fmpz_lll_check_babai_heuristic_d :: CInt -> Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CDMat -> Ptr CDMat -> Ptr CDouble -> Ptr CDMat -> Ptr CInt -> Ptr CFmpzGram -> CInt -> CInt -> CInt -> CInt -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_check_babai_heuristic/ /kappa/ /B/ /U/ /mu/ /r/ /s/ /appB/ /A/ /a/ /zeros/ /kappamax/ /n/ /tmp/ /rtmp/ /prec/ /fl/ +-- +-- This function is like the @mpf@ version of+-- @fmpz_lll_check_babai_heuristic_d@. However, it also inherits some+-- temporary @mpf_t@ variables @tmp@ and @rtmp@.+foreign import ccall "fmpz_lll.h fmpz_lll_check_babai_heuristic"+ fmpz_lll_check_babai_heuristic :: CInt -> Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CMpfMat -> Ptr CMpfMat -> Ptr CMpf -> Ptr CMpfMat -> Ptr CFmpzGram -> CInt -> CInt -> CInt -> CInt -> Ptr CMpf -> Ptr CMpf -> CFBitCnt -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_advance_check_babai/ /cur_kappa/ /kappa/ /B/ /U/ /mu/ /r/ /s/ /appB/ /expo/ /A/ /a/ /zeros/ /kappamax/ /n/ /fl/ +-- +-- This is a Babai procedure which is used when size reducing a vector+-- beyond an index which LLL has reached. @cur_kappa@ is the index behind+-- which we can assume @B@ is LLL reduced, while @kappa@ is the vector to+-- be reduced. This procedure only size reduces the @kappa@-th row by+-- vectors upto @cur_kappa@, textbf{not} @kappa - 1@.+foreign import ccall "fmpz_lll.h fmpz_lll_advance_check_babai"+ fmpz_lll_advance_check_babai :: CInt -> CInt -> Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CDMat -> Ptr CDMat -> Ptr CDouble -> Ptr CDMat -> Ptr CInt -> Ptr CFmpzGram -> CInt -> CInt -> CInt -> CInt -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_advance_check_babai_heuristic_d/ /cur_kappa/ /kappa/ /B/ /U/ /mu/ /r/ /s/ /appB/ /expo/ /A/ /a/ /zeros/ /kappamax/ /n/ /fl/ +-- +-- Same as @fmpz_lll_advance_check_babai@ but using the heuristic inner+-- product rather than a purely floating point inner product. The heuristic+-- will compute at full precision when there is cancellation.+foreign import ccall "fmpz_lll.h fmpz_lll_advance_check_babai_heuristic_d"+ fmpz_lll_advance_check_babai_heuristic_d :: CInt -> CInt -> Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CDMat -> Ptr CDMat -> Ptr CDouble -> Ptr CDMat -> Ptr CInt -> Ptr CFmpzGram -> CInt -> CInt -> CInt -> CInt -> Ptr CFmpzLLL -> IO CInt++-- Shift -----------------------------------------------------------------------++-- | /fmpz_lll_shift/ /B/ +-- +-- Computes the largest number of non-zero entries after the diagonal in+-- @B@.+foreign import ccall "fmpz_lll.h fmpz_lll_shift"+ fmpz_lll_shift :: Ptr CFmpzMat -> IO CInt++-- Varieties of LLL ------------------------------------------------------------++-- These programs implement ideas from the book chapter < [Stehle2010]>.+-- The list of function here that are heuristic in nature and may return+-- with \(B\) unreduced - that is to say, not do their job - includes (but+-- is not necessarily limited to): * @fmpz_lll_d@ * @fmpz_lll_d_heuristic@+-- * @fmpz_lll_d_heuristic_with_removal@ * @fmpz_lll_d_with_removal@ *+-- @fmpz_lll_d_with_removal_knapsack@+--+-- | /fmpz_lll_d/ /B/ /U/ /fl/ +-- +-- This is a mildly greedy version of floating point LLL using doubles+-- only. It tries the fast version of the Babai algorithm+-- (@fmpz_lll_check_babai@). If that fails, then it switches to the+-- heuristic version (@fmpz_lll_check_babai_heuristic_d@) for only one loop+-- and switches right back to the fast version. It reduces @B@ in place.+-- @U@ is the matrix used to capture the unimodular transformations if it+-- is not \(NULL\). An exception is raised if \(U != NULL\) and+-- \(U->r != d\), where \(d\) is the lattice dimension. @fl@ is the context+-- object containing information containing the LLL parameters delta and+-- eta. The function can perform reduction on both the lattice basis as+-- well as its Gram matrix. The type of lattice representation can be+-- specified via the parameter @fl->rt@. The type of Gram matrix to be used+-- in computation (approximate or exact) can also be specified through the+-- variable @fl->gt@ (applies only if @fl->rt@ == \(Z\_BASIS\)).+foreign import ccall "fmpz_lll.h fmpz_lll_d"+ fmpz_lll_d :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_d_heuristic/ /B/ /U/ /fl/ +-- +-- This LLL reduces @B@ in place using doubles only. It is similar to+-- @fmpz_lll_d@ but only uses the heuristic inner products which attempt to+-- detect cancellations.+foreign import ccall "fmpz_lll.h fmpz_lll_d_heuristic"+ fmpz_lll_d_heuristic :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_mpf2/ /B/ /U/ /prec/ /fl/ +-- +-- This is LLL using @mpf@ with the given precision, @prec@ for the+-- underlying GSO. It reduces @B@ in place like the other LLL functions.+-- The \(mpf2\) in the function name refers to the way the @mpf_t@\'s are+-- initialised.+foreign import ccall "fmpz_lll.h fmpz_lll_mpf2"+ fmpz_lll_mpf2 :: Ptr CFmpzMat -> Ptr CFmpzMat -> CFBitCnt -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_mpf/ /B/ /U/ /fl/ +-- +-- A wrapper of @fmpz_lll_mpf2@. This currently begins with+-- \(prec == D_BITS\), then for the first 20 loops, increases the precision+-- one limb at a time. After 20 loops, it doubles the precision each time.+-- There is a proof that this will eventually work. The return value of+-- this function is 0 if the LLL is successful or -1 if the precision maxes+-- out before @B@ is LLL-reduced.+foreign import ccall "fmpz_lll.h fmpz_lll_mpf"+ fmpz_lll_mpf :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_wrapper/ /B/ /U/ /fl/ +-- +-- A wrapper of the above procedures. It begins with the greediest version+-- (@fmpz_lll_d@), then adapts to the version using heuristic inner+-- products only (@fmpz_lll_d_heuristic@) if \(fl->rt == Z\_BASIS\) and+-- \(fl->gt == APPROX\), and finally to the mpf version (@fmpz_lll_mpf@) if+-- needed.+-- +-- @U@ is the matrix used to capture the unimodular transformations if it+-- is not \(NULL\). An exception is raised if \(U != NULL\) and+-- \(U->r != d\), where \(d\) is the lattice dimension. @fl@ is the context+-- object containing information containing the LLL parameters delta and+-- eta. The function can perform reduction on both the lattice basis as+-- well as its Gram matrix. The type of lattice representation can be+-- specified via the parameter @fl->rt@. The type of Gram matrix to be used+-- in computation (approximate or exact) can also be specified through the+-- variable @fl->gt@ (applies only if @fl->rt@ == \(Z\_BASIS\)).+foreign import ccall "fmpz_lll.h fmpz_lll_wrapper"+ fmpz_lll_wrapper :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_d_with_removal/ /B/ /U/ /gs_B/ /fl/ +-- +-- Same as @fmpz_lll_d@ but with a removal bound, @gs_B@. The return value+-- is the new dimension of @B@ if removals are desired.+foreign import ccall "fmpz_lll.h fmpz_lll_d_with_removal"+ fmpz_lll_d_with_removal :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_d_heuristic_with_removal/ /B/ /U/ /gs_B/ /fl/ +-- +-- Same as @fmpz_lll_d_heuristic@ but with a removal bound, @gs_B@. The+-- return value is the new dimension of @B@ if removals are desired.+foreign import ccall "fmpz_lll.h fmpz_lll_d_heuristic_with_removal"+ fmpz_lll_d_heuristic_with_removal :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_mpf2_with_removal/ /B/ /U/ /prec/ /gs_B/ /fl/ +-- +-- Same as @fmpz_lll_mpf2@ but with a removal bound, @gs_B@. The return+-- value is the new dimension of @B@ if removals are desired.+foreign import ccall "fmpz_lll.h fmpz_lll_mpf2_with_removal"+ fmpz_lll_mpf2_with_removal :: Ptr CFmpzMat -> Ptr CFmpzMat -> CFBitCnt -> Ptr CFmpz -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_mpf_with_removal/ /B/ /U/ /gs_B/ /fl/ +-- +-- A wrapper of @fmpz_lll_mpf2_with_removal@. This currently begins with+-- \(prec == D\_BITS\), then for the first 20 loops, increases the+-- precision one limb at a time. After 20 loops, it doubles the precision+-- each time. There is a proof that this will eventually work. The return+-- value of this function is the new dimension of @B@ if removals are+-- desired or -1 if the precision maxes out before @B@ is LLL-reduced.+foreign import ccall "fmpz_lll.h fmpz_lll_mpf_with_removal"+ fmpz_lll_mpf_with_removal :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_wrapper_with_removal/ /B/ /U/ /gs_B/ /fl/ +-- +-- A wrapper of the procedures implementing the base case LLL with the+-- addition of the removal boundary. It begins with the greediest version+-- (@fmpz_lll_d_with_removal@), then adapts to the version using heuristic+-- inner products only (@fmpz_lll_d_heuristic_with_removal@) if+-- \(fl->rt == Z\_BASIS\) and \(fl->gt == APPROX\), and finally to the mpf+-- version (@fmpz_lll_mpf_with_removal@) if needed.+foreign import ccall "fmpz_lll.h fmpz_lll_wrapper_with_removal"+ fmpz_lll_wrapper_with_removal :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_d_with_removal_knapsack/ /B/ /U/ /gs_B/ /fl/ +-- +-- This is floating point LLL specialized to knapsack-type lattices. It+-- performs early size reductions occasionally which makes things faster in+-- the knapsack case. Otherwise, it is similar to+-- @fmpz_lll_d_with_removal@.+foreign import ccall "fmpz_lll.h fmpz_lll_d_with_removal_knapsack"+ fmpz_lll_d_with_removal_knapsack :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_wrapper_with_removal_knapsack/ /B/ /U/ /gs_B/ /fl/ +-- +-- A wrapper of the procedures implementing the LLL specialized to+-- knapsack-type lattices. It begins with the greediest version and the+-- engine of this version, (@fmpz_lll_d_with_removal_knapsack@), then+-- adapts to the version using heuristic inner products only+-- (@fmpz_lll_d_heuristic_with_removal@) if \(fl->rt == Z\_BASIS\) and+-- \(fl->gt == APPROX\), and finally to the mpf version+-- (@fmpz_lll_mpf_with_removal@) if needed.+foreign import ccall "fmpz_lll.h fmpz_lll_wrapper_with_removal_knapsack"+ fmpz_lll_wrapper_with_removal_knapsack :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzLLL -> IO CInt++-- ULLL ------------------------------------------------------------------------++-- | /fmpz_lll_with_removal_ulll/ /FM/ /UM/ /new_size/ /gs_B/ /fl/ +-- +-- ULLL is a new style of LLL which does adjoins an identity matrix to the+-- input lattice @FM@, then scales the lattice down to @new_size@ bits and+-- reduces this augmented lattice. This tends to be more stable numerically+-- than traditional LLL which means higher dimensions can be attacked using+-- doubles. In each iteration a new identity matrix is adjoined to the+-- truncated lattice. @UM@ is used to capture the unimodular+-- transformations, while @gs_B@ and @fl@ have the same role as in the+-- previous routines. The function is optimised for factoring polynomials.+foreign import ccall "fmpz_lll.h fmpz_lll_with_removal_ulll"+ fmpz_lll_with_removal_ulll :: Ptr CFmpzMat -> Ptr CFmpzMat -> CLong -> Ptr CFmpz -> Ptr CFmpzLLL -> IO CInt++-- LLL-reducedness -------------------------------------------------------------++-- These programs implement ideas from the paper < [Villard2007]>. See+-- <https://arxiv.org/abs/cs/0701183> for the algorithm of Villard.+--+-- | /fmpz_lll_is_reduced_d/ /B/ /fl/ +-- +-- A non-zero return indicates the matrix is definitely reduced, that is,+-- that * @fmpz_mat_is_reduced@ or @fmpz_mat_is_reduced_gram@ (for the+-- first two) * @fmpz_mat_is_reduced_with_removal@ or+-- @fmpz_mat_is_reduced_gram_with_removal@ (for the last two) return+-- non-zero. A zero return value is inconclusive. The \(_d\) variants are+-- performed in machine precision, while the \(_mpfr\) uses a precision of+-- \(prec\) bits.+foreign import ccall "fmpz_lll.h fmpz_lll_is_reduced_d"+ fmpz_lll_is_reduced_d :: Ptr CFmpzMat -> Ptr CFmpzLLL -> IO CInt++-- | /fmpz_lll_is_reduced/ /B/ /fl/ /prec/ +-- +-- The return from these functions is always conclusive: the functions *+-- @fmpz_mat_is_reduced@ or @fmpz_mat_is_reduced_gram@ *+-- @fmpz_mat_is_reduced_with_removal@ or+-- @fmpz_mat_is_reduced_gram_with_removal@ are optimzied by calling the+-- above heuristics first and returning right away if they give a+-- conclusive answer.+foreign import ccall "fmpz_lll.h fmpz_lll_is_reduced"+ fmpz_lll_is_reduced :: Ptr CFmpzMat -> Ptr CFmpzLLL -> CFBitCnt -> IO CInt++-- Modified ULLL ---------------------------------------------------------------++-- | /fmpz_lll_storjohann_ulll/ /FM/ /new_size/ /fl/ +-- +-- Performs ULLL using @fmpz_mat_lll_storjohann@ as the LLL function.+foreign import ccall "fmpz_lll.h fmpz_lll_storjohann_ulll"+ fmpz_lll_storjohann_ulll :: Ptr CFmpzMat -> CLong -> Ptr CFmpzLLL -> IO ()++-- Main LLL functions ----------------------------------------------------------++-- | /fmpz_lll/ /B/ /U/ /fl/ +-- +-- Reduces @B@ in place according to the parameters specified by the LLL+-- context object @fl@.+-- +-- This is the main LLL function which should be called by the user. It+-- currently calls the ULLL algorithm (without removals). The ULLL function+-- in turn calls a LLL wrapper which tries to choose an optimal LLL+-- algorithm, starting with a version using just doubles (ULLL tries to+-- maximise usage of this), then a heuristic LLL a full precision floating+-- point LLL if required.+-- +-- @U@ is the matrix used to capture the unimodular transformations if it+-- is not \(NULL\). An exception is raised if \(U != NULL\) and+-- \(U->r != d\), where \(d\) is the lattice dimension. @fl@ is the context+-- object containing information containing the LLL parameters delta and+-- eta. The function can perform reduction on both the lattice basis as+-- well as its Gram matrix. The type of lattice representation can be+-- specified via the parameter @fl->rt@. The type of Gram matrix to be used+-- in computation (approximate or exact) can also be specified through the+-- variable @fl->gt@ (applies only if @fl->rt@ == \(Z\_BASIS\)).+foreign import ccall "fmpz_lll.h fmpz_lll"+ fmpz_lll :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzLLL -> IO ()++-- | /fmpz_lll_with_removal/ /B/ /U/ /gs_B/ /fl/ +-- +-- Reduces @B@ in place according to the parameters specified by the LLL+-- context object @fl@ and removes vectors whose squared Gram-Schmidt+-- length is greater than the bound @gs_B@. The return value is the new+-- dimension of @B@ to be considered for further computation.+-- +-- This is the main LLL with removals function which should be called by+-- the user. Like @fmpz_lll@ it calls ULLL, but it also sets the+-- Gram-Schmidt bound to that supplied and does removals.+foreign import ccall "fmpz_lll.h fmpz_lll_with_removal"+ fmpz_lll_with_removal :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzLLL -> IO CInt+
+ src/Data/Number/Flint/Fmpz/MPoly.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.MPoly (+ module Data.Number.Flint.Fmpz.MPoly.FFI+ ) where++import Data.Number.Flint.Fmpz.MPoly.FFI
+ src/Data/Number/Flint/Fmpz/MPoly/FFI.hsc view
@@ -0,0 +1,1568 @@+{-|+module : Data.Number.Flint.Fmpz.MPoly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.MPoly.FFI (+ -- * Multivariate polynomials over the integers+ FmpzMPoly (..)+ , CFmpzMPoly (..)+ -- * Constructor+ , newFmpzMPoly+ , withFmpzMPoly+ -- * Context object+ , FmpzMPolyCtx (..)+ , CFmpzMPolyCtx (..)+ , newFmpzMPolyCtx+ , withFmpzMPolyCtx+ , fmpz_mpoly_ctx_init+ , fmpz_mpoly_ctx_nvars+ , fmpz_mpoly_ctx_ord+ , fmpz_mpoly_ctx_clear+ -- * Memory management+ , fmpz_mpoly_init+ , fmpz_mpoly_init2+ , fmpz_mpoly_init3+ , fmpz_mpoly_fit_length+ , fmpz_mpoly_fit_bits+ , fmpz_mpoly_realloc+ , fmpz_mpoly_clear+ -- * Input\/Output+ , fmpz_mpoly_get_str_pretty+ , fmpz_mpoly_fprint_pretty+ , fmpz_mpoly_print_pretty+ , fmpz_mpoly_set_str_pretty+ -- * Basic manipulation+ , fmpz_mpoly_gen+ , fmpz_mpoly_is_gen+ , fmpz_mpoly_set+ , fmpz_mpoly_equal+ , fmpz_mpoly_swap+ , _fmpz_mpoly_fits_small+ , fmpz_mpoly_max_bits+ -- * Constants+ , fmpz_mpoly_is_fmpz+ , fmpz_mpoly_get_fmpz+ , fmpz_mpoly_set_fmpz+ , fmpz_mpoly_zero+ , fmpz_mpoly_one+ , fmpz_mpoly_equal_fmpz+ , fmpz_mpoly_is_zero+ , fmpz_mpoly_is_one+ -- * Degrees+ , fmpz_mpoly_degrees_fit_si+ , fmpz_mpoly_degrees_fmpz+ , fmpz_mpoly_degree_fmpz+ , fmpz_mpoly_total_degree_fits_si+ , fmpz_mpoly_total_degree_fmpz+ , fmpz_mpoly_used_vars+ -- * Coefficients+ , fmpz_mpoly_get_coeff_fmpz_monomial+ , fmpz_mpoly_set_coeff_fmpz_monomial+ , fmpz_mpoly_get_coeff_fmpz_fmpz+ , fmpz_mpoly_set_coeff_fmpz_fmpz+ , fmpz_mpoly_get_coeff_vars_ui+ -- * Comparison+ , fmpz_mpoly_cmp+ -- * Conversion+ , fmpz_mpoly_is_fmpz_poly+ , fmpz_mpoly_get_fmpz_poly+ , fmpz_mpoly_set_fmpz_poly+ -- * Container operations+ , fmpz_mpoly_term_coeff_ref+ , fmpz_mpoly_is_canonical+ , fmpz_mpoly_length+ , fmpz_mpoly_resize+ , fmpz_mpoly_get_term_coeff_fmpz+ , fmpz_mpoly_set_term_coeff_fmpz+ , fmpz_mpoly_term_exp_fits_si+ , fmpz_mpoly_get_term_exp_fmpz+ , fmpz_mpoly_get_term_var_exp_ui+ , fmpz_mpoly_set_term_exp_fmpz+ , fmpz_mpoly_get_term+ , fmpz_mpoly_get_term_monomial+ , fmpz_mpoly_push_term_fmpz_fmpz+ , fmpz_mpoly_sort_terms+ , fmpz_mpoly_combine_like_terms+ , fmpz_mpoly_reverse+ -- * Random generation+ , fmpz_mpoly_randtest_bound+ , fmpz_mpoly_randtest_bounds+ , fmpz_mpoly_randtest_bits+ -- * Addition\/Subtraction+ , fmpz_mpoly_add_fmpz+ , fmpz_mpoly_sub_fmpz+ , fmpz_mpoly_add+ , fmpz_mpoly_sub+ -- * Scalar operations+ , fmpz_mpoly_neg+ , fmpz_mpoly_scalar_mul_fmpz+ , fmpz_mpoly_scalar_fmma+ , fmpz_mpoly_scalar_divexact_fmpz+ , fmpz_mpoly_scalar_divides_fmpz+ -- * Differentiation\/Integration+ , fmpz_mpoly_derivative+ , fmpz_mpoly_integral+ -- * Evaluation+ , fmpz_mpoly_evaluate_all_fmpz+ , fmpz_mpoly_evaluate_one_fmpz+ , fmpz_mpoly_compose_fmpz_poly+ , fmpz_mpoly_compose_fmpz_mpoly_geobucket+ , fmpz_mpoly_compose_fmpz_mpoly_gen+ -- * Multiplication+ , fmpz_mpoly_mul+ , fmpz_mpoly_mul_johnson+ , fmpz_mpoly_mul_array+ , fmpz_mpoly_mul_dense+ -- * Powering+ , fmpz_mpoly_pow_fmpz+ , fmpz_mpoly_pow_ui+ -- * Division+ , fmpz_mpoly_divides+ , fmpz_mpoly_divrem+ , fmpz_mpoly_quasidivrem+ , fmpz_mpoly_div+ , fmpz_mpoly_quasidiv+ , fmpz_mpoly_divrem_ideal+ , fmpz_mpoly_quasidivrem_ideal+ -- * Greatest Common Divisor+ , fmpz_mpoly_term_content+ , fmpz_mpoly_content_vars+ , fmpz_mpoly_gcd+ , fmpz_mpoly_gcd_cofactors+ , fmpz_mpoly_gcd_brown+ , fmpz_mpoly_resultant+ , fmpz_mpoly_discriminant+ , fmpz_mpoly_primitive_part+ -- * Square Root+ , fmpz_mpoly_sqrt_heap+ , fmpz_mpoly_sqrt+ , fmpz_mpoly_is_square+ -- * Univariate Functions+ , fmpz_mpoly_univar_init+ , fmpz_mpoly_univar_clear+ , fmpz_mpoly_univar_swap+ , fmpz_mpoly_to_univar+ , fmpz_mpoly_from_univar+ , fmpz_mpoly_univar_degree_fits_si+ , fmpz_mpoly_univar_length+ , fmpz_mpoly_univar_get_term_exp_si+ , fmpz_mpoly_univar_get_term_coeff+ -- * Internal Functions+ , fmpz_mpoly_inflate+ , fmpz_mpoly_deflate+ , fmpz_mpoly_deflation+ , fmpz_mpoly_pow_fps+ , _fmpz_mpoly_divides_array+ , fmpz_mpoly_divides_array+ , _fmpz_mpoly_divides_monagan_pearce+ , fmpz_mpoly_divides_monagan_pearce+ , fmpz_mpoly_divides_heap_threaded+ , _fmpz_mpoly_div_monagan_pearce+ , fmpz_mpoly_div_monagan_pearce+ , _fmpz_mpoly_divrem_monagan_pearce+ , fmpz_mpoly_divrem_monagan_pearce+ , _fmpz_mpoly_divrem_array+ , fmpz_mpoly_divrem_array+ , fmpz_mpoly_quasidivrem_heap+ , _fmpz_mpoly_divrem_ideal_monagan_pearce+ , fmpz_mpoly_divrem_ideal_monagan_pearce+ -- * Vectors+ , fmpz_mpoly_vec_init+ , fmpz_mpoly_vec_clear+ , fmpz_mpoly_vec_print+ , fmpz_mpoly_vec_swap+ , fmpz_mpoly_vec_fit_length+ , fmpz_mpoly_vec_set+ , fmpz_mpoly_vec_append+ , fmpz_mpoly_vec_insert_unique+ , fmpz_mpoly_vec_set_length+ , fmpz_mpoly_vec_randtest_not_zero+ , fmpz_mpoly_vec_set_primitive_unique+ -- * Ideals and Gröbner bases+ , fmpz_mpoly_spoly+ , fmpz_mpoly_reduction_primitive_part+ , fmpz_mpoly_vec_is_groebner+ , fmpz_mpoly_vec_is_autoreduced+ , fmpz_mpoly_vec_autoreduction+ , fmpz_mpoly_vec_autoreduction_groebner+ -- , fmpz_mpoly_select_pop_pair+ , fmpz_mpoly_buchberger_naive+ , fmpz_mpoly_buchberger_naive_with_limits+ -- * Special polynomials+ , fmpz_mpoly_symmetric_gens+ , fmpz_mpoly_symmetric+) where++-- Multivariate polynomials over the integers ----------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpq+import Data.Number.Flint.MPoly++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpq.h>+#include <flint/fmpz_mpoly.h>++-- fmpz_mpoly_t ----------------------------------------------------------------++data FmpzMPoly = FmpzMPoly {-# UNPACK #-} !(ForeignPtr CFmpzMPoly)+data CFmpzMPoly = CFmpzMPoly ++instance Storable CFmpzMPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mpoly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mpoly_t}+ peek = error "CFmpzMPoly.peek: Not defined"+ poke = error "CFmpzMPoly.poke: Not defined"++-- | /newFmpzMPoly/ /ctx/+--+-- Construct a new `FmpzMPoly` with context /ctx/.+newFmpzMPoly ctx@(FmpzMPolyCtx pctx) = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withFmpzMPolyCtx ctx $ \ctx -> do + fmpz_mpoly_init p ctx+ addForeignPtrFinalizerEnv p_fmpz_mpoly_clear p pctx + return $ FmpzMPoly p++{-# INLINE withFmpzMPoly #-}+withFmpzMPoly (FmpzMPoly p) f = do+ withForeignPtr p $ \fp -> (FmpzMPoly p,) <$> f fp++-- | /withNewFmpzMPoly/ /ctx/+--+-- Execute computation /f/ on a new `FmpzMPoly` with context /ctx/.+{-# INLINE withNewFmpzMPoly #-}+withNewFmpzMPoly ctx f = do+ x <- newFmpzMPoly ctx+ withFmpzMPoly x f++-- fmpz_mpoly_univar_t ---------------------------------------------------------++data FmpzMPolyUnivar = FmpzMPolyUnivar {-# UNPACK #-} !(ForeignPtr CFmpzMPolyUnivar)+data CFmpzMPolyUnivar = CFmpzMPolyUnivar ++instance Storable CFmpzMPolyUnivar where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mpoly_univar_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mpoly_univar_t}+ peek = error "CFmpzMPolyUnivar.peek: Not defined"+ poke = error "CFmpzMPolyUnivar.poke: Not defined"++-- | Create a new `FmpzMPolyUnivar`+newFmpzMPolyUnivar ctx@(FmpzMPolyCtx pctx) = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withFmpzMPolyCtx ctx $ \ctx -> do + fmpz_mpoly_univar_init p ctx+ addForeignPtrFinalizerEnv p_fmpz_mpoly_univar_clear p pctx+ return $ FmpzMPolyUnivar p++{-# INLINE withFmpzMPolyUnivar #-}+withFmpzMPolyUnivar (FmpzMPolyUnivar p) f = do+ withForeignPtr p $ \fp -> (FmpzMPolyUnivar p,) <$> f fp+ +-- fmpz_mpoly_ctx_t ------------------------------------------------------------++data FmpzMPolyCtx = FmpzMPolyCtx {-# UNPACK #-} !(ForeignPtr CFmpzMPolyCtx)+data CFmpzMPolyCtx++instance Storable CFmpzMPolyCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mpoly_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mpoly_ctx_t}+ peek = error "CFmpzMPolyCtx.peek: Not defined"+ poke = error "CFmpzMPolyCtx.poke: Not defined"++-- | Create a new `FmpzMPolyCtx`+newFmpzMPolyCtx nvars ord = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ fmpz_mpoly_ctx_init p nvars ord+ addForeignPtrFinalizer p_fmpz_mpoly_ctx_clear p+ return $ FmpzMPolyCtx p++-- | Use a `FmpzMPolyCtx`+{-# INLINE withFmpzMPolyCtx #-}+withFmpzMPolyCtx (FmpzMPolyCtx p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpzMPolyCtx p,)++-- fmpz_mpoly_vec_t ------------------------------------------------------------++data FmpzMPolyVec = FmpzMPolyVec {-# UNPACK #-} !(ForeignPtr CFmpzMPolyVec)+data CFmpzMPolyVec = CFmpzMPolyVec (Ptr CFmpzMPoly) CLong CLong++-- pair_t ----------------------------------------------------------------------++data CPair = CPair CLong CLong+data CPairs = CPairs (Ptr CPair) CLong CLong++--------------------------------------------------------------------------------++-- | /fmpz_mpoly_ctx_init/ /ctx/ /nvars/ /ord/ +-- +-- Initialise a context object for a polynomial ring with the given number+-- of variables and the given ordering. The possibilities for the ordering+-- are @ORD_LEX@, @ORD_DEGLEX@ and @ORD_DEGREVLEX@.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_ctx_init"+ fmpz_mpoly_ctx_init :: Ptr CFmpzMPolyCtx -> CLong -> COrdering -> IO ()++-- | /fmpz_mpoly_ctx_nvars/ /ctx/ +-- +-- Return the number of variables used to initialize the context.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_ctx_nvars"+ fmpz_mpoly_ctx_nvars :: Ptr CFmpzMPolyCtx -> IO CLong++-- | /fmpz_mpoly_ctx_ord/ /ctx/ +-- +-- Return the ordering used to initialize the context.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_ctx_ord"+ fmpz_mpoly_ctx_ord :: Ptr CFmpzMPolyCtx -> IO COrdering++-- | /fmpz_mpoly_ctx_clear/ /ctx/ +-- +-- Release up any space allocated by /ctx/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_ctx_clear"+ fmpz_mpoly_ctx_clear :: Ptr CFmpzMPolyCtx -> IO ()++foreign import ccall "fmpz_mpoly.h &fmpz_mpoly_ctx_clear"+ p_fmpz_mpoly_ctx_clear :: FunPtr (Ptr CFmpzMPolyCtx -> IO ())++-- Memory management -----------------------------------------------------------++-- | /fmpz_mpoly_init/ /A/ /ctx/ +-- +-- Initialise /A/ for use with the given and initialised context object.+-- Its value is set to zero.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_init"+ fmpz_mpoly_init :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_init2/ /A/ /alloc/ /ctx/ +-- +-- Initialise /A/ for use with the given and initialised context object.+-- Its value is set to zero. It is allocated with space for /alloc/ terms+-- and at least @MPOLY_MIN_BITS@ bits for the exponents.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_init2"+ fmpz_mpoly_init2 :: Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_init3/ /A/ /alloc/ /bits/ /ctx/ +-- +-- Initialise /A/ for use with the given and initialised context object.+-- Its value is set to zero. It is allocated with space for /alloc/ terms+-- and /bits/ bits for the exponents.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_init3"+ fmpz_mpoly_init3 :: Ptr CFmpzMPoly -> CLong -> CFBitCnt -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_fit_length/ /A/ /len/ /ctx/ +-- +-- Ensure that /A/ has space for at least /len/ terms.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_fit_length"+ fmpz_mpoly_fit_length :: Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_fit_bits/ /A/ /bits/ /ctx/ +-- +-- Ensure that the exponent fields of /A/ have at least /bits/ bits.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_fit_bits"+ fmpz_mpoly_fit_bits :: Ptr CFmpzMPoly -> CFBitCnt -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_realloc/ /A/ /alloc/ /ctx/ +-- +-- Reallocate /A/ to have space for /alloc/ terms. Assumes the current+-- length of the polynomial is not greater than /alloc/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_realloc"+ fmpz_mpoly_realloc :: Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_clear/ /A/ /ctx/ +-- +-- Release any space allocated for /A/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_clear"+ fmpz_mpoly_clear :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++foreign import ccall "fmpz_mpoly.h &fmpz_mpoly_clear"+ p_fmpz_mpoly_clear :: FunPtr (Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ())++-- Input\/Output ---------------------------------------------------------------++-- | /fmpz_mpoly_get_str_pretty/ /A/ /x/ /ctx/ +-- +-- Return a string, which the user is responsible for cleaning up,+-- representing /A/, given an array of variable strings /x/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_get_str_pretty"+ fmpz_mpoly_get_str_pretty :: Ptr CFmpzMPoly -> Ptr (Ptr CChar) -> Ptr CFmpzMPolyCtx -> IO CString++-- | /fmpz_mpoly_fprint_pretty/ /file/ /A/ /x/ /ctx/ +-- +-- Print a string representing /A/ to /file/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_fprint_pretty"+ fmpz_mpoly_fprint_pretty :: Ptr CFile -> Ptr CFmpzMPoly -> Ptr (Ptr CChar) -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_print_pretty/ /A/ /x/ /ctx/ +-- +-- Print a string representing /A/ to @stdout@.+-- foreign import ccall "fmpz_mpoly.h fmpz_mpoly_print_pretty"+-- fmpz_mpoly_print_pretty :: Ptr CFmpzMPoly -> Ptr (Ptr CChar) -> Ptr CFmpzMPolyCtx -> IO CInt+fmpz_mpoly_print_pretty :: Ptr CFmpzMPoly ->+ Ptr (Ptr CChar) ->+ Ptr CFmpzMPolyCtx -> IO CInt+fmpz_mpoly_print_pretty a x ctx =+ printCStr (\a -> fmpz_mpoly_get_str_pretty a x ctx) a++-- | /fmpz_mpoly_set_str_pretty/ /A/ /str/ /x/ /ctx/ +-- +-- Set /A/ to the polynomial in the null-terminates string /str/ given an+-- array /x/ of variable strings. If parsing /str/ fails, /A/ is set to+-- zero, and \(-1\) is returned. Otherwise, \(0\) is returned. The+-- operations @+@, @-@, @*@, and @\/@ are permitted along with integers and+-- the variables in /x/. The character @^@ must be immediately followed by+-- the (integer) exponent. If any division is not exact, parsing fails.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_set_str_pretty"+ fmpz_mpoly_set_str_pretty :: Ptr CFmpzMPoly -> CString -> Ptr (Ptr CChar) -> Ptr CFmpzMPolyCtx -> IO CInt++-- Basic manipulation ----------------------------------------------------------++-- | /fmpz_mpoly_gen/ /A/ /var/ /ctx/ +-- +-- Set /A/ to the variable of index /var/, where \(var = 0\) corresponds to+-- the variable with the most significance with respect to the ordering.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_gen"+ fmpz_mpoly_gen :: Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_is_gen/ /A/ /var/ /ctx/ +-- +-- If \(var \ge 0\), return \(1\) if /A/ is equal to the \(var\)-th+-- generator, otherwise return \(0\). If \(var < 0\), return \(1\) if the+-- polynomial is equal to any generator, otherwise return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_is_gen"+ fmpz_mpoly_is_gen :: Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_set/ /A/ /B/ /ctx/ +-- +-- Set /A/ to /B/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_set"+ fmpz_mpoly_set :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_equal/ /A/ /B/ /ctx/ +-- +-- Return \(1\) if /A/ is equal to /B/, else return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_equal"+ fmpz_mpoly_equal :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_swap/ /poly1/ /poly2/ /ctx/ +-- +-- Efficiently swap /A/ and /B/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_swap"+ fmpz_mpoly_swap :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /_fmpz_mpoly_fits_small/ /poly/ /len/ +-- +-- Return 1 if the array of coefficients of length /len/ consists entirely+-- of values that are small @fmpz@ values, i.e. of at most @FLINT_BITS - 2@+-- bits plus a sign bit.+foreign import ccall "fmpz_mpoly.h _fmpz_mpoly_fits_small"+ _fmpz_mpoly_fits_small :: Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_mpoly_max_bits/ /A/ +-- +-- Computes the maximum number of bits \(b\) required to represent the+-- absolute values of the coefficients of /A/. If all of the coefficients+-- are positive, \(b\) is returned, otherwise \(-b\) is returned.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_max_bits"+ fmpz_mpoly_max_bits :: Ptr CFmpzMPoly -> IO CLong++-- Constants -------------------------------------------------------------------++-- | /fmpz_mpoly_is_fmpz/ /A/ /ctx/ +-- +-- Return \(1\) if /A/ is a constant, else return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_is_fmpz"+ fmpz_mpoly_is_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_get_fmpz/ /c/ /A/ /ctx/ +-- +-- Assuming that /A/ is a constant, set /c/ to this constant. This function+-- throws if /A/ is not a constant.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_get_fmpz"+ fmpz_mpoly_get_fmpz :: Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_set_fmpz/ /A/ /c/ /ctx/ +-- +-- Set /A/ to the constant /c/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_set_fmpz"+ fmpz_mpoly_set_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_zero/ /A/ /ctx/ +-- +-- Set /A/ to the constant \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_zero"+ fmpz_mpoly_zero :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_one/ /A/ /ctx/ +-- +-- Set /A/ to the constant \(1\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_one"+ fmpz_mpoly_one :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_equal_fmpz/ /A/ /c/ /ctx/ +-- +-- Return \(1\) if /A/ is equal to the constant /c/, else return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_equal_fmpz"+ fmpz_mpoly_equal_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_is_zero/ /A/ /ctx/ +-- +-- Return \(1\) if /A/ is the constant \(0\), else return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_is_zero"+ fmpz_mpoly_is_zero :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_is_one/ /A/ /ctx/ +-- +-- Return \(1\) if /A/ is the constant \(1\), else return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_is_one"+ fmpz_mpoly_is_one :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- Degrees ---------------------------------------------------------------------++-- | /fmpz_mpoly_degrees_fit_si/ /A/ /ctx/ +-- +-- Return \(1\) if the degrees of /A/ with respect to each variable fit+-- into an @slong@, otherwise return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_degrees_fit_si"+ fmpz_mpoly_degrees_fit_si :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_degrees_fmpz/ /degs/ /A/ /ctx/ +-- +-- Set /degs/ to the degrees of /A/ with respect to each variable. If /A/+-- is zero, all degrees are set to \(-1\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_degrees_fmpz"+ fmpz_mpoly_degrees_fmpz :: Ptr (Ptr CFmpz) -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_degree_fmpz/ /deg/ /A/ /var/ /ctx/ +-- +-- Either return or set /deg/ to the degree of /A/ with respect to the+-- variable of index /var/. If /A/ is zero, the degree is defined to be+-- \(-1\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_degree_fmpz"+ fmpz_mpoly_degree_fmpz :: Ptr CFmpz -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_total_degree_fits_si/ /A/ /ctx/ +-- +-- Return \(1\) if the total degree of /A/ fits into an @slong@, otherwise+-- return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_total_degree_fits_si"+ fmpz_mpoly_total_degree_fits_si :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_total_degree_fmpz/ /tdeg/ /A/ /ctx/ +-- +-- Either return or set /tdeg/ to the total degree of /A/. If /A/ is zero,+-- the total degree is defined to be \(-1\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_total_degree_fmpz"+ fmpz_mpoly_total_degree_fmpz :: Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_used_vars/ /used/ /A/ /ctx/ +-- +-- For each variable index /i/, set @used[i]@ to nonzero if the variable of+-- index /i/ appears in /A/ and to zero otherwise.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_used_vars"+ fmpz_mpoly_used_vars :: Ptr CInt -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- Coefficients ----------------------------------------------------------------++-- | /fmpz_mpoly_get_coeff_fmpz_monomial/ /c/ /A/ /M/ /ctx/ +-- +-- Assuming that /M/ is a monomial, set /c/ to the coefficient of the+-- corresponding monomial in /A/. This function throws if /M/ is not a+-- monomial.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_get_coeff_fmpz_monomial"+ fmpz_mpoly_get_coeff_fmpz_monomial :: Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_set_coeff_fmpz_monomial/ /poly/ /c/ /poly2/ /ctx/ +-- +-- Assuming that /M/ is a monomial, set the coefficient of the+-- corresponding monomial in /A/ to /c/. This function throws if /M/ is not+-- a monomial.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_set_coeff_fmpz_monomial"+ fmpz_mpoly_set_coeff_fmpz_monomial :: Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_get_coeff_fmpz_fmpz/ /c/ /A/ /exp/ /ctx/ +-- +-- Either return or set /c/ to the coefficient of the monomial with+-- exponent vector /exp/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_get_coeff_fmpz_fmpz"+ fmpz_mpoly_get_coeff_fmpz_fmpz :: Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr (Ptr CFmpz) -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_set_coeff_fmpz_fmpz/ /A/ /c/ /exp/ /ctx/ +-- +-- Set the coefficient of the monomial with exponent vector /exp/ to /c/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_set_coeff_fmpz_fmpz"+ fmpz_mpoly_set_coeff_fmpz_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr (Ptr CFmpz) -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_get_coeff_vars_ui/ /C/ /A/ /vars/ /exps/ /length/ /ctx/ +-- +-- Set /C/ to the coefficient of /A/ with respect to the variables in+-- /vars/ with powers in the corresponding array /exps/. Both /vars/ and+-- /exps/ point to array of length /length/. It is assumed that+-- \(0 < length \le nvars(A)\) and that the variables in /vars/ are+-- distinct.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_get_coeff_vars_ui"+ fmpz_mpoly_get_coeff_vars_ui :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CLong -> Ptr CULong -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fmpz_mpoly_cmp/ /A/ /B/ /ctx/ +-- +-- Return \(1\) (resp. \(-1\), or \(0\)) if /A/ is after (resp. before,+-- same as) /B/ in some arbitrary but fixed total ordering of the+-- polynomials. This ordering agrees with the usual ordering of monomials+-- when /A/ and /B/ are both monomials.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_cmp"+ fmpz_mpoly_cmp :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- Conversion ------------------------------------------------------------------++-- | /fmpz_mpoly_is_fmpz_poly/ /A/ /var/ /ctx/ +-- +-- Return whether /A/ is a univariate polynomial in the variable with index+-- /var/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_is_fmpz_poly"+ fmpz_mpoly_is_fmpz_poly :: Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_get_fmpz_poly/ /A/ /B/ /var/ /ctx/ +-- +-- If /B/ is a univariate polynomial in the variable with index /var/, set+-- /A/ to this polynomial and return 1; otherwise return 0.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_get_fmpz_poly"+ fmpz_mpoly_get_fmpz_poly :: Ptr CFmpzPoly -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_set_fmpz_poly/ /A/ /B/ /var/ /ctx/ +-- +-- Set /A/ to the univariate polynomial /B/ in the variable with index+-- /var/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_set_fmpz_poly"+ fmpz_mpoly_set_fmpz_poly :: Ptr CFmpzMPoly -> Ptr CFmpzPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- Container operations --------------------------------------------------------++-- | /fmpz_mpoly_term_coeff_ref/ /A/ /i/ /ctx/ +-- +-- Return a reference to the coefficient of index /i/ of /A/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_term_coeff_ref"+ fmpz_mpoly_term_coeff_ref :: Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO (Ptr CFmpz)++-- | /fmpz_mpoly_is_canonical/ /A/ /ctx/ +-- +-- Return \(1\) if /A/ is in canonical form. Otherwise, return \(0\). To be+-- in canonical form, all of the terms must have nonzero coefficient, and+-- the terms must be sorted from greatest to least.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_is_canonical"+ fmpz_mpoly_is_canonical :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_length/ /A/ /ctx/ +-- +-- Return the number of terms in /A/. If the polynomial is in canonical+-- form, this will be the number of nonzero coefficients.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_length"+ fmpz_mpoly_length :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CLong++-- | /fmpz_mpoly_resize/ /A/ /new_length/ /ctx/ +-- +-- Set the length of /A/ to \(new\_length\). Terms are either deleted from+-- the end, or new zero terms are appended.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_resize"+ fmpz_mpoly_resize :: Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_get_term_coeff_fmpz/ /c/ /A/ /i/ /ctx/ +-- +-- Either return or set /c/ to the coefficient of the term of index /i/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_get_term_coeff_fmpz"+ fmpz_mpoly_get_term_coeff_fmpz :: Ptr CFmpz -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_set_term_coeff_fmpz/ /A/ /i/ /c/ /ctx/ +-- +-- Set the coefficient of the term of index /i/ to /c/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_set_term_coeff_fmpz"+ fmpz_mpoly_set_term_coeff_fmpz :: Ptr CFmpzMPoly -> CLong -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_term_exp_fits_si/ /poly/ /i/ /ctx/ +-- +-- Return \(1\) if all entries of the exponent vector of the term of index+-- /i/ fit into an @slong@ (resp. a @ulong@). Otherwise, return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_term_exp_fits_si"+ fmpz_mpoly_term_exp_fits_si :: Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_get_term_exp_fmpz/ /exp/ /A/ /i/ /ctx/ +-- +-- Set /exp/ to the exponent vector of the term of index /i/. The @_ui@+-- (resp. @_si@) version throws if any entry does not fit into a @ulong@+-- (resp. @slong@).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_get_term_exp_fmpz"+ fmpz_mpoly_get_term_exp_fmpz :: Ptr (Ptr CFmpz) -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_get_term_var_exp_ui/ /A/ /i/ /var/ /ctx/ +-- +-- Return the exponent of the variable \(var\) of the term of index /i/.+-- This function throws if the exponent does not fit into a @ulong@ (resp.+-- @slong@).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_get_term_var_exp_ui"+ fmpz_mpoly_get_term_var_exp_ui :: Ptr CFmpzMPoly -> CLong -> CLong -> Ptr CFmpzMPolyCtx -> IO CULong++-- | /fmpz_mpoly_set_term_exp_fmpz/ /A/ /i/ /exp/ /ctx/ +-- +-- Set the exponent vector of the term of index /i/ to /exp/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_set_term_exp_fmpz"+ fmpz_mpoly_set_term_exp_fmpz :: Ptr CFmpzMPoly -> CLong -> Ptr (Ptr CFmpz) -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_get_term/ /M/ /A/ /i/ /ctx/ +-- +-- Set \(M\) to the term of index /i/ in /A/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_get_term"+ fmpz_mpoly_get_term :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_get_term_monomial/ /M/ /A/ /i/ /ctx/ +-- +-- Set \(M\) to the monomial of the term of index /i/ in /A/. The+-- coefficient of \(M\) will be one.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_get_term_monomial"+ fmpz_mpoly_get_term_monomial :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_push_term_fmpz_fmpz/ /A/ /c/ /exp/ /ctx/ +-- +-- Append a term to /A/ with coefficient /c/ and exponent vector /exp/.+-- This function runs in constant average time.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_push_term_fmpz_fmpz"+ fmpz_mpoly_push_term_fmpz_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr (Ptr CFmpz) -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_sort_terms/ /A/ /ctx/ +-- +-- Sort the terms of /A/ into the canonical ordering dictated by the+-- ordering in /ctx/. This function simply reorders the terms: It does not+-- combine like terms, nor does it delete terms with coefficient zero. This+-- function runs in linear time in the size of /A/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_sort_terms"+ fmpz_mpoly_sort_terms :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_combine_like_terms/ /A/ /ctx/ +-- +-- Combine adjacent like terms in /A/ and delete terms with coefficient+-- zero. If the terms of /A/ were sorted to begin with, the result will be+-- in canonical form. This function runs in linear time in the size of /A/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_combine_like_terms"+ fmpz_mpoly_combine_like_terms :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_reverse/ /A/ /B/ /ctx/ +-- +-- Set /A/ to the reversal of /B/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_reverse"+ fmpz_mpoly_reverse :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- Random generation -----------------------------------------------------------++-- | /fmpz_mpoly_randtest_bound/ /A/ /state/ /length/ /coeff_bits/ /exp_bound/ /ctx/ +-- +-- Generate a random polynomial with length up to /length/ and exponents in+-- the range @[0, exp_bound - 1]@. The exponents of each variable are+-- generated by calls to @n_randint(state, exp_bound)@.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_randtest_bound"+ fmpz_mpoly_randtest_bound :: Ptr CFmpzMPoly -> Ptr CFRandState -> CLong -> CMpLimb -> CULong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_randtest_bounds/ /A/ /state/ /length/ /coeff_bits/ /exp_bounds/ /ctx/ +-- +-- Generate a random polynomial with length up to /length/ and exponents in+-- the range @[0, exp_bounds[i] - 1]@. The exponents of the variable of+-- index /i/ are generated by calls to @n_randint(state, exp_bounds[i])@.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_randtest_bounds"+ fmpz_mpoly_randtest_bounds :: Ptr CFmpzMPoly -> Ptr CFRandState -> CLong -> CMpLimb -> Ptr CULong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_randtest_bits/ /A/ /state/ /length/ /coeff_bits/ /exp_bits/ /ctx/ +-- +-- Generate a random polynomial with length up to the given length and+-- exponents whose packed form does not exceed the given bit count.+-- +-- The parameter @coeff_bits@ to the three functions+-- @fmpz_mpoly_randtest_{bound|bounds|bits}@ is merely a suggestion for the+-- approximate bit count of the resulting signed coefficients. The function+-- @fmpz_mpoly_max_bits@ will give the exact bit count of the result.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_randtest_bits"+ fmpz_mpoly_randtest_bits :: Ptr CFmpzMPoly -> Ptr CFRandState -> CLong -> CMpLimb -> CMpLimb -> Ptr CFmpzMPolyCtx -> IO ()++-- Addition\/Subtraction -------------------------------------------------------++-- | /fmpz_mpoly_add_fmpz/ /A/ /B/ /c/ /ctx/ +-- +-- Set /A/ to \(B + c\). If /A/ and /B/ are aliased, this function will+-- probably run quickly.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_add_fmpz"+ fmpz_mpoly_add_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_sub_fmpz/ /A/ /B/ /c/ /ctx/ +-- +-- Set /A/ to \(B - c\). If /A/ and /B/ are aliased, this function will+-- probably run quickly.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_sub_fmpz"+ fmpz_mpoly_sub_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_add/ /A/ /B/ /C/ /ctx/ +-- +-- Set /A/ to \(B + C\). If /A/ and /B/ are aliased, this function might+-- run in time proportional to the size of \(C\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_add"+ fmpz_mpoly_add :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_sub/ /A/ /B/ /C/ /ctx/ +-- +-- Set /A/ to \(B - C\). If /A/ and /B/ are aliased, this function might+-- run in time proportional to the size of \(C\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_sub"+ fmpz_mpoly_sub :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- Scalar operations -----------------------------------------------------------++-- | /fmpz_mpoly_neg/ /A/ /B/ /ctx/ +-- +-- Set /A/ to \(-B\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_neg"+ fmpz_mpoly_neg :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_scalar_mul_fmpz/ /A/ /B/ /c/ /ctx/ +-- +-- Set /A/ to \(B \times c\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_scalar_mul_fmpz"+ fmpz_mpoly_scalar_mul_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_scalar_fmma/ /A/ /B/ /c/ /D/ /e/ /ctx/ +-- +-- Sets /A/ to \(B \times c + D \times e\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_scalar_fmma"+ fmpz_mpoly_scalar_fmma :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_scalar_divexact_fmpz/ /A/ /B/ /c/ /ctx/ +-- +-- Set /A/ to /B/ divided by /c/. The division is assumed to be exact.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_scalar_divexact_fmpz"+ fmpz_mpoly_scalar_divexact_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_scalar_divides_fmpz/ /A/ /B/ /c/ /ctx/ +-- +-- If /B/ is divisible by /c/, set /A/ to the exact quotient and return+-- \(1\), otherwise set /A/ to zero and return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_scalar_divides_fmpz"+ fmpz_mpoly_scalar_divides_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO CInt++-- Differentiation\/Integration ------------------------------------------------++-- | /fmpz_mpoly_derivative/ /A/ /B/ /var/ /ctx/ +-- +-- Set /A/ to the derivative of /B/ with respect to the variable of index+-- \(var\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_derivative"+ fmpz_mpoly_derivative :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_integral/ /A/ /scale/ /B/ /var/ /ctx/ +-- +-- Set /A/ and /scale/ so that /A/ is an integral of \(scale \times B\)+-- with respect to the variable of index /var/, where /scale/ is positive+-- and as small as possible.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_integral"+ fmpz_mpoly_integral :: Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- Evaluation ------------------------------------------------------------------+++++-- | /fmpz_mpoly_evaluate_all_fmpz/ /ev/ /A/ /vals/ /ctx/ +-- +-- Set /ev/ to the evaluation of /A/ where the variables are replaced by+-- the corresponding elements of the array /vals/. Return \(1\) for success+-- and \(0\) for failure.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_evaluate_all_fmpz"+ fmpz_mpoly_evaluate_all_fmpz :: Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr (Ptr CFmpz) -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_evaluate_one_fmpz/ /A/ /B/ /var/ /val/ /ctx/ +-- +-- Set /A/ to the evaluation of /B/ where the variable of index /var/ is+-- replaced by @val@. Return \(1\) for success and \(0\) for failure.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_evaluate_one_fmpz"+ fmpz_mpoly_evaluate_one_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_compose_fmpz_poly/ /A/ /B/ /C/ /ctxB/ +-- +-- Set /A/ to the evaluation of /B/ where the variables are replaced by the+-- corresponding elements of the array /C/. The context object of /B/ is+-- /ctxB/. Return \(1\) for success and \(0\) for failure.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_compose_fmpz_poly"+ fmpz_mpoly_compose_fmpz_poly :: Ptr CFmpzPoly -> Ptr CFmpzMPoly -> Ptr (Ptr CFmpzPoly) -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_compose_fmpz_mpoly_geobucket/ /A/ /B/ /C/ /ctxB/ /ctxAC/ +-- +-- Set /A/ to the evaluation of /B/ where the variables are replaced by the+-- corresponding elements of the array /C/. Both /A/ and the elements of+-- /C/ have context object /ctxAC/, while /B/ has context object /ctxB/.+-- The length of the array /C/ is the number of variables in /ctxB/.+-- Neither /A/ nor /B/ is allowed to alias any other polynomial. Return+-- \(1\) for success and \(0\) for failure. The main method attempts to+-- perform the calculation using matrices and chooses heuristically between+-- the @geobucket@ and @horner@ methods if needed.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_compose_fmpz_mpoly_geobucket"+ fmpz_mpoly_compose_fmpz_mpoly_geobucket :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr (Ptr CFmpzMPoly) -> Ptr CFmpzMPolyCtx -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_compose_fmpz_mpoly_gen/ /A/ /B/ /c/ /ctxB/ /ctxAC/ +-- +-- Set /A/ to the evaluation of /B/ where the variable of index /i/ in+-- /ctxB/ is replaced by the variable of index @c[i]@ in /ctxAC/. The+-- length of the array /C/ is the number of variables in /ctxB/. If any+-- @c[i]@ is negative, the corresponding variable of /B/ is replaced by+-- zero. Otherwise, it is expected that @c[i]@ is less than the number of+-- variables in /ctxAC/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_compose_fmpz_mpoly_gen"+ fmpz_mpoly_compose_fmpz_mpoly_gen :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CLong -> Ptr CFmpzMPolyCtx -> Ptr CFmpzMPolyCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /fmpz_mpoly_mul/ /A/ /B/ /C/ /ctx/ +-- +-- Set /A/ to \(B \times C\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_mul"+ fmpz_mpoly_mul :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_mul_johnson/ /A/ /B/ /C/ /ctx/ +-- +-- Set /A/ to \(B \times C\) using Johnson\'s heap-based method. The first+-- version always uses one thread.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_mul_johnson"+ fmpz_mpoly_mul_johnson :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_mul_array/ /A/ /B/ /C/ /ctx/ +-- +-- Try to set /A/ to \(B \times C\) using arrays. If the return is \(0\),+-- the operation was unsuccessful. Otherwise, it was successful and the+-- return is \(1\). The first version always uses one thread.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_mul_array"+ fmpz_mpoly_mul_array :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_mul_dense/ /A/ /B/ /C/ /ctx/ +-- +-- Try to set /A/ to \(B \times C\) using dense arithmetic. If the return+-- is \(0\), the operation was unsuccessful. Otherwise, it was successful+-- and the return is \(1\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_mul_dense"+ fmpz_mpoly_mul_dense :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- Powering --------------------------------------------------------------------+++++-- | /fmpz_mpoly_pow_fmpz/ /A/ /B/ /k/ /ctx/ +-- +-- Set /A/ to /B/ raised to the /k/-th power. Return \(1\) for success and+-- \(0\) for failure.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_pow_fmpz"+ fmpz_mpoly_pow_fmpz :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_pow_ui/ /A/ /B/ /k/ /ctx/ +-- +-- Set /A/ to /B/ raised to the /k/-th power. Return \(1\) for success and+-- \(0\) for failure.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_pow_ui"+ fmpz_mpoly_pow_ui :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> CULong -> Ptr CFmpzMPolyCtx -> IO CInt++-- Division --------------------------------------------------------------------++-- | /fmpz_mpoly_divides/ /Q/ /A/ /B/ /ctx/ +-- +-- If /A/ is divisible by /B/, set /Q/ to the exact quotient and return+-- \(1\). Otherwise, set \(Q\) to zero and return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_divides"+ fmpz_mpoly_divides :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_divrem/ /Q/ /R/ /A/ /B/ /ctx/ +-- +-- Set \(Q\) and \(R\) to the quotient and remainder of /A/ divided by /B/.+-- The monomials in /R/ divisible by the leading monomial of /B/ will have+-- coefficients reduced modulo the absolute value of the leading+-- coefficient of /B/. Note that this function is not very useful if the+-- leading coefficient /B/ is not a unit.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_divrem"+ fmpz_mpoly_divrem :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_quasidivrem/ /scale/ /Q/ /R/ /A/ /B/ /ctx/ +-- +-- Set /scale/, /Q/ and /R/ so that /Q/ and /R/ are the quotient and+-- remainder of \(scale \times A\) divided by /B/. No monomials in /R/ will+-- be divisible by the leading monomial of /B/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_quasidivrem"+ fmpz_mpoly_quasidivrem :: Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_div/ /Q/ /A/ /B/ /ctx/ +-- +-- Perform the operation of @fmpz_mpoly_divrem@ and discard /R/. Note that+-- this function is not very useful if the division is not exact and the+-- leading coefficient /B/ is not a unit.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_div"+ fmpz_mpoly_div :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_quasidiv/ /scale/ /Q/ /A/ /B/ /ctx/ +-- +-- Perform the operation of @fmpz_mpoly_quasidivrem@ and discard /R/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_quasidiv"+ fmpz_mpoly_quasidiv :: Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_divrem_ideal/ /Q/ /R/ /A/ /B/ /len/ /ctx/ +-- +-- This function is as per @fmpz_mpoly_divrem@ except that it takes an+-- array of divisor polynomials /B/ and it returns an array of quotient+-- polynomials /Q/. The number of divisor (and hence quotient) polynomials+-- is given by /len/. Note that this function is not very useful if there+-- is no unit among the leading coefficients in the array /B/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_divrem_ideal"+ fmpz_mpoly_divrem_ideal :: Ptr (Ptr CFmpzMPoly) -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr (Ptr CFmpzMPoly) -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_quasidivrem_ideal/ /scale/ /Q/ /R/ /A/ /B/ /len/ /ctx/ +-- +-- This function is as per @fmpz_mpoly_quasidivrem@ except that it takes an+-- array of divisor polynomials /B/ and it returns an array of quotient+-- polynomials /Q/. The number of divisor (and hence quotient) polynomials+-- is given by /len/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_quasidivrem_ideal"+ fmpz_mpoly_quasidivrem_ideal :: Ptr CFmpz -> Ptr (Ptr CFmpzMPoly) -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr (Ptr CFmpzMPoly) -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- Greatest Common Divisor -----------------------------------------------------++-- | /fmpz_mpoly_term_content/ /M/ /A/ /ctx/ +-- +-- Set /M/ to the GCD of the terms of /A/. If /A/ is zero, /M/ will be+-- zero. Otherwise, /M/ will be a monomial with positive coefficient.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_term_content"+ fmpz_mpoly_term_content :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_content_vars/ /g/ /A/ /vars/ /vars_length/ /ctx/ +-- +-- Set /g/ to the GCD of the coefficients of /A/ when viewed as a+-- polynomial in the variables /vars/. Return \(1\) for success and \(0\)+-- for failure. Upon success, /g/ will be independent of the variables+-- /vars/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_content_vars"+ fmpz_mpoly_content_vars :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CLong -> CLong -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_gcd/ /G/ /A/ /B/ /ctx/ +-- +-- Try to set /G/ to the GCD of /A/ and /B/ with positive leading+-- coefficient. The GCD of zero and zero is defined to be zero. If the+-- return is \(1\) the function was successful. Otherwise the return is+-- \(0\) and /G/ is left untouched.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_gcd"+ fmpz_mpoly_gcd :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_gcd_cofactors/ /G/ /Abar/ /Bbar/ /A/ /B/ /ctx/ +-- +-- Do the operation of @fmpz_mpoly_gcd@ and also compute \(Abar = A/G\) and+-- \(Bbar = B/G\) if successful.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_gcd_cofactors"+ fmpz_mpoly_gcd_cofactors :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_gcd_brown/ /G/ /A/ /B/ /ctx/ +-- +-- Try to set /G/ to the GCD of /A/ and /B/ using various algorithms.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_gcd_brown"+ fmpz_mpoly_gcd_brown :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_resultant/ /R/ /A/ /B/ /var/ /ctx/ +-- +-- Try to set /R/ to the resultant of /A/ and /B/ with respect to the+-- variable of index /var/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_resultant"+ fmpz_mpoly_resultant :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_discriminant/ /D/ /A/ /var/ /ctx/ +-- +-- Try to set /D/ to the discriminant of /A/ with respect to the variable+-- of index /var/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_discriminant"+ fmpz_mpoly_discriminant :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_primitive_part/ /res/ /f/ /ctx/ +-- +-- Sets /res/ to the primitive part of /f/, obtained by dividing out the+-- content of all coefficients and normalizing the leading coefficient to+-- be positive. The zero polynomial is unchanged.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_primitive_part"+ fmpz_mpoly_primitive_part :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- Square Root -----------------------------------------------------------------++-- | /fmpz_mpoly_sqrt_heap/ /Q/ /A/ /ctx/ /check/ +-- +-- If /A/ is a perfect square return \(1\) and set /Q/ to the square root+-- with positive leading coefficient. Otherwise return \(0\) and set /Q/ to+-- the zero polynomial. If \(check = 0\) the polynomial is assumed to be a+-- perfect square. This can be significantly faster, but it will not detect+-- non-squares with any reliability, and in the event of being passed a+-- non-square the result is meaningless.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_sqrt_heap"+ fmpz_mpoly_sqrt_heap :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> CInt -> IO CInt++-- | /fmpz_mpoly_sqrt/ /q/ /A/ /ctx/ +-- +-- If /A/ is a perfect square return \(1\) and set /Q/ to the square root+-- with positive leading coefficient. Otherwise return \(0\) and set /Q/ to+-- zero.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_sqrt"+ fmpz_mpoly_sqrt :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_is_square/ /A/ /ctx/ +-- +-- Return \(1\) if /A/ is a perfect square, otherwise return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_is_square"+ fmpz_mpoly_is_square :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- Univariate Functions --------------------------------------------------------++-- | /fmpz_mpoly_univar_init/ /A/ /ctx/ +-- +-- Initialize /A/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_univar_init"+ fmpz_mpoly_univar_init :: Ptr CFmpzMPolyUnivar -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_univar_clear/ /A/ /ctx/ +-- +-- Clear /A/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_univar_clear"+ fmpz_mpoly_univar_clear :: Ptr CFmpzMPolyUnivar -> Ptr CFmpzMPolyCtx -> IO ()++foreign import ccall "fmpz_mpoly.h &fmpz_mpoly_univar_clear"+ p_fmpz_mpoly_univar_clear :: FunPtr (Ptr CFmpzMPolyUnivar -> Ptr CFmpzMPolyCtx -> IO ())++-- | /fmpz_mpoly_univar_swap/ /A/ /B/ /ctx/ +-- +-- Swap /A/ and /B/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_univar_swap"+ fmpz_mpoly_univar_swap :: Ptr CFmpzMPolyUnivar -> Ptr CFmpzMPolyUnivar -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_to_univar/ /A/ /B/ /var/ /ctx/ +-- +-- Set /A/ to a univariate form of /B/ by pulling out the variable of index+-- /var/. The coefficients of /A/ will still belong to the content /ctx/+-- but will not depend on the variable of index /var/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_to_univar"+ fmpz_mpoly_to_univar :: Ptr CFmpzMPolyUnivar -> Ptr CFmpzMPoly -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_from_univar/ /A/ /B/ /var/ /ctx/ +-- +-- Set /A/ to the normal form of /B/ by putting in the variable of index+-- /var/. This function is undefined if the coefficients of /B/ depend on+-- the variable of index /var/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_from_univar"+ fmpz_mpoly_from_univar :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyUnivar -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_univar_degree_fits_si/ /A/ /ctx/ +-- +-- Return \(1\) if the degree of /A/ with respect to the main variable fits+-- an @slong@. Otherwise, return \(0\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_univar_degree_fits_si"+ fmpz_mpoly_univar_degree_fits_si :: Ptr CFmpzMPolyUnivar -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_univar_length/ /A/ /ctx/ +-- +-- Return the number of terms in /A/ with respect to the main variable.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_univar_length"+ fmpz_mpoly_univar_length :: Ptr CFmpzMPolyUnivar -> Ptr CFmpzMPolyCtx -> IO CLong++-- | /fmpz_mpoly_univar_get_term_exp_si/ /A/ /i/ /ctx/ +-- +-- Return the exponent of the term of index /i/ of /A/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_univar_get_term_exp_si"+ fmpz_mpoly_univar_get_term_exp_si :: Ptr CFmpzMPolyUnivar -> CLong -> Ptr CFmpzMPolyCtx -> IO CLong++-- | /fmpz_mpoly_univar_get_term_coeff/ /c/ /A/ /i/ /ctx/ +-- +-- Set (resp. swap) /c/ to (resp. with) the coefficient of the term of+-- index /i/ of /A/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_univar_get_term_coeff"+ fmpz_mpoly_univar_get_term_coeff :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyUnivar -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- Internal Functions ----------------------------------------------------------++-- | /fmpz_mpoly_inflate/ /A/ /B/ /shift/ /stride/ /ctx/ +-- +-- Apply the function @e -> shift[v] + stride[v]*e@ to each exponent @e@+-- corresponding to the variable @v@. It is assumed that each shift and+-- stride is not negative.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_inflate"+ fmpz_mpoly_inflate :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_deflate/ /A/ /B/ /shift/ /stride/ /ctx/ +-- +-- Apply the function @e -> (e - shift[v])\/stride[v]@ to each exponent @e@+-- corresponding to the variable @v@. If any @stride[v]@ is zero, the+-- corresponding numerator @e - shift[v]@ is assumed to be zero, and the+-- quotient is defined as zero. This allows the function to undo the+-- operation performed by @fmpz_mpoly_inflate@ when possible.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_deflate"+ fmpz_mpoly_deflate :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_deflation/ /shift/ /stride/ /A/ /ctx/ +-- +-- For each variable \(v\) let \(S_v\) be the set of exponents appearing on+-- \(v\). Set @shift[v]@ to \(\operatorname{min}(S_v)\) and set @stride[v]@+-- to \(\operatorname{gcd}(S-\operatorname{min}(S_v))\). If /A/ is zero,+-- all shifts and strides are set to zero.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_deflation"+ fmpz_mpoly_deflation :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_pow_fps/ /A/ /B/ /k/ /ctx/ +-- +-- Set /A/ to /B/ raised to the /k/-th power, using the Monagan and Pearce+-- FPS algorithm. It is assumed that /B/ is not zero and \(k \geq 2\).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_pow_fps"+ fmpz_mpoly_pow_fps :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> CULong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /_fmpz_mpoly_divides_array/ /poly1/ /exp1/ /alloc/ /poly2/ /exp2/ /len2/ /poly3/ /exp3/ /len3/ /mults/ /num/ /bits/ +-- +-- Use dense array exact division to set @(poly1, exp1, alloc)@ to+-- @(poly2, exp3, len2)@ divided by @(poly3, exp3, len3)@ in @num@+-- variables, given a list of multipliers to tightly pack exponents and a+-- number of bits for the fields of the exponents of the result. The array+-- \"mults\" is a list of bases to be used in encoding the array indices+-- from the exponents. The function reallocates its output, hence the+-- double indirection, and returns the length of its output if the quotient+-- is exact, or zero if not. It is assumed that @poly2@ is not zero. No+-- aliasing is allowed.+foreign import ccall "fmpz_mpoly.h _fmpz_mpoly_divides_array"+ _fmpz_mpoly_divides_array :: Ptr (Ptr CFmpz) -> Ptr (Ptr CULong) -> Ptr CLong -> Ptr CFmpz -> Ptr CULong -> CLong -> Ptr CFmpz -> Ptr CULong -> CLong -> Ptr CLong -> CLong -> CLong -> IO CLong++-- | /fmpz_mpoly_divides_array/ /poly1/ /poly2/ /poly3/ /ctx/ +-- +-- Set @poly1@ to @poly2@ divided by @poly3@, using a big dense array to+-- accumulate coefficients, and return 1 if the quotient is exact.+-- Otherwise, return 0 if the quotient is not exact. If the array will be+-- larger than some internally set parameter, the function fails silently+-- and returns \(-1\) so that some other method may be called. This+-- function is most efficient on dense inputs. Note that the function+-- @fmpz_mpoly_div_monagan_pearce@ below may be much faster if the quotient+-- is known to be exact.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_divides_array"+ fmpz_mpoly_divides_array :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /_fmpz_mpoly_divides_monagan_pearce/ /poly1/ /exp1/ /alloc/ /poly2/ /exp2/ /len2/ /poly3/ /exp3/ /len3/ /bits/ /N/ +-- +-- Set @(poly1, exp1, alloc)@ to @(poly2, exp3, len2)@ divided by+-- @(poly3, exp3, len3)@ and return 1 if the quotient is exact. Otherwise+-- return 0. The function assumes exponent vectors that each fit in \(N\)+-- words, and are packed into fields of the given number of bits. Assumes+-- input polys are nonzero. Implements \"Polynomial division using dynamic+-- arrays, heaps and packed exponents\" by Michael Monagan and Roman+-- Pearce. No aliasing is allowed.+foreign import ccall "fmpz_mpoly.h _fmpz_mpoly_divides_monagan_pearce"+ _fmpz_mpoly_divides_monagan_pearce :: Ptr (Ptr CFmpz) -> Ptr (Ptr CULong) -> Ptr CLong -> Ptr CFmpz -> Ptr CULong -> CLong -> Ptr CFmpz -> Ptr CULong -> CLong -> CLong -> CLong -> IO CLong++foreign import ccall "fmpz_mpoly.h fmpz_mpoly_divides_monagan_pearce"+ fmpz_mpoly_divides_monagan_pearce :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_divides_heap_threaded/ /Q/ /A/ /B/ /ctx/ /thread_limit/ +-- +-- Set @poly1@ to @poly2@ divided by @poly3@ and return 1 if the quotient+-- is exact. Otherwise return 0. The function uses the algorithm of Michael+-- Monagan and Roman Pearce. Note that the function+-- @fmpz_mpoly_div_monagan_pearce@ below may be much faster if the quotient+-- is known to be exact.+-- +-- The threaded version takes an upper limit on the number of threads to+-- use, while the first version always uses one thread.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_divides_heap_threaded"+ fmpz_mpoly_divides_heap_threaded :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> CLong -> IO CInt++-- | /_fmpz_mpoly_div_monagan_pearce/ /polyq/ /expq/ /allocq/ /poly2/ /exp2/ /len2/ /poly3/ /exp3/ /len3/ /bits/ /N/ +-- +-- Set @(polyq, expq, allocq)@ to the quotient of @(poly2, exp2, len2)@ by+-- @(poly3, exp3, len3)@ discarding remainder (with notional remainder+-- coefficients reduced modulo the leading coefficient of+-- @(poly3, exp3, len3)@), and return the length of the quotient. The+-- function reallocates its output, hence the double indirection. The+-- function assumes the exponent vectors all fit in \(N\) words. The+-- exponent vectors are assumed to have fields with the given number of+-- bits. Assumes input polynomials are nonzero. Implements \"Polynomial+-- division using dynamic arrays, heaps and packed exponents\" by Michael+-- Monagan and Roman Pearce. No aliasing is allowed.+foreign import ccall "fmpz_mpoly.h _fmpz_mpoly_div_monagan_pearce"+ _fmpz_mpoly_div_monagan_pearce :: Ptr (Ptr CFmpz) -> Ptr (Ptr CULong) -> Ptr CLong -> Ptr CFmpz -> Ptr CULong -> CLong -> Ptr CFmpz -> Ptr CULong -> CLong -> CLong -> CLong -> IO CLong++-- | /fmpz_mpoly_div_monagan_pearce/ /polyq/ /poly2/ /poly3/ /ctx/ +-- +-- Set @polyq@ to the quotient of @poly2@ by @poly3@, discarding the+-- remainder (with notional remainder coefficients reduced modulo the+-- leading coefficient of @poly3@). Implements \"Polynomial division using+-- dynamic arrays, heaps and packed exponents\" by Michael Monagan and+-- Roman Pearce. This function is exceptionally efficient if the division+-- is known to be exact.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_div_monagan_pearce"+ fmpz_mpoly_div_monagan_pearce :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /_fmpz_mpoly_divrem_monagan_pearce/ /lenr/ /polyq/ /expq/ /allocq/ /polyr/ /expr/ /allocr/ /poly2/ /exp2/ /len2/ /poly3/ /exp3/ /len3/ /bits/ /N/ +-- +-- Set @(polyq, expq, allocq)@ and @(polyr, expr, allocr)@ to the quotient+-- and remainder of @(poly2, exp2, len2)@ by @(poly3, exp3, len3)@ (with+-- remainder coefficients reduced modulo the leading coefficient of+-- @(poly3, exp3, len3)@), and return the length of the quotient. The+-- function reallocates its outputs, hence the double indirection. The+-- function assumes the exponent vectors all fit in \(N\) words. The+-- exponent vectors are assumed to have fields with the given number of+-- bits. Assumes input polynomials are nonzero. Implements \"Polynomial+-- division using dynamic arrays, heaps and packed exponents\" by Michael+-- Monagan and Roman Pearce. No aliasing is allowed.+foreign import ccall "fmpz_mpoly.h _fmpz_mpoly_divrem_monagan_pearce"+ _fmpz_mpoly_divrem_monagan_pearce :: Ptr CLong -> Ptr (Ptr CFmpz) -> Ptr (Ptr CULong) -> Ptr CLong -> Ptr (Ptr CFmpz) -> Ptr (Ptr CULong) -> Ptr CLong -> Ptr CFmpz -> Ptr CULong -> CLong -> Ptr CFmpz -> Ptr CULong -> CLong -> CLong -> CLong -> IO CLong++-- | /fmpz_mpoly_divrem_monagan_pearce/ /q/ /r/ /poly2/ /poly3/ /ctx/ +-- +-- Set @polyq@ and @polyr@ to the quotient and remainder of @poly2@ divided+-- by @poly3@ (with remainder coefficients reduced modulo the leading+-- coefficient of @poly3@). Implements \"Polynomial division using dynamic+-- arrays, heaps and packed exponents\" by Michael Monagan and Roman+-- Pearce.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_divrem_monagan_pearce"+ fmpz_mpoly_divrem_monagan_pearce :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /_fmpz_mpoly_divrem_array/ /lenr/ /polyq/ /expq/ /allocq/ /polyr/ /expr/ /allocr/ /poly2/ /exp2/ /len2/ /poly3/ /exp3/ /len3/ /mults/ /num/ /bits/ +-- +-- Use dense array division to set @(polyq, expq, allocq)@ and+-- @(polyr, expr, allocr)@ to the quotient and remainder of+-- @(poly2, exp2, len2)@ divided by @(poly3, exp3, len3)@ in @num@+-- variables, given a list of multipliers to tightly pack exponents and a+-- number of bits for the fields of the exponents of the result. The+-- function reallocates its outputs, hence the double indirection. The+-- array @mults@ is a list of bases to be used in encoding the array+-- indices from the exponents. The function returns the length of the+-- quotient. It is assumed that the input polynomials are not zero. No+-- aliasing is allowed.+foreign import ccall "fmpz_mpoly.h _fmpz_mpoly_divrem_array"+ _fmpz_mpoly_divrem_array :: Ptr CLong -> Ptr (Ptr CFmpz) -> Ptr (Ptr CULong) -> Ptr CLong -> Ptr (Ptr CFmpz) -> Ptr (Ptr CULong) -> Ptr CLong -> Ptr CFmpz -> Ptr CULong -> CLong -> Ptr CFmpz -> Ptr CULong -> CLong -> Ptr CLong -> CLong -> CLong -> IO CLong++-- | /fmpz_mpoly_divrem_array/ /q/ /r/ /poly2/ /poly3/ /ctx/ +-- +-- Set @polyq@ and @polyr@ to the quotient and remainder of @poly2@ divided+-- by @poly3@ (with remainder coefficients reduced modulo the leading+-- coefficient of @poly3@). The function is implemented using dense arrays,+-- and is efficient when the inputs are fairly dense. If the array will be+-- larger than some internally set parameter, the function silently returns+-- 0 so that another function can be called, otherwise it returns 1.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_divrem_array"+ fmpz_mpoly_divrem_array :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_quasidivrem_heap/ /scale/ /q/ /r/ /poly2/ /poly3/ /ctx/ +-- +-- Set @scale@, @q@ and @r@ so that @scale*poly2 = q*poly3 + r@ and no+-- monomial in @r@ is divisible by the leading monomial of @poly3@, where+-- @scale@ is positive and as small as possible. This function throws an+-- exception if @poly3@ is zero or if an exponent overflow occurs.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_quasidivrem_heap"+ fmpz_mpoly_quasidivrem_heap :: Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /_fmpz_mpoly_divrem_ideal_monagan_pearce/ /polyq/ /polyr/ /expr/ /allocr/ /poly2/ /exp2/ /len2/ /poly3/ /exp3/ /len/ /N/ /bits/ /ctx/ +-- +-- This function is as per @_fmpz_mpoly_divrem_monagan_pearce@ except that+-- it takes an array of divisor polynomials @poly3@ and an array of+-- repacked exponent arrays @exp3@, which may alias the exponent arrays of+-- @poly3@, and it returns an array of quotient polynomials @polyq@. The+-- number of divisor (and hence quotient) polynomials is given by @len@.+-- The function computes polynomials \(q_i\) such that+-- \(r = a - \sum_{i=0}^{\mbox{len - 1}} q_ib_i\), where the \(q_i\) are+-- the quotient polynomials and the \(b_i\) are the divisor polynomials.+foreign import ccall "fmpz_mpoly.h _fmpz_mpoly_divrem_ideal_monagan_pearce"+ _fmpz_mpoly_divrem_ideal_monagan_pearce :: Ptr (Ptr CFmpzMPoly) -> Ptr (Ptr CFmpz) -> Ptr (Ptr CULong) -> Ptr CLong -> Ptr CFmpz -> Ptr CULong -> CLong -> Ptr (Ptr CFmpzMPoly) -> Ptr (Ptr CULong) -> CLong -> CLong -> CLong -> Ptr CFmpzMPolyCtx -> IO CLong++-- | /fmpz_mpoly_divrem_ideal_monagan_pearce/ /q/ /r/ /poly2/ /poly3/ /len/ /ctx/ +-- +-- This function is as per @fmpz_mpoly_divrem_monagan_pearce@ except that+-- it takes an array of divisor polynomials @poly3@, and it returns an+-- array of quotient polynomials @q@. The number of divisor (and hence+-- quotient) polynomials is given by @len@. The function computes+-- polynomials \(q_i = q[i]\) such that @poly2@ is+-- \(r + \sum_{i=0}^{\mbox{len - 1}} q_ib_i\), where \(b_i =\) @poly3[i]@.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_divrem_ideal_monagan_pearce"+ fmpz_mpoly_divrem_ideal_monagan_pearce :: Ptr (Ptr CFmpzMPoly) -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr (Ptr CFmpzMPoly) -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- Vectors ---------------------------------------------------------------------++-- | /fmpz_mpoly_vec_init/ /vec/ /len/ /ctx/ +-- +-- Initializes /vec/ to a vector of length /len/, setting all entries to+-- the zero polynomial.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_init"+ fmpz_mpoly_vec_init :: Ptr CFmpzMPolyVec -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_vec_clear/ /vec/ /ctx/ +-- +-- Clears /vec/, freeing its allocated memory.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_clear"+ fmpz_mpoly_vec_clear :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_vec_print/ /vec/ /ctx/ +-- +-- Prints /vec/ to standard output.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_print"+ fmpz_mpoly_vec_print :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_vec_swap/ /x/ /y/ /ctx/ +-- +-- Swaps /x/ and /y/ efficiently.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_swap"+ fmpz_mpoly_vec_swap :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_vec_fit_length/ /vec/ /len/ /ctx/ +-- +-- Allocates room for /len/ entries in /vec/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_fit_length"+ fmpz_mpoly_vec_fit_length :: Ptr CFmpzMPolyVec -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_vec_set/ /dest/ /src/ /ctx/ +-- +-- Sets /dest/ to a copy of /src/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_set"+ fmpz_mpoly_vec_set :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_vec_append/ /vec/ /f/ /ctx/ +-- +-- Appends /f/ to the end of /vec/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_append"+ fmpz_mpoly_vec_append :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_vec_insert_unique/ /vec/ /f/ /ctx/ +-- +-- Inserts /f/ without duplication into /vec/ and returns its index. If+-- this polynomial already exists, /vec/ is unchanged. If this polynomial+-- does not exist in /vec/, it is appended.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_insert_unique"+ fmpz_mpoly_vec_insert_unique :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CLong++-- | /fmpz_mpoly_vec_set_length/ /vec/ /len/ /ctx/ +-- +-- Sets the length of /vec/ to /len/, truncating or zero-extending as+-- needed.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_set_length"+ fmpz_mpoly_vec_set_length :: Ptr CFmpzMPolyVec -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_vec_randtest_not_zero/ /vec/ /state/ /len/ /poly_len/ /bits/ /exp_bound/ /ctx/ +-- +-- Sets /vec/ to a random vector with exactly /len/ entries, all nonzero,+-- with random parameters defined by /poly_len/, /bits/ and /exp_bound/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_randtest_not_zero"+ fmpz_mpoly_vec_randtest_not_zero :: Ptr CFmpzMPolyVec -> Ptr CFRandState -> CLong -> CLong -> CLong -> CULong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_vec_set_primitive_unique/ /res/ /src/ /ctx/ +-- +-- Sets /res/ to a vector containing all polynomials in /src/ reduced to+-- their primitive parts, without duplication. The zero polynomial is+-- skipped if present. The output order is arbitrary.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_set_primitive_unique"+ fmpz_mpoly_vec_set_primitive_unique :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO ()++-- Ideals and Gröbner bases ----------------------------------------------------++-- The following methods deal with ideals in+-- \(\mathbb{Q}[X_1,\ldots,X_n]\). We use primitive integer polynomials as+-- normalised generators in place of monic rational polynomials.+--+-- | /fmpz_mpoly_spoly/ /res/ /f/ /g/ /ctx/ +-- +-- Sets /res/ to the /S/-polynomial of /f/ and /g/, scaled to an integer+-- polynomial by computing the LCM of the leading coefficients.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_spoly"+ fmpz_mpoly_spoly :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_reduction_primitive_part/ /res/ /f/ /vec/ /ctx/ +-- +-- Sets /res/ to the primitive part of the reduction (remainder of+-- multivariate quasidivision with remainder) with respect to the+-- polynomials /vec/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_reduction_primitive_part"+ fmpz_mpoly_reduction_primitive_part :: Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_vec_is_groebner/ /G/ /F/ /ctx/ +-- +-- If /F/ is /NULL/, checks if /G/ is a Gröbner basis. If /F/ is not+-- /NULL/, checks if /G/ is a Gröbner basis for /F/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_is_groebner"+ fmpz_mpoly_vec_is_groebner :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_vec_is_autoreduced/ /F/ /ctx/ +-- +-- Checks whether the vector /F/ is autoreduced (or inter-reduced).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_is_autoreduced"+ fmpz_mpoly_vec_is_autoreduced :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_vec_autoreduction/ /H/ /F/ /ctx/ +-- +-- Sets /H/ to the autoreduction (inter-reduction) of /F/.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_autoreduction"+ fmpz_mpoly_vec_autoreduction :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_vec_autoreduction_groebner/ /H/ /G/ /ctx/ +-- +-- Sets /H/ to the autoreduction (inter-reduction) of /G/. Assumes that /G/+-- is a Gröbner basis. This produces a reduced Gröbner basis, which is+-- unique (up to the sort order of the entries in the vector).+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_vec_autoreduction_groebner"+ fmpz_mpoly_vec_autoreduction_groebner :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO ()++-- -- | /fmpz_mpoly_select_pop_pair/ /pairs/ /G/ /ctx/ +-- -- +-- -- Given a vector /pairs/ of indices \((i, j)\) into /G/, selects one pair+-- -- for elimination in Buchberger\'s algorithm. The pair is removed from+-- -- /pairs/ and returned.+-- foreign import ccall "fmpz_mpoly.h fmpz_mpoly_select_pop_pair"+-- fmpz_mpoly_select_pop_pair :: Ptr CPairs -> Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO (Ptr CPair)++-- | /fmpz_mpoly_buchberger_naive/ /G/ /F/ /ctx/ +-- +-- Sets /G/ to a Gröbner basis for /F/, computed using a naive+-- implementation of Buchberger\'s algorithm.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_buchberger_naive"+ fmpz_mpoly_buchberger_naive :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_buchberger_naive_with_limits/ /G/ /F/ /ideal_len_limit/ /poly_len_limit/ /poly_bits_limit/ /ctx/ +-- +-- As @fmpz_mpoly_buchberger_naive@, but halts if during the execution of+-- Buchberger\'s algorithm the length of the ideal basis set exceeds+-- /ideal_len_limit/, the length of any polynomial exceeds+-- /poly_len_limit/, or the size of the coefficients of any polynomial+-- exceeds /poly_bits_limit/. Returns 1 for success and 0 for failure. On+-- failure, /G/ is a valid basis for /F/ but it might not be a Gröbner+-- basis.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_buchberger_naive_with_limits"+ fmpz_mpoly_buchberger_naive_with_limits :: Ptr CFmpzMPolyVec -> Ptr CFmpzMPolyVec -> CLong -> CLong -> CLong -> Ptr CFmpzMPolyCtx -> IO CInt++-- Special polynomials ---------------------------------------------------------++foreign import ccall "fmpz_mpoly.h fmpz_mpoly_symmetric_gens"+ fmpz_mpoly_symmetric_gens :: Ptr CFmpzMPoly -> CULong -> Ptr CLong -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_symmetric/ /res/ /k/ /ctx/ +-- +-- Sets /res/ to the elementary symmetric polynomial+-- \(e_k(X_1,\ldots,X_n)\).+-- +-- The /gens/ version takes \(X_1,\ldots,X_n\) to be the subset of+-- generators given by /vars/ and /n/. The indices in /vars/ start from+-- zero. Currently, the indices in /vars/ must be distinct.+foreign import ccall "fmpz_mpoly.h fmpz_mpoly_symmetric"+ fmpz_mpoly_symmetric :: Ptr CFmpzMPoly -> CULong -> Ptr CFmpzMPolyCtx -> IO ()+
+ src/Data/Number/Flint/Fmpz/MPoly/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.MPoly.Factor (+ module Data.Number.Flint.Fmpz.MPoly.Factor.FFI+ ) where++import Data.Number.Flint.Fmpz.MPoly.Factor.FFI
+ src/Data/Number/Flint/Fmpz/MPoly/Factor/FFI.hsc view
@@ -0,0 +1,160 @@+{-|+module : Data.Number.Flint.Fmpz.MPoly.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.MPoly.Factor.FFI (+ -- * Factorisation of multivariate polynomials over the integers+ -- * Types+ FmpzMPolyFactor (..)+ , CFmpzMPolyFactor (..)+ , newFmpzMPolyFactor+ , withFmpzMPolyFactor+ -- * Memory management+ , fmpz_mpoly_factor_init+ , fmpz_mpoly_factor_clear+ -- * Basic manipulation+ , fmpz_mpoly_factor_swap+ , fmpz_mpoly_factor_length+ , fmpz_mpoly_factor_get_constant_fmpz+ , fmpz_mpoly_factor_get_base+ , fmpz_mpoly_factor_get_exp_si+ , fmpz_mpoly_factor_sort+ -- * Factorisation+ , fmpz_mpoly_factor_squarefree+ , fmpz_mpoly_factor+) where++-- Factorisation of multivariate polynomials over the integers -----------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.MPoly+import Data.Number.Flint.Fmpq+import Data.Number.Flint.MPoly++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpq.h>+#include <flint/fmpz_mpoly.h>+#include <flint/fmpz_mpoly_factor.h>++-- Types -----------------------------------------------------------------------++data FmpzMPolyFactor =+ FmpzMPolyFactor {-# UNPACK #-} !(ForeignPtr CFmpzMPolyFactor)+data CFmpzMPolyFactor =+ CFmpzMPolyFactor (Ptr CFmpz) (Ptr CFmpz) (Ptr CFmpzMPoly)+ (Ptr CFmpz) CLong CLong++instance Storable CFmpzMPolyFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mpoly_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mpoly_factor_t}+ peek ptr = CFmpzMPolyFactor+ <$> #{peek fmpz_mpoly_factor_struct, constant } ptr+ <*> #{peek fmpz_mpoly_factor_struct, constant_den} ptr+ <*> #{peek fmpz_mpoly_factor_struct, poly } ptr+ <*> #{peek fmpz_mpoly_factor_struct, exp } ptr+ <*> #{peek fmpz_mpoly_factor_struct, num } ptr+ <*> #{peek fmpz_mpoly_factor_struct, alloc } ptr+ poke = error "CFmpzMPolyFactor.poke: Not defined"++newFmpzMPolyFactor ctx@(FmpzMPolyCtx pctx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpzMPolyCtx ctx $ \ctx -> do+ fmpz_mpoly_factor_init x ctx+ addForeignPtrFinalizerEnv p_fmpz_mpoly_factor_clear x pctx+ return $ FmpzMPolyFactor x++withFmpzMPolyFactor (FmpzMPolyFactor p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpzMPolyFactor p,)+ +-- Memory management -----------------------------------------------------------++-- | /fmpz_mpoly_factor_init/ /f/ /ctx/ +-- +-- Initialise /f/.+foreign import ccall "fmpz_mpoly_factor.h fmpz_mpoly_factor_init"+ fmpz_mpoly_factor_init :: Ptr CFmpzMPolyFactor -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_factor_clear/ /f/ /ctx/ +-- +-- Clear /f/.+foreign import ccall "fmpz_mpoly_factor.h fmpz_mpoly_factor_clear"+ fmpz_mpoly_factor_clear :: Ptr CFmpzMPolyFactor -> Ptr CFmpzMPolyCtx -> IO ()++foreign import ccall "fmpz_mpoly_factor.h &fmpz_mpoly_factor_clear"+ p_fmpz_mpoly_factor_clear :: FunPtr (Ptr CFmpzMPolyFactor -> Ptr CFmpzMPolyCtx -> IO ())++-- Basic manipulation ----------------------------------------------------------++-- | /fmpz_mpoly_factor_swap/ /f/ /g/ /ctx/ +-- +-- Efficiently swap /f/ and /g/.+foreign import ccall "fmpz_mpoly_factor.h fmpz_mpoly_factor_swap"+ fmpz_mpoly_factor_swap :: Ptr CFmpzMPolyFactor -> Ptr CFmpzMPolyFactor -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_factor_length/ /f/ /ctx/ +-- +-- Return the length of the product in /f/.+foreign import ccall "fmpz_mpoly_factor.h fmpz_mpoly_factor_length"+ fmpz_mpoly_factor_length :: Ptr CFmpzMPolyFactor -> Ptr CFmpzMPolyCtx -> IO CLong++-- | /fmpz_mpoly_factor_get_constant_fmpz/ /c/ /f/ /ctx/ +-- +-- Set \(c\) to the constant of /f/.+foreign import ccall "fmpz_mpoly_factor.h fmpz_mpoly_factor_get_constant_fmpz"+ fmpz_mpoly_factor_get_constant_fmpz :: Ptr CFmpz -> Ptr CFmpzMPolyFactor -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_factor_get_base/ /B/ /f/ /i/ /ctx/ +-- +-- Set (resp. swap) /B/ to (resp. with) the base of the term of index \(i\)+-- in /A/.+foreign import ccall "fmpz_mpoly_factor.h fmpz_mpoly_factor_get_base"+ fmpz_mpoly_factor_get_base :: Ptr CFmpzMPoly -> Ptr CFmpzMPolyFactor -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_factor_get_exp_si/ /f/ /i/ /ctx/ +-- +-- Return the exponent of the term of index \(i\) in /A/. It is assumed to+-- fit an @slong@.+foreign import ccall "fmpz_mpoly_factor.h fmpz_mpoly_factor_get_exp_si"+ fmpz_mpoly_factor_get_exp_si :: Ptr CFmpzMPolyFactor -> CLong -> Ptr CFmpzMPolyCtx -> IO CLong++-- | /fmpz_mpoly_factor_sort/ /f/ /ctx/+-- +-- Sort the product of /f/ first by exponent and then by base.+foreign import ccall "fmpz_mpoly_factor.h fmpz_mpoly_factor_sort"+ fmpz_mpoly_factor_sort :: Ptr CFmpzMPolyFactor -> Ptr CFmpzMPolyCtx -> IO ()++-- Factorisation ---------------------------------------------------------------++-- | /fmpz_mpoly_factor_squarefree/ /f/ /A/ /ctx/ +-- +-- Set /f/ to a factorization of /A/ where the bases are primitive and+-- pairwise relatively prime. If the product of all irreducible factors+-- with a given exponent is desired, it is recommended to call+-- @fmpz_mpoly_factor_sort@ and then multiply the bases with the desired+-- exponent.+foreign import ccall "fmpz_mpoly_factor.h fmpz_mpoly_factor_squarefree"+ fmpz_mpoly_factor_squarefree :: Ptr CFmpzMPolyFactor -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_factor/ /f/ /A/ /ctx/ +-- +-- Set /f/ to a factorization of /A/ where the bases are irreducible.+foreign import ccall "fmpz_mpoly_factor.h fmpz_mpoly_factor"+ fmpz_mpoly_factor :: Ptr CFmpzMPolyFactor -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO CInt+
+ src/Data/Number/Flint/Fmpz/MPoly/Q.hs view
@@ -0,0 +1,23 @@+{-|+module : Data.Number.Flint.Fmpz.MPoly.Q+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+++An @FmpzMPolyQ@ represents an element of :math:`\mathbb{Q}(x_1,ldots,x_n)`+for fixed /n/ as a pair of Flint multivariate polynomials+(@FmpzMPolyQ@). Instances are always kept in canonical form by+ensuring that the GCD of numerator and denominator is 1 and that the+coefficient of the leading term of the denominator is positive.++The user must create a multivariate polynomial context+(@FmpzMPolyCtx@) specifying the number of variables /n/ and the+monomial ordering.++-}+module Data.Number.Flint.Fmpz.MPoly.Q (+ module Data.Number.Flint.Fmpz.MPoly.Q.FFI+ ) where++import Data.Number.Flint.Fmpz.MPoly.Q.FFI
+ src/Data/Number/Flint/Fmpz/MPoly/Q/FFI.hsc view
@@ -0,0 +1,306 @@+{-|+module : Data.Number.Flint.Fmpz.MPoly.Q.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.MPoly.Q.FFI (+ -- * Multivariate rational functions over Q+ -- * Types+ FmpzMPolyQ (..)+ , CFmpzMPolyQ (..)+ , newFmpzMPolyQ+ , withFmpzMPolyQ+ , withFmpzMPolyQNumerator+ , withFmpzMPolyQDenominator+ -- * Memory management+ , fmpz_mpoly_q_init+ , fmpz_mpoly_q_clear+ -- * Assignment+ , fmpz_mpoly_q_swap+ , fmpz_mpoly_q_set+ -- * Canonicalisation+ , fmpz_mpoly_q_canonicalise+ , fmpz_mpoly_q_is_canonical+ -- * Properties+ , fmpz_mpoly_q_is_zero+ , fmpz_mpoly_q_is_one+ , fmpz_mpoly_q_used_vars+ -- * Special values+ , fmpz_mpoly_q_zero+ , fmpz_mpoly_q_one+ , fmpz_mpoly_q_gen+ -- * Input and output+ , fmpz_mpoly_q_get_str_pretty+ , fmpz_mpoly_q_fprint_pretty+ , fmpz_mpoly_q_print_pretty+ -- * Random generation+ , fmpz_mpoly_q_randtest+ -- * Comparisons+ , fmpz_mpoly_q_equal+ -- * Arithmetic+ , fmpz_mpoly_q_neg+ , fmpz_mpoly_q_add+ , fmpz_mpoly_q_sub+ , fmpz_mpoly_q_mul+ , fmpz_mpoly_q_div+ , fmpz_mpoly_q_inv+ -- * Content+ , _fmpz_mpoly_q_content+) where ++-- Multivariate rational functions over Q --------------------------------------++import System.IO.Unsafe++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, nullPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array (advancePtr)++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.MPoly++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_poly.h>+#include <flint/fmpz_mpoly_q.h>++-- Types -----------------------------------------------------------------------++data FmpzMPolyQ = FmpzMPolyQ {-# UNPACK #-} !(ForeignPtr CFmpzMPolyQ)+data CFmpzMPolyQ = CFmpzMPolyQ CFmpzMPoly CFmpzMPoly++instance Storable CFmpzMPolyQ where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mpoly_q_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mpoly_q_t}+ peek ptr = CFmpzMPolyQ+ <$> #{peek fmpz_mpoly_q_struct, num} ptr+ <*> #{peek fmpz_mpoly_q_struct, den} ptr+ poke ptr (CFmpzMPolyQ num den) = do+ #{poke fmpz_mpoly_q_struct, num} ptr num+ #{poke fmpz_mpoly_q_struct, den} ptr den++-- | Create a new `FmpzMPolyQ`+newFmpzMPolyQ ctx@(FmpzMPolyCtx pctx) = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withFmpzMPolyCtx ctx $ \ctx -> do + fmpz_mpoly_q_init p ctx+ addForeignPtrFinalizerEnv p_fmpz_mpoly_q_clear p pctx + return $ FmpzMPolyQ p++-- | Use a new `FmpzMPolyQ`+{-# INLINE withFmpzMPolyQ #-}+withFmpzMPolyQ (FmpzMPolyQ p) f = do+ withForeignPtr p $ \fp -> (FmpzMPolyQ p,) <$> f fp++-- | Use the numerator of `FmpzMPolyQ`+withFmpzMPolyQNumerator ::+ FmpzMPolyQ -> (Ptr CFmpzMPoly -> IO t) -> IO (FmpzMPolyQ, t)+withFmpzMPolyQNumerator (FmpzMPolyQ p) f = do+ withForeignPtr p $ \fp -> (FmpzMPolyQ p,) <$> f (castPtr fp)++-- | Use the denominator of `FmpzMPolyQ`+withFmpzMPolyQDenominator ::+ FmpzMPolyQ -> (Ptr CFmpzMPoly -> IO t) -> IO (FmpzMPolyQ, t)+withFmpzMPolyQDenominator (FmpzMPolyQ p) f = do+ withForeignPtr p $ \fp -> (FmpzMPolyQ p,) <$> f (castPtr fp `advancePtr` 1)++-- Memory management -----------------------------------------------------------++-- | /fmpz_mpoly_q_init/ /res/ /ctx/ +-- +-- Initializes /res/ for use, and sets its value to zero.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_init"+ fmpz_mpoly_q_init :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_q_clear/ /res/ /ctx/ +-- +-- Clears /res/, freeing or recycling its allocated memory.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_clear"+ fmpz_mpoly_q_clear :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++foreign import ccall "fmpz_mpoly_q.h &fmpz_mpoly_q_clear"+ p_fmpz_mpoly_q_clear :: FunPtr (Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ())++-- Assignment ------------------------------------------------------------------++-- | /fmpz_mpoly_q_swap/ /x/ /y/ /ctx/ +-- +-- Swaps the values of /x/ and /y/ efficiently.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_swap"+ fmpz_mpoly_q_swap :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_q_set/ /res/ /x/ /ctx/ +-- +-- Sets /res/ to the value /x/.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_set"+ fmpz_mpoly_q_set :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- Canonicalisation ------------------------------------------------------------++-- | /fmpz_mpoly_q_canonicalise/ /x/ /ctx/ +-- +-- Puts the numerator and denominator of /x/ in canonical form by removing+-- common content and making the leading term of the denominator positive.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_canonicalise"+ fmpz_mpoly_q_canonicalise :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_q_is_canonical/ /x/ /ctx/ +-- +-- Returns whether /x/ is in canonical form.+-- +-- In addition to verifying that the numerator and denominator have no+-- common content and that the leading term of the denominator is positive,+-- this function checks that the denominator is nonzero and that the+-- numerator and denominator have correctly sorted terms (these properties+-- should normally hold; verifying them provides an extra consistency check+-- for test code).+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_is_canonical"+ fmpz_mpoly_q_is_canonical :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO CInt++-- Properties ------------------------------------------------------------------++-- | /fmpz_mpoly_q_is_zero/ /x/ /ctx/ +-- +-- Returns whether /x/ is the constant 0.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_is_zero"+ fmpz_mpoly_q_is_zero :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_q_is_one/ /x/ /ctx/ +-- +-- Returns whether /x/ is the constant 1.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_is_one"+ fmpz_mpoly_q_is_one :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO CInt++-- | /fmpz_mpoly_q_used_vars/ /used/ /f/ /ctx/ +-- +-- For each variable, sets the corresponding entry in /used/ to the boolean+-- flag indicating whether that variable appears in the rational function+-- (respectively its numerator or denominator).+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_used_vars"+ fmpz_mpoly_q_used_vars :: Ptr CInt -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- Special values --------------------------------------------------------------++-- | /fmpz_mpoly_q_zero/ /res/ /ctx/ +-- +-- Sets /res/ to the constant 0.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_zero"+ fmpz_mpoly_q_zero :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_q_one/ /res/ /ctx/ +-- +-- Sets /res/ to the constant 1.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_one"+ fmpz_mpoly_q_one :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_q_gen/ /res/ /i/ /ctx/ +-- +-- Sets /res/ to the generator \(x_{i+1}\). Requires \(0 \le i < n\) where+-- /n/ is the number of variables of /ctx/.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_gen"+ fmpz_mpoly_q_gen :: Ptr CFmpzMPolyQ -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- Input and output ------------------------------------------------------------++-- | /fmpz_mpoly_q_get_str_pretty/ /f/ /x/ /ctx/ +-- +-- Returns string representation of /f/. If /x/ is not /NULL/, the strings in+-- /x/ are used as the symbols for the variables.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_get_str_pretty"+ fmpz_mpoly_q_get_str_pretty :: Ptr CFmpzMPolyQ -> Ptr (Ptr CChar) -> Ptr CFmpzMPolyCtx -> IO CString+ +-- | /fmpz_mpoly_q_print_pretty/ /f/ /x/ /ctx/ +-- +-- Prints /f/ to standard output. If /x/ is not /NULL/, the strings in+-- /x/ are used as the symbols for the variables.+fmpz_mpoly_q_print_pretty :: Ptr CFmpzMPolyQ -> Ptr (Ptr CChar) -> Ptr CFmpzMPolyCtx -> IO CInt+fmpz_mpoly_q_print_pretty x vars ctx = do+ printCStr (\x -> fmpz_mpoly_q_get_str_pretty x vars ctx) x++-- | /fmpz_mpoly_q_fprint_pretty/ /out/ /f/ /x/ /ctx/ +-- +-- Prints /f/ to file /out/. If /x/ is not /NULL/, the strings in+-- /x/ are used as the symbols for the variables.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_fprint_pretty"+ fmpz_mpoly_q_fprint_pretty :: Ptr CFile -> Ptr CFmpzMPolyQ -> Ptr (Ptr CChar) -> Ptr CFmpzMPolyCtx -> IO CInt++-- Random generation -----------------------------------------------------------++-- | /fmpz_mpoly_q_randtest/ /res/ /state/ /length/ /coeff_bits/ /exp_bound/ /ctx/ +-- +-- Sets /res/ to a random rational function where both numerator and+-- denominator have up to /length/ terms, coefficients up to size+-- /coeff_bits/, and exponents strictly smaller than /exp_bound/.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_randtest"+ fmpz_mpoly_q_randtest :: Ptr CFmpzMPolyQ -> Ptr CFRandState -> CLong -> CMpLimb -> CLong -> Ptr CFmpzMPolyCtx -> IO ()++-- Comparisons -----------------------------------------------------------------++-- | /fmpz_mpoly_q_equal/ /x/ /y/ /ctx/ +-- +-- Returns whether /x/ and /y/ are equal.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_equal"+ fmpz_mpoly_q_equal :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO CInt++-- Arithmetic ------------------------------------------------------------------++-- | /fmpz_mpoly_q_neg/ /res/ /x/ /ctx/ +-- +-- Sets /res/ to the negation of /x/.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_neg"+ fmpz_mpoly_q_neg :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_q_add/ /res/ /x/ /y/ /ctx/ +-- +-- Sets /res/ to the sum of /x/ and /y/.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_add"+ fmpz_mpoly_q_add :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_q_sub/ /res/ /x/ /y/ /ctx/ +-- +-- Sets /res/ to the difference of /x/ and /y/.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_sub"+ fmpz_mpoly_q_sub :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_q_mul/ /res/ /x/ /y/ /ctx/ +-- +-- Sets /res/ to the product of /x/ and /y/.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_mul"+ fmpz_mpoly_q_mul :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_q_div/ /res/ /x/ /y/ /ctx/ +-- +-- Sets /res/ to the quotient of /x/ and /y/. Division by zero calls+-- /flint_abort/.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_div"+ fmpz_mpoly_q_div :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- | /fmpz_mpoly_q_inv/ /res/ /x/ /ctx/ +-- +-- Sets /res/ to the inverse of /x/. Division by zero calls /flint_abort/.+foreign import ccall "fmpz_mpoly_q.h fmpz_mpoly_q_inv"+ fmpz_mpoly_q_inv :: Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyQ -> Ptr CFmpzMPolyCtx -> IO ()++-- Content ---------------------------------------------------------------------++-- | /_fmpz_mpoly_q_content/ /num/ /den/ /xnum/ /xden/ /ctx/ +-- +-- Sets /res/ to the content of the coefficients of /x/.+foreign import ccall "fmpz_mpoly_q.h _fmpz_mpoly_q_content"+ _fmpz_mpoly_q_content :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzMPoly -> Ptr CFmpzMPoly -> Ptr CFmpzMPolyCtx -> IO ()++++
+ src/Data/Number/Flint/Fmpz/Mat.hs view
@@ -0,0 +1,34 @@+{- | +module : Data.Number.Flint.Fmpz.Mat+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de++An @FmpzMat@ represents an matrix over integer.+This module implements operations on matrices over integers.++== Basic usage ++Create a 3x3 matrix over integers, set it to the unit matrix and print it.++@+import Data.Number.Flint++main = do+ withNewFmpzMat 3 2 $ \\a -> do+ fmpz_mat_one a+ fmpz_mat_print a+ putStr "\\n"+@++Running main yields:++>>> main +3 3 1 0 0 0 1 0 0 0 1+-}++module Data.Number.Flint.Fmpz.Mat (+ module Data.Number.Flint.Fmpz.Mat.FFI,+) where++import Data.Number.Flint.Fmpz.Mat.FFI
+ src/Data/Number/Flint/Fmpz/Mat/FFI.hsc view
@@ -0,0 +1,1833 @@+{-|+module : Data.Number.Flint.Fmpz.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Mat.FFI (+ -- * Matrices over the integers+ FmpzMat (..)+ , CFmpzMat (..)+ -- * Constructor+ , newFmpzMat+ , withFmpzMat+ , withNewFmpzMat+ -- * Memory management+ , fmpz_mat_init+ , fmpz_mat_clear+ -- * Basic assignment and manipulation+ , fmpz_mat_set+ , fmpz_mat_init_set+ , fmpz_mat_swap+ , fmpz_mat_swap_entrywise+ , fmpz_mat_entry+ , fmpz_mat_set_entry+ , fmpz_mat_get_entry+ , fmpz_mat_zero+ , fmpz_mat_one+ , fmpz_mat_swap_rows+ , fmpz_mat_swap_cols+ , fmpz_mat_invert_rows+ , fmpz_mat_invert_cols+ -- * Window+ , fmpz_mat_window_init+ , fmpz_mat_window_clear+ -- * Random matrix generation+ , fmpz_mat_randbits+ , fmpz_mat_randtest+ , fmpz_mat_randintrel+ , fmpz_mat_randsimdioph+ , fmpz_mat_randntrulike+ , fmpz_mat_randntrulike2+ , fmpz_mat_randajtai+ , fmpz_mat_randpermdiag+ , fmpz_mat_randrank+ , fmpz_mat_randdet+ , fmpz_mat_randops+ -- * Input and output+ , fmpz_mat_get_str+ , fmpz_mat_get_str_pretty+ , fmpz_mat_fprint+ , fmpz_mat_fprint_pretty+ , fmpz_mat_print+ , fmpz_mat_print_pretty+ , fmpz_mat_fread+ , fmpz_mat_read+ -- * Comparison+ , fmpz_mat_equal+ , fmpz_mat_is_zero+ , fmpz_mat_is_one+ , fmpz_mat_is_empty+ , fmpz_mat_is_square+ , fmpz_mat_is_zero_row+ -- , fmpz_mat_col_equal -- deprecated+ -- , fmpz_mat_row_equal -- deprecated+ -- * Transpose+ , fmpz_mat_transpose+ -- * Concatenate+ , fmpz_mat_concat_vertical+ , fmpz_mat_concat_horizontal+ -- * Modular reduction and reconstruction+ , fmpz_mat_get_nmod_mat+ , fmpz_mat_set_nmod_mat+ , fmpz_mat_set_nmod_mat_unsigned+ , fmpz_mat_CRT_ui+ , fmpz_mat_multi_mod_ui_precomp+ , fmpz_mat_multi_mod_ui+ , fmpz_mat_multi_CRT_ui_precomp+ , fmpz_mat_multi_CRT_ui+ -- * Addition and subtraction+ , fmpz_mat_add+ , fmpz_mat_sub+ , fmpz_mat_neg+ -- * Matrix-scalar arithmetic+ , fmpz_mat_scalar_mul_si+ , fmpz_mat_scalar_addmul_si+ , fmpz_mat_scalar_submul_si+ , fmpz_mat_scalar_addmul_nmod_mat_ui+ , fmpz_mat_scalar_divexact_si+ , fmpz_mat_scalar_mul_2exp+ , fmpz_mat_scalar_tdiv_q_2exp+ , fmpz_mat_scalar_smod+ -- * Matrix multiplication+ , fmpz_mat_mul+ , fmpz_mat_mul_classical+ , fmpz_mat_mul_strassen+ , _fmpz_mat_mul_multi_mod+ , fmpz_mat_mul_blas+ , fmpz_mat_mul_fft+ , fmpz_mat_sqr+ , fmpz_mat_sqr_bodrato+ , fmpz_mat_pow+ , _fmpz_mat_mul_small+ , _fmpz_mat_mul_double_word+ , fmpz_mat_mul_fmpz_vec+ , fmpz_mat_fmpz_vec_mul+ -- * Inverse+ , fmpz_mat_inv+ -- * Kronecker product+ , fmpz_mat_kronecker_product+ -- * Content+ , fmpz_mat_content+ -- * Trace+ , fmpz_mat_trace+ -- * Determinant+ , fmpz_mat_det+ , fmpz_mat_det_cofactor+ , fmpz_mat_det_bareiss+ , fmpz_mat_det_modular+ , fmpz_mat_det_modular_accelerated+ , fmpz_mat_det_modular_given_divisor+ , fmpz_mat_det_bound+ , fmpz_mat_det_bound_nonzero+ , fmpz_mat_det_divisor+ -- * Transforms+ , fmpz_mat_similarity+ -- * Characteristic polynomial+ , _fmpz_mat_charpoly_berkowitz+ , fmpz_mat_charpoly_berkowitz+ , _fmpz_mat_charpoly_modular+ , fmpz_mat_charpoly_modular+ , _fmpz_mat_charpoly+ , fmpz_mat_charpoly+ -- * Minimal polynomial+ , _fmpz_mat_minpoly_modular+ , fmpz_mat_minpoly_modular+ , _fmpz_mat_minpoly+ , fmpz_mat_minpoly+ -- * Rank+ , fmpz_mat_rank+ -- * Column partitioning+ , fmpz_mat_col_partition+ -- * Nonsingular solving+ , fmpz_mat_solve+ , fmpz_mat_solve_fflu+ , fmpz_mat_solve_fflu_precomp+ , fmpz_mat_solve_cramer+ , fmpz_mat_solve_bound+ , fmpz_mat_solve_dixon+ -- , _fmpz_mat_solve_dixon_den ??? Not present in static library+ , fmpz_mat_solve_dixon_den+ , fmpz_mat_solve_multi_mod_den+ , fmpz_mat_can_solve_multi_mod_den+ , fmpz_mat_can_solve_fflu+ , fmpz_mat_can_solve+ -- * Row reduction+ , fmpz_mat_find_pivot_any+ , fmpz_mat_fflu+ , fmpz_mat_rref+ , fmpz_mat_rref_fflu+ , fmpz_mat_rref_mul+ , fmpz_mat_is_in_rref_with_rank+ -- * Modular gaussian elimination+ , fmpz_mat_rref_mod+ -- * Strong echelon form and Howell form+ , fmpz_mat_strong_echelon_form_mod+ , fmpz_mat_howell_form_mod+ -- * Nullspace+ , fmpz_mat_nullspace+ -- -- * Echelon form+ -- , fmpz_mat_rref_fraction_free ??? Not present in static library+ -- * Hermite normal form+ , fmpz_mat_hnf+ , fmpz_mat_hnf_transform+ , fmpz_mat_hnf_classical+ , fmpz_mat_hnf_xgcd+ , fmpz_mat_hnf_modular+ , fmpz_mat_hnf_modular_eldiv+ , fmpz_mat_hnf_minors+ , fmpz_mat_hnf_pernet_stein+ , fmpz_mat_is_in_hnf+ -- * Smith normal form+ , fmpz_mat_snf+ , fmpz_mat_snf_diagonal+ , fmpz_mat_snf_kannan_bachem+ , fmpz_mat_snf_iliopoulos+ , fmpz_mat_is_in_snf+ -- * Special matrices+ , fmpz_mat_gram+ , fmpz_mat_is_hadamard+ , fmpz_mat_hadamard+ -- * Conversions+ , fmpz_mat_get_d_mat+ , fmpz_mat_get_d_mat_transpose+ -- , fmpz_mat_get_mpf_mat -- deprecated+ -- * Cholesky Decomposition+ , fmpz_mat_chol_d+ -- * LLL+ , fmpz_mat_is_reduced+ , fmpz_mat_is_reduced_with_removal+ -- * Classical LLL+ , fmpz_mat_lll_original+ -- * Modified LLL+ , fmpz_mat_lll_storjohann+) where++-- Matrices over the integers --------------------------------------------------++import System.IO.Unsafe++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpq+import Data.Number.Flint.NMod.Types+import Data.Number.Flint.Support.D.Mat+import Data.Number.Flint.Support.Mpf.Mat++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_mat.h>+#include <flint/fmpz_poly.h>+#include <flint/fmpq.h>++-- fmpz_mat_t ------------------------------------------------------------------++data FmpzMat = FmpzMat {-# UNPACK #-} !(ForeignPtr CFmpzMat) +data CFmpzMat = CFmpzMat (Ptr CFmpz) CLong CLong (Ptr (Ptr CFmpz)) ++instance Storable CFmpzMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mat_t}+ peek ptr = CFmpzMat+ <$> #{peek fmpz_mat_struct, entries} ptr+ <*> #{peek fmpz_mat_struct, r } ptr+ <*> #{peek fmpz_mat_struct, c } ptr+ <*> #{peek fmpz_mat_struct, rows } ptr+ poke = error "CFmpzMat.poke: Not defined."+ +newFmpzMat rows cols = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> fmpz_mat_init x rows cols+ addForeignPtrFinalizer p_fmpz_mat_clear x+ return $ FmpzMat x++{-# INLINE withFmpzMat #-}+withFmpzMat (FmpzMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FmpzMat x,)++{-# INLINE withNewFmpzMat #-}+withNewFmpzMat rows cols f = do+ x <- newFmpzMat rows cols+ withFmpzMat x f+ +-- Memory management -----------------------------------------------------------++-- | /fmpz_mat_init/ /mat/ /rows/ /cols/ +-- +-- Initialises a matrix with the given number of rows and columns for use.+foreign import ccall "fmpz_mat.h fmpz_mat_init"+ fmpz_mat_init :: Ptr CFmpzMat -> CLong -> CLong -> IO ()++-- | /fmpz_mat_clear/ /mat/ +-- +-- Clears the given matrix.+foreign import ccall "fmpz_mat.h fmpz_mat_clear"+ fmpz_mat_clear :: Ptr CFmpzMat -> IO ()++foreign import ccall "fmpz_mat.h &fmpz_mat_clear"+ p_fmpz_mat_clear :: FunPtr (Ptr CFmpzMat -> IO ())++-- Basic assignment and manipulation -------------------------------------------++-- | /fmpz_mat_set/ /mat1/ /mat2/ +-- +-- Sets @mat1@ to a copy of @mat2@. The dimensions of @mat1@ and @mat2@+-- must be the same.+foreign import ccall "fmpz_mat.h fmpz_mat_set"+ fmpz_mat_set :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_init_set/ /mat/ /src/ +-- +-- Initialises the matrix @mat@ to the same size as @src@ and sets it to a+-- copy of @src@.+foreign import ccall "fmpz_mat.h fmpz_mat_init_set"+ fmpz_mat_init_set :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_swap/ /mat1/ /mat2/ +-- +-- Swaps two matrices. The dimensions of @mat1@ and @mat2@ are allowed to+-- be different.+foreign import ccall "fmpz_mat.h fmpz_mat_swap"+ fmpz_mat_swap :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_swap_entrywise/ /mat1/ /mat2/ +-- +-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "fmpz_mat.h fmpz_mat_swap_entrywise"+ fmpz_mat_swap_entrywise :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_entry/ /mat/ /i/ /j/ +-- +-- Returns a reference to the entry of @mat@ at row \(i\) and column \(j\).+-- This reference can be passed as an input or output variable to any+-- function in the @fmpz@ module for direct manipulation.+-- +-- Both \(i\) and \(j\) must not exceed the dimensions of the+-- matrix. No bounds checking is performed.+fmpz_mat_entry :: Ptr CFmpzMat -> CLong -> CLong -> IO (Ptr CFmpz)+fmpz_mat_entry mat i j = do+ CFmpzMat entries r c rows <- peek mat+ return $ entries `advancePtr` (fromIntegral (i*c + j))++fmpz_mat_set_entry :: Ptr CFmpzMat -> CLong -> CLong -> Ptr CFmpz -> IO ()+fmpz_mat_set_entry mat i j x = do+ p <- fmpz_mat_entry mat i j+ fmpz_set p x+ +fmpz_mat_get_entry :: Ptr CFmpz -> Ptr CFmpzMat -> CLong -> CLong -> IO ()+fmpz_mat_get_entry x mat i j = do+ p <- fmpz_mat_entry mat i j+ fmpz_set x p++-- | /fmpz_mat_zero/ /mat/ +-- +-- Sets all entries of @mat@ to 0.+foreign import ccall "fmpz_mat.h fmpz_mat_zero"+ fmpz_mat_zero :: Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_one/ /mat/ +-- +-- Sets @mat@ to the unit matrix, having ones on the main diagonal and+-- zeroes elsewhere. If @mat@ is nonsquare, it is set to the truncation of+-- a unit matrix.+foreign import ccall "fmpz_mat.h fmpz_mat_one"+ fmpz_mat_one :: Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_swap_rows/ /mat/ /perm/ /r/ /s/ +-- +-- Swaps rows @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the rows will also be applied to @perm@.+foreign import ccall "fmpz_mat.h fmpz_mat_swap_rows"+ fmpz_mat_swap_rows :: Ptr CFmpzMat -> Ptr CLong -> CLong -> CLong -> IO ()++-- | /fmpz_mat_swap_cols/ /mat/ /perm/ /r/ /s/ +-- +-- Swaps columns @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the columns will also be applied to @perm@.+foreign import ccall "fmpz_mat.h fmpz_mat_swap_cols"+ fmpz_mat_swap_cols :: Ptr CFmpzMat -> Ptr CLong -> CLong -> CLong -> IO ()++-- | /fmpz_mat_invert_rows/ /mat/ /perm/ +-- +-- Swaps rows @i@ and @r - i@ of @mat@ for @0 \<= i \< r\/2@, where @r@ is+-- the number of rows of @mat@. If @perm@ is non-@NULL@, the permutation of+-- the rows will also be applied to @perm@.+foreign import ccall "fmpz_mat.h fmpz_mat_invert_rows"+ fmpz_mat_invert_rows :: Ptr CFmpzMat -> Ptr CLong -> IO ()++-- | /fmpz_mat_invert_cols/ /mat/ /perm/ +-- +-- Swaps columns @i@ and @c - i@ of @mat@ for @0 \<= i \< c\/2@, where @c@+-- is the number of columns of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the columns will also be applied to @perm@.+foreign import ccall "fmpz_mat.h fmpz_mat_invert_cols"+ fmpz_mat_invert_cols :: Ptr CFmpzMat -> Ptr CLong -> IO ()++-- Window ----------------------------------------------------------------------++-- | /fmpz_mat_window_init/ /window/ /mat/ /r1/ /c1/ /r2/ /c2/ +-- +-- Initializes the matrix @window@ to be an @r2 - r1@ by @c2 - c1@+-- submatrix of @mat@ whose @(0,0)@ entry is the @(r1, c1)@ entry of @mat@.+-- The memory for the elements of @window@ is shared with @mat@.+foreign import ccall "fmpz_mat.h fmpz_mat_window_init"+ fmpz_mat_window_init :: Ptr CFmpzMat -> Ptr CFmpzMat -> CLong -> CLong -> CLong -> CLong -> IO ()++-- | /fmpz_mat_window_clear/ /window/ +-- +-- Clears the matrix @window@ and releases any memory that it uses. Note+-- that the memory to the underlying matrix that @window@ points to is not+-- freed.+foreign import ccall "fmpz_mat.h fmpz_mat_window_clear"+ fmpz_mat_window_clear :: Ptr CFmpzMat -> IO ()++-- Random matrix generation ----------------------------------------------------++-- | /fmpz_mat_randbits/ /mat/ /state/ /bits/ +-- +-- Sets the entries of @mat@ to random signed integers whose absolute+-- values have the given number of binary bits.+foreign import ccall "fmpz_mat.h fmpz_mat_randbits"+ fmpz_mat_randbits :: Ptr CFmpzMat -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /fmpz_mat_randtest/ /mat/ /state/ /bits/ +-- +-- Sets the entries of @mat@ to random signed integers whose absolute+-- values have a random number of bits up to the given number of bits+-- inclusive.+foreign import ccall "fmpz_mat.h fmpz_mat_randtest"+ fmpz_mat_randtest :: Ptr CFmpzMat -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /fmpz_mat_randintrel/ /mat/ /state/ /bits/ +-- +-- Sets @mat@ to be a random /integer relations/ matrix, with signed+-- entries up to the given number of bits.+-- +-- The number of columns of @mat@ must be equal to one more than the number+-- of rows. The format of the matrix is a set of random integers in the+-- left hand column and an identity matrix in the remaining square+-- submatrix.+foreign import ccall "fmpz_mat.h fmpz_mat_randintrel"+ fmpz_mat_randintrel :: Ptr CFmpzMat -> Ptr CFRandState -> CFBitCnt -> IO ()++-- | /fmpz_mat_randsimdioph/ /mat/ /state/ /bits/ /bits2/ +-- +-- Sets @mat@ to a random /simultaneous diophantine/ matrix.+-- +-- The matrix must be square. The top left entry is set to @2^bits2@. The+-- remainder of that row is then set to signed random integers of the given+-- number of binary bits. The remainder of the first column is zero.+-- Running down the rest of the diagonal are the values @2^bits@ with all+-- remaining entries zero.+foreign import ccall "fmpz_mat.h fmpz_mat_randsimdioph"+ fmpz_mat_randsimdioph :: Ptr CFmpzMat -> Ptr CFRandState -> CFBitCnt -> CFBitCnt -> IO ()++-- | /fmpz_mat_randntrulike/ /mat/ /state/ /bits/ /q/ +-- +-- Sets a square matrix @mat@ of even dimension to a random /NTRU like/+-- matrix.+-- +-- The matrix is broken into four square submatrices. The top left+-- submatrix is set to the identity. The bottom left submatrix is set to+-- the zero matrix. The bottom right submatrix is set to \(q\) times the+-- identity matrix. Finally the top right submatrix has the following+-- format. A random vector \(h\) of length \(r/2\) is created, with random+-- signed entries of the given number of bits. Then entry \((i, j)\) of the+-- submatrix is set to \(h[i + j \bmod{r/2}]\).+foreign import ccall "fmpz_mat.h fmpz_mat_randntrulike"+ fmpz_mat_randntrulike :: Ptr CFmpzMat -> Ptr CFRandState -> CFBitCnt -> CULong -> IO ()++-- | /fmpz_mat_randntrulike2/ /mat/ /state/ /bits/ /q/ +-- +-- Sets a square matrix @mat@ of even dimension to a random /NTRU like/+-- matrix.+-- +-- The matrix is broken into four square submatrices. The top left+-- submatrix is set to \(q\) times the identity matrix. The top right+-- submatrix is set to the zero matrix. The bottom right submatrix is set+-- to the identity matrix. Finally the bottom left submatrix has the+-- following format. A random vector \(h\) of length \(r/2\) is created,+-- with random signed entries of the given number of bits. Then entry+-- \((i, j)\) of the submatrix is set to \(h[i + j \bmod{r/2}]\).+foreign import ccall "fmpz_mat.h fmpz_mat_randntrulike2"+ fmpz_mat_randntrulike2 :: Ptr CFmpzMat -> Ptr CFRandState -> CFBitCnt -> CULong -> IO ()++-- | /fmpz_mat_randajtai/ /mat/ /state/ /alpha/ +-- +-- Sets a square matrix @mat@ to a random /ajtai/ matrix. The diagonal+-- entries \((i, i)\) are set to a random entry in the range+-- \([1, 2^{b-1}]\) inclusive where \(b = \lfloor(2 r - i)^\alpha\rfloor\)+-- for some double parameter~\`alpha\`. The entries below the diagonal in+-- column~\`i\` are set to a random entry in the range+-- \((-2^b + 1, 2^b - 1)\) whilst the entries to the right of the diagonal+-- in row~\`i\` are set to zero.+foreign import ccall "fmpz_mat.h fmpz_mat_randajtai"+ fmpz_mat_randajtai :: Ptr CFmpzMat -> Ptr CFRandState -> CDouble -> IO ()++-- | /fmpz_mat_randpermdiag/ /mat/ /state/ /diag/ /n/ +-- +-- Sets @mat@ to a random permutation of the rows and columns of a given+-- diagonal matrix. The diagonal matrix is specified in the form of an+-- array of the \(n\) initial entries on the main diagonal.+-- +-- The return value is \(0\) or \(1\) depending on whether the permutation+-- is even or odd.+foreign import ccall "fmpz_mat.h fmpz_mat_randpermdiag"+ fmpz_mat_randpermdiag :: Ptr CFmpzMat -> Ptr CFRandState -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_mat_randrank/ /mat/ /state/ /rank/ /bits/ +-- +-- Sets @mat@ to a random sparse matrix with the given rank, having exactly+-- as many non-zero elements as the rank, with the nonzero elements being+-- random integers of the given bit size.+-- +-- The matrix can be transformed into a dense matrix with unchanged rank by+-- subsequently calling @fmpz_mat_randops@.+foreign import ccall "fmpz_mat.h fmpz_mat_randrank"+ fmpz_mat_randrank :: Ptr CFmpzMat -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- | /fmpz_mat_randdet/ /mat/ /state/ /det/ +-- +-- Sets @mat@ to a random sparse matrix with minimal number of nonzero+-- entries such that its determinant has the given value.+-- +-- Note that the matrix will be zero if @det@ is zero. In order to generate+-- a non-zero singular matrix, the function @fmpz_mat_randrank@ can be+-- used.+-- +-- The matrix can be transformed into a dense matrix with unchanged+-- determinant by subsequently calling @fmpz_mat_randops@.+foreign import ccall "fmpz_mat.h fmpz_mat_randdet"+ fmpz_mat_randdet :: Ptr CFmpzMat -> Ptr CFRandState -> Ptr CFmpz -> IO ()++-- | /fmpz_mat_randops/ /mat/ /state/ /count/ +-- +-- Randomises @mat@ by performing elementary row or column operations. More+-- precisely, at most @count@ random additions or subtractions of distinct+-- rows and columns will be performed. This leaves the rank (and for square+-- matrices, the determinant) unchanged.+foreign import ccall "fmpz_mat.h fmpz_mat_randops"+ fmpz_mat_randops :: Ptr CFmpzMat -> Ptr CFRandState -> CLong -> IO ()++-- Input and output ------------------------------------------------------------++-- | /fmpz_mat_fprint/ /file/ /mat/ +-- +-- Prints the given matrix to the stream @file@. The format is the number+-- of rows, a space, the number of columns, two spaces, then a space+-- separated list of coefficients, one row after the other.+-- +-- In case of success, returns a positive value; otherwise, returns a+-- non-positive value.+foreign import ccall "fmpz_mat.h fmpz_mat_fprint"+ fmpz_mat_fprint :: Ptr CFile -> Ptr CFmpzMat -> IO CInt++foreign import ccall "fmpz_mat.h fmpz_mat_get_str"+ fmpz_mat_get_str :: Ptr CFmpzMat -> IO CString+ +-- | /fmpz_mat_fprint_pretty/ /file/ /mat/ +-- +-- Prints the given matrix to the stream @file@. The format is an opening+-- square bracket then on each line a row of the matrix, followed by a+-- closing square bracket. Each row is written as an opening square bracket+-- followed by a space separated list of coefficients followed by a closing+-- square bracket.+-- +-- In case of success, returns a positive value; otherwise, returns a+-- non-positive value.+foreign import ccall "fmpz_mat.h fmpz_mat_fprint_pretty"+ fmpz_mat_fprint_pretty :: Ptr CFile -> Ptr CFmpzMat -> IO CInt++foreign import ccall "fmpz_mat.h fmpz_mat_get_str_pretty"+ fmpz_mat_get_str_pretty :: Ptr CFmpzMat -> IO CString++-- | /fmpz_mat_print/ /mat/ +-- +-- Prints the given matrix to the stream @stdout@. For further details, see+-- @fmpz_mat_fprint@.+fmpz_mat_print :: Ptr CFmpzMat -> IO CInt+fmpz_mat_print mat = printCStr (fmpz_mat_get_str) mat++-- | /fmpz_mat_print_pretty/ /mat/ +-- +-- Prints the given matrix to @stdout@. For further details, see+-- @fmpz_mat_fprint_pretty@.+fmpz_mat_print_pretty :: Ptr CFmpzMat -> IO CInt+fmpz_mat_print_pretty mat = printCStr (fmpz_mat_get_str_pretty) mat++-- | /fmpz_mat_fread/ /file/ /mat/ +-- +-- Reads a matrix from the stream @file@, storing the result in @mat@. The+-- expected format is the number of rows, a space, the number of columns,+-- two spaces, then a space separated list of coefficients, one row after+-- the other.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_mat.h fmpz_mat_fread"+ fmpz_mat_fread :: Ptr CFile -> Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_read/ /mat/ +-- +-- Reads a matrix from @stdin@, storing the result in @mat@.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_mat.h fmpz_mat_read"+ fmpz_mat_read :: Ptr CFmpzMat -> IO CInt++-- Comparison ------------------------------------------------------------------++-- | /fmpz_mat_equal/ /mat1/ /mat2/ +-- +-- Returns a non-zero value if @mat1@ and @mat2@ have the same dimensions+-- and entries, and zero otherwise.+foreign import ccall "fmpz_mat.h fmpz_mat_equal"+ fmpz_mat_equal :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_is_zero/ /mat/ +-- +-- Returns a non-zero value if all entries @mat@ are zero, and otherwise+-- returns zero.+foreign import ccall "fmpz_mat.h fmpz_mat_is_zero"+ fmpz_mat_is_zero :: Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_is_one/ /mat/ +-- +-- Returns a non-zero value if @mat@ is the unit matrix or the truncation+-- of a unit matrix, and otherwise returns zero.+foreign import ccall "fmpz_mat.h fmpz_mat_is_one"+ fmpz_mat_is_one :: Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_is_empty/ /mat/ +-- +-- Returns a non-zero value if the number of rows or the number of columns+-- in @mat@ is zero, and otherwise returns zero.+foreign import ccall "fmpz_mat.h fmpz_mat_is_empty"+ fmpz_mat_is_empty :: Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_is_square/ /mat/ +-- +-- Returns a non-zero value if the number of rows is equal to the number of+-- columns in @mat@, and otherwise returns zero.+foreign import ccall "fmpz_mat.h fmpz_mat_is_square"+ fmpz_mat_is_square :: Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_is_zero_row/ /mat/ /i/ +-- +-- Returns a non-zero value if row \(i\) of @mat@ is zero.+foreign import ccall "fmpz_mat.h fmpz_mat_is_zero_row"+ fmpz_mat_is_zero_row :: Ptr CFmpzMat -> CLong -> IO CInt++-- -- | /fmpz_mat_col_equal/ /M/ /m/ /n/ +-- -- +-- -- Returns \(1\) if columns \(m\) and \(n\) of the matrix \(M\) are equal,+-- -- otherwise returns \(0\).+-- foreign import ccall "fmpz_mat.h fmpz_mat_col_equal"+-- fmpz_mat_col_equal :: Ptr CFmpzMat -> CLong -> CLong -> IO CInt++-- -- | /fmpz_mat_row_equal/ /M/ /m/ /n/ +-- -- +-- -- Returns \(1\) if rows \(m\) and \(n\) of the matrix \(M\) are equal,+-- -- otherwise returns \(0\).+-- foreign import ccall "fmpz_mat.h fmpz_mat_row_equal"+-- fmpz_mat_row_equal :: Ptr CFmpzMat -> CLong -> CLong -> IO CInt++-- Transpose -------------------------------------------------------------------++-- | /fmpz_mat_transpose/ /B/ /A/ +-- +-- Sets \(B\) to \(A^T\), the transpose of \(A\). Dimensions must be+-- compatible. \(A\) and \(B\) are allowed to be the same object if \(A\)+-- is a square matrix.+foreign import ccall "fmpz_mat.h fmpz_mat_transpose"+ fmpz_mat_transpose :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- Concatenate -----------------------------------------------------------------++-- | /fmpz_mat_concat_vertical/ /res/ /mat1/ /mat2/ +-- +-- Sets @res@ to vertical concatenation of (@mat1@, @mat2@) in that order.+-- Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ : \(k \times n\),+-- @res@ : \((m + k) \times n\).+foreign import ccall "fmpz_mat.h fmpz_mat_concat_vertical"+ fmpz_mat_concat_vertical :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_concat_horizontal/ /res/ /mat1/ /mat2/ +-- +-- Sets @res@ to horizontal concatenation of (@mat1@, @mat2@) in that+-- order. Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ :+-- \(m \times k\), @res@ : \(m \times (n + k)\).+foreign import ccall "fmpz_mat.h fmpz_mat_concat_horizontal"+ fmpz_mat_concat_horizontal :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- Modular reduction and reconstruction ----------------------------------------++-- | /fmpz_mat_get_nmod_mat/ /Amod/ /A/ +-- +-- Sets the entries of @Amod@ to the entries of @A@ reduced by the modulus+-- of @Amod@.+foreign import ccall "fmpz_mat.h fmpz_mat_get_nmod_mat"+ fmpz_mat_get_nmod_mat :: Ptr CNModMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_set_nmod_mat/ /A/ /Amod/ +-- +-- Sets the entries of @Amod@ to the residues in @Amod@, normalised to the+-- interval \(-m/2 <= r < m/2\) where \(m\) is the modulus.+foreign import ccall "fmpz_mat.h fmpz_mat_set_nmod_mat"+ fmpz_mat_set_nmod_mat :: Ptr CFmpzMat -> Ptr CNModMat -> IO ()++-- | /fmpz_mat_set_nmod_mat_unsigned/ /A/ /Amod/ +-- +-- Sets the entries of @Amod@ to the residues in @Amod@, normalised to the+-- interval \(0 <= r < m\) where \(m\) is the modulus.+foreign import ccall "fmpz_mat.h fmpz_mat_set_nmod_mat_unsigned"+ fmpz_mat_set_nmod_mat_unsigned :: Ptr CFmpzMat -> Ptr CNModMat -> IO ()++-- | /fmpz_mat_CRT_ui/ /res/ /mat1/ /m1/ /mat2/ /sign/ +-- +-- Given @mat1@ with entries modulo @m@ and @mat2@ with modulus \(n\), sets+-- @res@ to the CRT reconstruction modulo \(mn\) with entries satisfying+-- \(-mn/2 <= c < mn/2\) (if sign = 1) or \(0 <= c < mn\) (if sign = 0).+foreign import ccall "fmpz_mat.h fmpz_mat_CRT_ui"+ fmpz_mat_CRT_ui :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> Ptr CNModMat -> CInt -> IO ()++-- | /fmpz_mat_multi_mod_ui_precomp/ /residues/ /nres/ /mat/ /comb/ /temp/ +-- +-- Sets each of the @nres@ matrices in @residues@ to @mat@ reduced modulo+-- the modulus of the respective matrix, given precomputed @comb@ and+-- @comb_temp@ structures.+foreign import ccall "fmpz_mat.h fmpz_mat_multi_mod_ui_precomp"+ fmpz_mat_multi_mod_ui_precomp :: Ptr CNModMat -> CLong -> Ptr CFmpzMat -> Ptr CFmpzComb -> Ptr CFmpzCombTemp -> IO ()++-- | /fmpz_mat_multi_mod_ui/ /residues/ /nres/ /mat/ +-- +-- Sets each of the @nres@ matrices in @residues@ to @mat@ reduced modulo+-- the modulus of the respective matrix.+-- +-- This function is provided for convenience purposes. For reducing or+-- reconstructing multiple integer matrices over the same set of moduli, it+-- is faster to use\\ @fmpz_mat_multi_mod_precomp@.+foreign import ccall "fmpz_mat.h fmpz_mat_multi_mod_ui"+ fmpz_mat_multi_mod_ui :: Ptr CNModMat -> CLong -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_multi_CRT_ui_precomp/ /mat/ /residues/ /nres/ /comb/ /temp/ /sign/ +-- +-- Reconstructs @mat@ from its images modulo the @nres@ matrices in+-- @residues@, given precomputed @comb@ and @comb_temp@ structures.+foreign import ccall "fmpz_mat.h fmpz_mat_multi_CRT_ui_precomp"+ fmpz_mat_multi_CRT_ui_precomp :: Ptr CFmpzMat -> Ptr CNModMat -> CLong -> Ptr CFmpzComb -> Ptr CFmpzCombTemp -> CInt -> IO ()++-- | /fmpz_mat_multi_CRT_ui/ /mat/ /residues/ /nres/ /sign/ +-- +-- Reconstructs @mat@ from its images modulo the @nres@ matrices in+-- @residues@.+-- +-- This function is provided for convenience purposes. For reducing or+-- reconstructing multiple integer matrices over the same set of moduli, it+-- is faster to use @fmpz_mat_multi_CRT_ui_precomp@.+foreign import ccall "fmpz_mat.h fmpz_mat_multi_CRT_ui"+ fmpz_mat_multi_CRT_ui :: Ptr CFmpzMat -> Ptr CNModMat -> CLong -> CInt -> IO ()++-- Addition and subtraction ----------------------------------------------------++-- | /fmpz_mat_add/ /C/ /A/ /B/ +-- +-- Sets @C@ to the elementwise sum \(A + B\). All inputs must be of the+-- same size. Aliasing is allowed.+foreign import ccall "fmpz_mat.h fmpz_mat_add"+ fmpz_mat_add :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_sub/ /C/ /A/ /B/ +-- +-- Sets @C@ to the elementwise difference \(A - B\). All inputs must be of+-- the same size. Aliasing is allowed.+foreign import ccall "fmpz_mat.h fmpz_mat_sub"+ fmpz_mat_sub :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_neg/ /B/ /A/ +-- +-- Sets @B@ to the elementwise negation of @A@. Both inputs must be of the+-- same size. Aliasing is allowed.+foreign import ccall "fmpz_mat.h fmpz_mat_neg"+ fmpz_mat_neg :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- Matrix-scalar arithmetic ----------------------------------------------------++-- | /fmpz_mat_scalar_mul_si/ /B/ /A/ /c/ +-- +-- Set @B = A*c@ where @A@ is an @fmpz_mat_t@ and @c@ is a scalar+-- respectively of type @slong@, @ulong@, or @fmpz_t@. The dimensions of+-- @A@ and @B@ must be compatible.+foreign import ccall "fmpz_mat.h fmpz_mat_scalar_mul_si"+ fmpz_mat_scalar_mul_si :: Ptr CFmpzMat -> Ptr CFmpzMat -> CLong -> IO ()++-- | /fmpz_mat_scalar_addmul_si/ /B/ /A/ /c/ +-- +-- Set @B = B + A*c@ where @A@ is an @fmpz_mat_t@ and @c@ is a scalar+-- respectively of type @slong@, @ulong@, or @fmpz_t@. The dimensions of+-- @A@ and @B@ must be compatible.+foreign import ccall "fmpz_mat.h fmpz_mat_scalar_addmul_si"+ fmpz_mat_scalar_addmul_si :: Ptr CFmpzMat -> Ptr CFmpzMat -> CLong -> IO ()++-- | /fmpz_mat_scalar_submul_si/ /B/ /A/ /c/ +-- +-- Set @B = B - A*c@ where @A@ is an @fmpz_mat_t@ and @c@ is a scalar+-- respectively of type @slong@, @ulong@, or @fmpz_t@. The dimensions of+-- @A@ and @B@ must be compatible.+foreign import ccall "fmpz_mat.h fmpz_mat_scalar_submul_si"+ fmpz_mat_scalar_submul_si :: Ptr CFmpzMat -> Ptr CFmpzMat -> CLong -> IO ()++-- | /fmpz_mat_scalar_addmul_nmod_mat_ui/ /B/ /A/ /c/ +-- +-- Set @B = B + A*c@ where @A@ is an @nmod_mat_t@ and @c@ is a scalar+-- respectively of type @ulong@ or @fmpz_t@. The dimensions of @A@ and @B@+-- must be compatible.+foreign import ccall "fmpz_mat.h fmpz_mat_scalar_addmul_nmod_mat_ui"+ fmpz_mat_scalar_addmul_nmod_mat_ui :: Ptr CFmpzMat -> Ptr CNModMat -> CULong -> IO ()++-- | /fmpz_mat_scalar_divexact_si/ /B/ /A/ /c/ +-- +-- Set @A = B \/ c@, where @B@ is an @fmpz_mat_t@ and @c@ is a scalar+-- respectively of type @slong@, @ulong@, or @fmpz_t@, which is assumed to+-- divide all elements of @B@ exactly.+foreign import ccall "fmpz_mat.h fmpz_mat_scalar_divexact_si"+ fmpz_mat_scalar_divexact_si :: Ptr CFmpzMat -> Ptr CFmpzMat -> CLong -> IO ()++-- | /fmpz_mat_scalar_mul_2exp/ /B/ /A/ /exp/ +-- +-- Set the matrix @B@ to the matrix @A@, of the same dimensions, multiplied+-- by \(2^{exp}\).+foreign import ccall "fmpz_mat.h fmpz_mat_scalar_mul_2exp"+ fmpz_mat_scalar_mul_2exp :: Ptr CFmpzMat -> Ptr CFmpzMat -> CULong -> IO ()++-- | /fmpz_mat_scalar_tdiv_q_2exp/ /B/ /A/ /exp/ +-- +-- Set the matrix @B@ to the matrix @A@, of the same dimensions, divided by+-- \(2^{exp}\), rounding down towards zero.+foreign import ccall "fmpz_mat.h fmpz_mat_scalar_tdiv_q_2exp"+ fmpz_mat_scalar_tdiv_q_2exp :: Ptr CFmpzMat -> Ptr CFmpzMat -> CULong -> IO ()++-- | /fmpz_mat_scalar_smod/ /B/ /A/ /P/ +-- +-- Set the matrix @B@ to the matrix @A@, of the same dimensions, with each+-- entry reduced modulo \(P\) in the symmetric moduli system. We require+-- \(P > 0\).+foreign import ccall "fmpz_mat.h fmpz_mat_scalar_smod"+ fmpz_mat_scalar_smod :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> IO ()++-- Matrix multiplication -------------------------------------------------------++-- | /fmpz_mat_mul/ /C/ /A/ /B/ +-- +-- Sets @C@ to the matrix product \(C = A B\). The matrices must have+-- compatible dimensions for matrix multiplication. Aliasing is allowed.+-- +-- This function automatically switches between classical and multimodular+-- multiplication, based on a heuristic comparison of the dimensions and+-- entry sizes.+foreign import ccall "fmpz_mat.h fmpz_mat_mul"+ fmpz_mat_mul :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_mul_classical/ /C/ /A/ /B/ +-- +-- Sets @C@ to the matrix product \(C = A B\) computed using classical+-- matrix algorithm.+-- +-- The matrices must have compatible dimensions for matrix multiplication.+-- No aliasing is allowed.+foreign import ccall "fmpz_mat.h fmpz_mat_mul_classical"+ fmpz_mat_mul_classical :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_mul_strassen/ /C/ /A/ /B/ +-- +-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. \(C\) is not allowed to be aliased with \(A\) or \(B\).+-- Uses Strassen multiplication (the Strassen-Winograd variant).+foreign import ccall "fmpz_mat.h fmpz_mat_mul_strassen"+ fmpz_mat_mul_strassen :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /_fmpz_mat_mul_multi_mod/ /C/ /A/ /B/ /sign/ /bits/ +-- +-- Sets @C@ to the matrix product \(C = AB\) computed using a multimodular+-- algorithm. \(C\) is computed modulo several small prime numbers and+-- reconstructed using the Chinese Remainder Theorem. This generally+-- becomes more efficient than classical multiplication for large matrices.+-- +-- The absolute value of the elements of \(C\) should be+-- \(< 2^{\text{bits}}\), and @sign@ should be \(0\) if the entries of+-- \(C\) are known to be nonnegative and \(1\) otherwise. The function+-- @fmpz_mat_mul_multi_mod@ calculates a rigorous bound automatically. If+-- the default bound is too pessimistic, @_fmpz_mat_mul_multi_mod@ can be+-- used with a custom bound.+-- +-- The matrices must have compatible dimensions for matrix multiplication.+-- No aliasing is allowed.+foreign import ccall "fmpz_mat.h _fmpz_mat_mul_multi_mod"+ _fmpz_mat_mul_multi_mod :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> CInt -> CFBitCnt -> IO ()++-- | /fmpz_mat_mul_blas/ /C/ /A/ /B/ +-- +-- Tries to set \(C = AB\) using BLAS and returns \(1\) for success and+-- \(0\) for failure. Dimensions must be compatible for matrix+-- multiplication. No aliasing is allowed. This function currently will+-- fail if the matrices are empty, their dimensions are too large, or their+-- max bits size is over one million bits.+foreign import ccall "fmpz_mat.h fmpz_mat_mul_blas"+ fmpz_mat_mul_blas :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_mul_fft/ /C/ /A/ /B/ +-- +-- Aliasing is allowed.+foreign import ccall "fmpz_mat.h fmpz_mat_mul_fft"+ fmpz_mat_mul_fft :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_sqr/ /B/ /A/ +-- +-- Sets @B@ to the square of the matrix @A@, which must be a square matrix.+-- Aliasing is allowed. The function calls @fmpz_mat_mul@ for dimensions+-- less than 12 and calls @fmpz_mat_sqr_bodrato@ for cases in which the+-- latter is faster.+foreign import ccall "fmpz_mat.h fmpz_mat_sqr"+ fmpz_mat_sqr :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_sqr_bodrato/ /B/ /A/ +-- +-- Sets @B@ to the square of the matrix @A@, which must be a square matrix.+-- Aliasing is allowed. The bodrato algorithm is described in+-- < [Bodrato2010]>. It is highly efficient for squaring matrices which+-- satisfy both the following conditions : (a) large elements (b)+-- dimensions less than 150.+foreign import ccall "fmpz_mat.h fmpz_mat_sqr_bodrato"+ fmpz_mat_sqr_bodrato :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_pow/ /B/ /A/ /e/ +-- +-- Sets @B@ to the matrix @A@ raised to the power @e@, where @A@ must be a+-- square matrix. Aliasing is allowed.+foreign import ccall "fmpz_mat.h fmpz_mat_pow"+ fmpz_mat_pow :: Ptr CFmpzMat -> Ptr CFmpzMat -> CULong -> IO ()++-- | /_fmpz_mat_mul_small/ /C/ /A/ /B/ +-- +-- This internal function sets \(C\) to the matrix product \(C = A B\)+-- computed using classical matrix algorithm assuming that all entries of+-- \(A\) and \(B\) are small, that is, have bits \( \le FLINT\_BITS - 2\).+-- No aliasing is allowed.+foreign import ccall "fmpz_mat.h _fmpz_mat_mul_small"+ _fmpz_mat_mul_small :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- | /_fmpz_mat_mul_double_word/ /C/ /A/ /B/ +-- +-- [This function is only for internal use and assumes that either:]+-- - the entries of \(A\) and \(B\) are all nonnegative and strictly+-- less than \(2^{2*FLINT_BITS}\), or+-- - the entries of \(A\) and \(B\) are all strictly less than+-- \(2^{2*FLINT_BITS - 1}\) in absolute value.+foreign import ccall "fmpz_mat.h _fmpz_mat_mul_double_word"+ _fmpz_mat_mul_double_word :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_mul_fmpz_vec/ /c/ /A/ /b/ /blen/ +-- +-- Compute a matrix-vector product of @A@ and @(b, blen)@ and store the+-- result in @c@. The vector @(b, blen)@ is either truncated or+-- zero-extended to the number of columns of @A@. The number entries+-- written to @c@ is always equal to the number of rows of @A@.+foreign import ccall "fmpz_mat.h fmpz_mat_mul_fmpz_vec"+ fmpz_mat_mul_fmpz_vec :: Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_mat_fmpz_vec_mul/ /c/ /a/ /alen/ /B/ +-- +-- Compute a vector-matrix product of @(a, alen)@ and @B@ and and store the+-- result in @c@. The vector @(a, alen)@ is either truncated or+-- zero-extended to the number of rows of @B@. The number entries written+-- to @c@ is always equal to the number of columns of @B@.+foreign import ccall "fmpz_mat.h fmpz_mat_fmpz_vec_mul"+ fmpz_mat_fmpz_vec_mul :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzMat -> IO ()++-- Inverse ---------------------------------------------------------------------++-- | /fmpz_mat_inv/ /Ainv/ /den/ /A/ +-- +-- Sets (@Ainv@, @den@) to the inverse matrix of @A@. Returns 1 if @A@ is+-- nonsingular and 0 if @A@ is singular. Aliasing of @Ainv@ and @A@ is+-- allowed.+-- +-- The denominator is not guaranteed to be minimal, but is guaranteed to be+-- a divisor of the determinant of @A@.+-- +-- This function uses a direct formula for matrices of size two or less,+-- and otherwise solves for the identity matrix using fraction-free LU+-- decomposition.+foreign import ccall "fmpz_mat.h fmpz_mat_inv"+ fmpz_mat_inv :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> IO CInt++-- Kronecker product -----------------------------------------------------------++-- | /fmpz_mat_kronecker_product/ /C/ /A/ /B/ +-- +-- Sets @C@ to the Kronecker product of @A@ and @B@.+foreign import ccall "fmpz_mat.h fmpz_mat_kronecker_product"+ fmpz_mat_kronecker_product :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- Content ---------------------------------------------------------------------++-- | /fmpz_mat_content/ /mat_gcd/ /A/ +-- +-- Sets @mat_gcd@ as the gcd of all the elements of the matrix @A@. Returns+-- 0 if the matrix is empty.+foreign import ccall "fmpz_mat.h fmpz_mat_content"+ fmpz_mat_content :: Ptr CFmpz -> Ptr CFmpzMat -> IO ()++-- Trace -----------------------------------------------------------------------++-- | /fmpz_mat_trace/ /trace/ /mat/ +-- +-- Computes the trace of the matrix, i.e. the sum of the entries on the+-- main diagonal. The matrix is required to be square.+foreign import ccall "fmpz_mat.h fmpz_mat_trace"+ fmpz_mat_trace :: Ptr CFmpz -> Ptr CFmpzMat -> IO ()++-- Determinant -----------------------------------------------------------------++-- | /fmpz_mat_det/ /det/ /A/ +-- +-- Sets @det@ to the determinant of the square matrix \(A\). The matrix of+-- dimension \(0 \times 0\) is defined to have determinant 1.+-- +-- This function automatically chooses between @fmpz_mat_det_cofactor@,+-- @fmpz_mat_det_bareiss@, @fmpz_mat_det_modular@ and+-- @fmpz_mat_det_modular_accelerated@ (with @proved@ = 1), depending on the+-- size of the matrix and its entries.+foreign import ccall "fmpz_mat.h fmpz_mat_det"+ fmpz_mat_det :: Ptr CFmpz -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_det_cofactor/ /det/ /A/ +-- +-- Sets @det@ to the determinant of the square matrix \(A\) computed using+-- direct cofactor expansion. This function only supports matrices up to+-- size \(4 \times 4\).+foreign import ccall "fmpz_mat.h fmpz_mat_det_cofactor"+ fmpz_mat_det_cofactor :: Ptr CFmpz -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_det_bareiss/ /det/ /A/ +-- +-- Sets @det@ to the determinant of the square matrix \(A\) computed using+-- the Bareiss algorithm. A copy of the input matrix is row reduced using+-- fraction-free Gaussian elimination, and the determinant is read off from+-- the last element on the main diagonal.+foreign import ccall "fmpz_mat.h fmpz_mat_det_bareiss"+ fmpz_mat_det_bareiss :: Ptr CFmpz -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_det_modular/ /det/ /A/ /proved/ +-- +-- Sets @det@ to the determinant of the square matrix \(A\) (if @proved@ =+-- 1), or a probabilistic value for the determinant (@proved@ = 0),+-- computed using a multimodular algorithm.+-- +-- The determinant is computed modulo several small primes and+-- reconstructed using the Chinese Remainder Theorem. With @proved@ = 1,+-- sufficiently many primes are chosen to satisfy the bound computed by+-- @fmpz_mat_det_bound@. With @proved@ = 0, the determinant is considered+-- determined if it remains unchanged modulo several consecutive primes+-- (currently if their product exceeds \(2^{100}\)).+foreign import ccall "fmpz_mat.h fmpz_mat_det_modular"+ fmpz_mat_det_modular :: Ptr CFmpz -> Ptr CFmpzMat -> CInt -> IO ()++-- | /fmpz_mat_det_modular_accelerated/ /det/ /A/ /proved/ +-- +-- Sets @det@ to the determinant of the square matrix \(A\) (if @proved@ =+-- 1), or a probabilistic value for the determinant (@proved@ = 0),+-- computed using a multimodular algorithm.+-- +-- This function uses the same basic algorithm as @fmpz_mat_det_modular@,+-- but instead of computing \(\det(A)\) directly, it generates a divisor+-- \(d\) of \(\det(A)\) and then computes \(x = \det(A) / d\) modulo+-- several small primes not dividing \(d\). This typically accelerates the+-- computation by requiring fewer primes for large matrices, since \(d\)+-- with high probability will be nearly as large as the determinant. This+-- trick is described in < [AbbottBronsteinMulders1999]>.+foreign import ccall "fmpz_mat.h fmpz_mat_det_modular_accelerated"+ fmpz_mat_det_modular_accelerated :: Ptr CFmpz -> Ptr CFmpzMat -> CInt -> IO ()++-- | /fmpz_mat_det_modular_given_divisor/ /det/ /A/ /d/ /proved/ +-- +-- Given a positive divisor \(d\) of \(\det(A)\), sets @det@ to the+-- determinant of the square matrix \(A\) (if @proved@ = 1), or a+-- probabilistic value for the determinant (@proved@ = 0), computed using a+-- multimodular algorithm.+foreign import ccall "fmpz_mat.h fmpz_mat_det_modular_given_divisor"+ fmpz_mat_det_modular_given_divisor :: Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpz -> CInt -> IO ()++-- | /fmpz_mat_det_bound/ /bound/ /A/ +-- +-- Sets @bound@ to a nonnegative integer \(B\) such that+-- \(|\det(A)| \le B\). Assumes \(A\) to be a square matrix. The bound is+-- computed from the Hadamard inequality \(|\det(A)| \le \prod \|a_i\|_2\)+-- where the product is taken over the rows \(a_i\) of \(A\).+foreign import ccall "fmpz_mat.h fmpz_mat_det_bound"+ fmpz_mat_det_bound :: Ptr CFmpz -> Ptr CFmpzMat -> IO ()++foreign import ccall "fmpz_mat.h fmpz_mat_det_bound_nonzero"+ fmpz_mat_det_bound_nonzero :: Ptr CFmpz -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_det_divisor/ /d/ /A/ +-- +-- Sets \(d\) to some positive divisor of the determinant of the given+-- square matrix \(A\), if the determinant is nonzero. If+-- \(|\det(A)| = 0\), \(d\) will always be set to zero.+-- +-- A divisor is obtained by solving \(Ax = b\) for an arbitrarily chosen+-- right-hand side \(b\) using Dixon\'s algorithm and computing the least+-- common multiple of the denominators in \(x\). This yields a divisor+-- \(d\) such that \(|\det(A)| / d\) is tiny with very high probability.+foreign import ccall "fmpz_mat.h fmpz_mat_det_divisor"+ fmpz_mat_det_divisor :: Ptr CFmpz -> Ptr CFmpzMat -> IO ()++-- Transforms ------------------------------------------------------------------++-- | /fmpz_mat_similarity/ /A/ /r/ /d/ +-- +-- Applies a similarity transform to the \(n\times n\) matrix \(M\)+-- in-place.+-- +-- If \(P\) is the \(n\times n\) identity matrix the zero entries of whose+-- row \(r\) (0-indexed) have been replaced by \(d\), this transform is+-- equivalent to \(M = P^{-1}MP\).+-- +-- Similarity transforms preserve the determinant, characteristic+-- polynomial and minimal polynomial.+foreign import ccall "fmpz_mat.h fmpz_mat_similarity"+ fmpz_mat_similarity :: Ptr CFmpzMat -> CLong -> Ptr CFmpz -> IO ()++-- Characteristic polynomial ---------------------------------------------------++-- | /_fmpz_mat_charpoly_berkowitz/ /cp/ /mat/ +-- +-- Sets @(cp, n+1)@ to the characteristic polynomial of an \(n \times n\)+-- square matrix.+foreign import ccall "fmpz_mat.h _fmpz_mat_charpoly_berkowitz"+ _fmpz_mat_charpoly_berkowitz :: Ptr CFmpz -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_charpoly_berkowitz/ /cp/ /mat/ +-- +-- Computes the characteristic polynomial of length \(n + 1\) of an+-- \(n \times n\) square matrix. Uses an \(O(n^4)\) algorithm based on the+-- method of Berkowitz.+foreign import ccall "fmpz_mat.h fmpz_mat_charpoly_berkowitz"+ fmpz_mat_charpoly_berkowitz :: Ptr CFmpzPoly -> Ptr CFmpzMat -> IO ()++-- | /_fmpz_mat_charpoly_modular/ /cp/ /mat/ +-- +-- Sets @(cp, n+1)@ to the characteristic polynomial of an \(n \times n\)+-- square matrix.+foreign import ccall "fmpz_mat.h _fmpz_mat_charpoly_modular"+ _fmpz_mat_charpoly_modular :: Ptr CFmpz -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_charpoly_modular/ /cp/ /mat/ +-- +-- Computes the characteristic polynomial of length \(n + 1\) of an+-- \(n \times n\) square matrix. Uses a modular method based on an+-- \(O(n^3)\) method over \(\mathbb{Z}/n\mathbb{Z}\).+foreign import ccall "fmpz_mat.h fmpz_mat_charpoly_modular"+ fmpz_mat_charpoly_modular :: Ptr CFmpzPoly -> Ptr CFmpzMat -> IO ()++-- | /_fmpz_mat_charpoly/ /cp/ /mat/ +-- +-- Sets @(cp, n+1)@ to the characteristic polynomial of an \(n \times n\)+-- square matrix.+foreign import ccall "fmpz_mat.h _fmpz_mat_charpoly"+ _fmpz_mat_charpoly :: Ptr CFmpz -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_charpoly/ /cp/ /mat/ +-- +-- Computes the characteristic polynomial of length \(n + 1\) of an+-- \(n \times n\) square matrix.+foreign import ccall "fmpz_mat.h fmpz_mat_charpoly"+ fmpz_mat_charpoly :: Ptr CFmpzPoly -> Ptr CFmpzMat -> IO ()++-- Minimal polynomial ----------------------------------------------------------++-- | /_fmpz_mat_minpoly_modular/ /cp/ /mat/ +-- +-- Sets @(cp, n+1)@ to the modular polynomial of an \(n \times n\) square+-- matrix and returns its length.+foreign import ccall "fmpz_mat.h _fmpz_mat_minpoly_modular"+ _fmpz_mat_minpoly_modular :: Ptr CFmpz -> Ptr CFmpzMat -> IO CLong++-- | /fmpz_mat_minpoly_modular/ /cp/ /mat/ +-- +-- Computes the minimal polynomial of an \(n \times n\) square matrix. Uses+-- a modular method based on an average time \(O~(n^3)\), worst case+-- \(O(n^4)\) method over \(\mathbb{Z}/n\mathbb{Z}\).+foreign import ccall "fmpz_mat.h fmpz_mat_minpoly_modular"+ fmpz_mat_minpoly_modular :: Ptr CFmpzPoly -> Ptr CFmpzMat -> IO ()++-- | /_fmpz_mat_minpoly/ /cp/ /mat/ +-- +-- Sets @cp@ to the minimal polynomial of an \(n \times n\) square matrix+-- and returns its length.+foreign import ccall "fmpz_mat.h _fmpz_mat_minpoly"+ _fmpz_mat_minpoly :: Ptr CFmpz -> Ptr CFmpzMat -> IO CLong++-- | /fmpz_mat_minpoly/ /cp/ /mat/ +-- +-- Computes the minimal polynomial of an \(n \times n\) square matrix.+foreign import ccall "fmpz_mat.h fmpz_mat_minpoly"+ fmpz_mat_minpoly :: Ptr CFmpzPoly -> Ptr CFmpzMat -> IO ()++-- Rank ------------------------------------------------------------------------++-- | /fmpz_mat_rank/ /A/ +-- +-- Returns the rank, that is, the number of linearly independent columns+-- (equivalently, rows), of \(A\). The rank is computed by row reducing a+-- copy of \(A\).+foreign import ccall "fmpz_mat.h fmpz_mat_rank"+ fmpz_mat_rank :: Ptr CFmpzMat -> IO CLong++-- Column partitioning ---------------------------------------------------------++-- | /fmpz_mat_col_partition/ /part/ /M/ /short_circuit/ +-- +-- Returns the number \(p\) of distinct columns of \(M\) (or \(0\) if the+-- flag @short_circuit@ is set and this number is greater than the number+-- of rows of \(M\)). The entries of array @part@ are set to values in+-- \([0, p)\) such that two entries of part are equal iff the corresponding+-- columns of \(M\) are equal. This function is used in van Hoeij+-- polynomial factoring.+foreign import ccall "fmpz_mat.h fmpz_mat_col_partition"+ fmpz_mat_col_partition :: Ptr CLong -> Ptr CFmpzMat -> CInt -> IO CInt++-- Nonsingular solving ---------------------------------------------------------++-- The following functions allow solving matrix-matrix equations \(AX = B\)+-- where the system matrix \(A\) is square and has full rank. The solving+-- is implicitly done over the field of rational numbers: except where+-- otherwise noted, an integer matrix \(\hat X\) and a separate denominator+-- \(d\) (@den@) are computed such that \(A(\hat X/d) = b\), equivalently+-- such that \(A\hat X = bd\) holds over the integers. No guarantee is made+-- that the numerators and denominator are reduced to lowest terms, but the+-- denominator is always guaranteed to be a divisor of the determinant of+-- \(A\). If \(A\) is singular, @den@ will be set to zero and the elements+-- of the solution vector or matrix will have undefined values. No aliasing+-- is allowed between arguments.+--+-- | /fmpz_mat_solve/ /X/ /den/ /A/ /B/ +-- +-- Solves the equation \(AX = B\) for nonsingular \(A\). More precisely,+-- computes (@X@, @den@) such that \(AX = B \times \operatorname{den}\).+-- Returns 1 if \(A\) is nonsingular and 0 if \(A\) is singular. The+-- computed denominator will not generally be minimal.+-- +-- This function uses Cramer\'s rule for small systems and fraction-free LU+-- decomposition followed by fraction-free forward and back substitution+-- for larger systems.+-- +-- Note that for very large systems, it is faster to compute a modular+-- solution using @fmpz_mat_solve_dixon@.+foreign import ccall "fmpz_mat.h fmpz_mat_solve"+ fmpz_mat_solve :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_solve_fflu/ /X/ /den/ /A/ /B/ +-- +-- Solves the equation \(AX = B\) for nonsingular \(A\). More precisely,+-- computes (@X@, @den@) such that \(AX = B \times \operatorname{den}\).+-- Returns 1 if \(A\) is nonsingular and 0 if \(A\) is singular. The+-- computed denominator will not generally be minimal.+-- +-- Uses fraction-free LU decomposition followed by fraction-free forward+-- and back substitution.+foreign import ccall "fmpz_mat.h fmpz_mat_solve_fflu"+ fmpz_mat_solve_fflu :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_solve_fflu_precomp/ /X/ /perm/ /FFLU/ /B/ +-- +-- Performs fraction-free forward and back substitution given a precomputed+-- fraction-free LU decomposition and corresponding permutation. If no+-- impossible division is encountered, the function returns \(1\). This+-- does not mean the system has a solution, however a return value of \(0\)+-- can only occur if the system is insoluble.+-- +-- If the return value is \(1\) and \(r\) is the rank of the matrix \(A\)+-- whose FFLU we have, then the first \(r\) rows of \(p(A)y = p(b)d\) hold,+-- where \(d\) is the denominator of the FFLU. The remaining rows must be+-- checked by the caller.+foreign import ccall "fmpz_mat.h fmpz_mat_solve_fflu_precomp"+ fmpz_mat_solve_fflu_precomp :: Ptr CFmpzMat -> Ptr CLong -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_solve_cramer/ /X/ /den/ /A/ /B/ +-- +-- Solves the equation \(AX = B\) for nonsingular \(A\). More precisely,+-- computes (@X@, @den@) such that \(AX = B \times \operatorname{den}\).+-- Returns 1 if \(A\) is nonsingular and 0 if \(A\) is singular.+-- +-- Uses Cramer\'s rule. Only systems of size up to \(3 \times 3\) are+-- allowed.+foreign import ccall "fmpz_mat.h fmpz_mat_solve_cramer"+ fmpz_mat_solve_cramer :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_solve_bound/ /N/ /D/ /A/ /B/ +-- +-- Assuming that \(A\) is nonsingular, computes integers \(N\) and \(D\)+-- such that the reduced numerators and denominators \(n/d\) in+-- \(A^{-1} B\) satisfy the bounds \(0 \le |n| \le N\) and+-- \(0 \le d \le D\).+foreign import ccall "fmpz_mat.h fmpz_mat_solve_bound"+ fmpz_mat_solve_bound :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_solve_dixon/ /X/ /M/ /A/ /B/ +-- +-- Solves \(AX = B\) given a nonsingular square matrix \(A\) and a matrix+-- \(B\) of compatible dimensions, using a modular algorithm. In+-- particular, Dixon\'s p-adic lifting algorithm is used (currently a+-- non-adaptive version). This is generally the preferred method for large+-- dimensions.+-- +-- More precisely, this function computes an integer \(M\) and an integer+-- matrix \(X\) such that \(AX = B \bmod M\) and such that all the reduced+-- numerators and denominators of the elements \(x = p/q\) in the full+-- solution satisfy \(2|p|q < M\). As such, the explicit rational solution+-- matrix can be recovered uniquely by passing the output of this function+-- to @fmpq_mat_set_fmpz_mat_mod@.+-- +-- A nonzero value is returned if \(A\) is nonsingular. If \(A\) is+-- singular, zero is returned and the values of the output variables will+-- be undefined.+-- +-- Aliasing between input and output matrices is allowed.+foreign import ccall "fmpz_mat.h fmpz_mat_solve_dixon"+ fmpz_mat_solve_dixon :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- IMPLEMENTATION ???+-- -- | /_fmpz_mat_solve_dixon_den/ /X/ /den/ /A/ /B/ /Ainv/ /p/ /N/ /D/ +-- -- +-- -- Solves the equation \(AX = B\) for nonsingular \(A\). More precisely,+-- -- computes (@X@, @den@) such that \(AX = B \times \operatorname{den}\)+-- -- using a @p@-adic algorithm for the supplied prime @p@. The values @N@+-- -- and @D@ are absolute value bounds for the numerator and denominator of+-- -- the solution.+-- -- +-- -- Uses the Dixon lifting algorithm with early termination once the lifting+-- -- stabilises.+-- foreign import ccall "fmpz_mat.h _fmpz_mat_solve_dixon_den"+-- _fmpz_mat_solve_dixon_den :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CNModMat -> CMpLimb -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_mat_solve_dixon_den/ /X/ /den/ /A/ /B/ +-- +-- Solves the equation \(AX = B\) for nonsingular \(A\). More precisely,+-- computes (@X@, @den@) such that \(AX = B \times \operatorname{den}\).+-- Returns 1 if \(A\) is nonsingular and 0 if \(A\) is singular. The+-- computed denominator will not generally be minimal.+-- +-- Uses the Dixon lifting algorithm with early termination once the lifting+-- stabilises.+foreign import ccall "fmpz_mat.h fmpz_mat_solve_dixon_den"+ fmpz_mat_solve_dixon_den :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_solve_multi_mod_den/ /X/ /den/ /A/ /B/ +-- +-- Solves the equation \(AX = B\) for nonsingular \(A\). More precisely,+-- computes (@X@, @den@) such that \(AX = B \times \operatorname{den}\).+-- Returns 1 if \(A\) is nonsingular and 0 if \(A\) is singular. The+-- computed denominator will not generally be minimal.+-- +-- Uses a Chinese remainder algorithm with early termination once the+-- lifting stabilises.+foreign import ccall "fmpz_mat.h fmpz_mat_solve_multi_mod_den"+ fmpz_mat_solve_multi_mod_den :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_can_solve_multi_mod_den/ /X/ /den/ /A/ /B/ +-- +-- Returns \(1\) if the system \(AX = B\) can be solved. If so it computes+-- (@X@, @den@) such that \(AX = B \times \operatorname{den}\). The+-- computed denominator will not generally be minimal.+-- +-- Uses a Chinese remainder algorithm.+-- +-- Note that the matrices \(A\) and \(B\) may have any shape as long as+-- they have the same number of rows.+foreign import ccall "fmpz_mat.h fmpz_mat_can_solve_multi_mod_den"+ fmpz_mat_can_solve_multi_mod_den :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_can_solve_fflu/ /X/ /den/ /A/ /B/ +-- +-- Returns \(1\) if the system \(AX = B\) can be solved. If so it computes+-- (@X@, @den@) such that \(AX = B \times \operatorname{den}\). The+-- computed denominator will not generally be minimal.+-- +-- Uses a fraction free LU decomposition algorithm.+-- +-- Note that the matrices \(A\) and \(B\) may have any shape as long as+-- they have the same number of rows.+foreign import ccall "fmpz_mat.h fmpz_mat_can_solve_fflu"+ fmpz_mat_can_solve_fflu :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_can_solve/ /X/ /den/ /A/ /B/ +-- +-- Returns \(1\) if the system \(AX = B\) can be solved. If so it computes+-- (@X@, @den@) such that \(AX = B \times \operatorname{den}\). The+-- computed denominator will not generally be minimal.+-- +-- Note that the matrices \(A\) and \(B\) may have any shape as long as+-- they have the same number of rows.+foreign import ccall "fmpz_mat.h fmpz_mat_can_solve"+ fmpz_mat_can_solve :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO CInt++-- Row reduction ---------------------------------------------------------------++-- | /fmpz_mat_find_pivot_any/ /mat/ /start_row/ /end_row/ /c/ +-- +-- Attempts to find a pivot entry for row reduction. Returns a row index+-- \(r\) between @start_row@ (inclusive) and @stop_row@ (exclusive) such+-- that column \(c\) in @mat@ has a nonzero entry on row \(r\), or returns+-- -1 if no such entry exists.+-- +-- This implementation simply chooses the first nonzero entry from it+-- encounters. This is likely to be a nearly optimal choice if all entries+-- in the matrix have roughly the same size, but can lead to unnecessary+-- coefficient growth if the entries vary in size.+foreign import ccall "fmpz_mat.h fmpz_mat_find_pivot_any"+ fmpz_mat_find_pivot_any :: Ptr CFmpzMat -> CLong -> CLong -> CLong -> IO CLong++-- | /fmpz_mat_fflu/ /B/ /den/ /perm/ /A/ /rank_check/ +-- +-- Uses fraction-free Gaussian elimination to set (@B@, @den@) to a+-- fraction-free LU decomposition of @A@ and returns the rank of @A@.+-- Aliasing of @A@ and @B@ is allowed.+-- +-- Pivot elements are chosen with @fmpz_mat_find_pivot_any@. If @perm@ is+-- non-@NULL@, the permutation of rows in the matrix will also be applied+-- to @perm@.+-- +-- If @rank_check@ is set, the function aborts and returns 0 if the matrix+-- is detected not to have full rank without completing the elimination.+-- +-- The denominator @den@ is set to \(\pm \operatorname{det}(S)\) where+-- \(S\) is an appropriate submatrix of \(A\) (S = A if \(A\) is square)+-- and the sign is decided by the parity of the permutation. Note that the+-- determinant is not generally the minimal denominator.+-- +-- The fraction-free LU decomposition is defined in < [NakTurWil1997]>.+foreign import ccall "fmpz_mat.h fmpz_mat_fflu"+ fmpz_mat_fflu :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CLong -> Ptr CFmpzMat -> CInt -> IO CLong++-- | /fmpz_mat_rref/ /B/ /den/ /A/ +-- +-- Sets (@B@, @den@) to the reduced row echelon form of @A@ and returns the+-- rank of @A@. Aliasing of @A@ and @B@ is allowed.+-- +-- The algorithm used chooses between @fmpz_mat_rref_fflu@ and+-- @fmpz_mat_rref_mul@ based on the dimensions of the input matrix.+foreign import ccall "fmpz_mat.h fmpz_mat_rref"+ fmpz_mat_rref :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> IO CLong++-- | /fmpz_mat_rref_fflu/ /B/ /den/ /A/ +-- +-- Sets (@B@, @den@) to the reduced row echelon form of @A@ and returns the+-- rank of @A@. Aliasing of @A@ and @B@ is allowed.+-- +-- The algorithm proceeds by first computing a row echelon form using+-- @fmpz_mat_fflu@. Letting the upper part of this matrix be \((U | V) P\)+-- where \(U\) is full rank upper triangular and \(P\) is a permutation+-- matrix, we obtain the rref by setting \(V\) to \(U^{-1} V\) using back+-- substitution. Scaling each completed row in the back substitution to the+-- denominator @den@, we avoid introducing new fractions. This strategy is+-- equivalent to the fraction-free Gauss-Jordan elimination in+-- < [NakTurWil1997]>, but faster since only the part \(V\) corresponding+-- to the null space has to be updated.+-- +-- The denominator @den@ is set to \(\pm \operatorname{det}(S)\) where+-- \(S\) is an appropriate submatrix of \(A\) (S = A if \(A\) is square).+-- Note that the determinant is not generally the minimal denominator.+foreign import ccall "fmpz_mat.h fmpz_mat_rref_fflu"+ fmpz_mat_rref_fflu :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> IO CLong++-- | /fmpz_mat_rref_mul/ /B/ /den/ /A/ +-- +-- Sets (@B@, @den@) to the reduced row echelon form of @A@ and returns the+-- rank of @A@. Aliasing of @A@ and @B@ is allowed.+-- +-- The algorithm works by computing the reduced row echelon form of @A@+-- modulo a prime \(p\) using @nmod_mat_rref@. The pivot columns and rows+-- of this matrix will then define a non-singular submatrix of @A@,+-- nonsingular solving and matrix multiplication can then be used to+-- determine the reduced row echelon form of the whole of @A@. This+-- procedure is described in < [Stein2007]>.+foreign import ccall "fmpz_mat.h fmpz_mat_rref_mul"+ fmpz_mat_rref_mul :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> IO CLong++-- | /fmpz_mat_is_in_rref_with_rank/ /A/ /den/ /rank/ +-- +-- Checks that the matrix \(A/den\) is in reduced row echelon form of rank+-- @rank@, returns 1 if so and 0 otherwise.+foreign import ccall "fmpz_mat.h fmpz_mat_is_in_rref_with_rank"+ fmpz_mat_is_in_rref_with_rank :: Ptr CFmpzMat -> Ptr CFmpz -> CLong -> IO CInt++-- Modular gaussian elimination ------------------------------------------------++-- | /fmpz_mat_rref_mod/ /perm/ /A/ /p/ +-- +-- Uses fraction-free Gauss-Jordan elimination to set @A@ to its reduced+-- row echelon form and returns the rank of @A@. All computations are done+-- modulo p.+-- +-- Pivot elements are chosen with @fmpz_mat_find_pivot_any@. If @perm@ is+-- non-@NULL@, the permutation of rows in the matrix will also be applied+-- to @perm@.+foreign import ccall "fmpz_mat.h fmpz_mat_rref_mod"+ fmpz_mat_rref_mod :: Ptr CLong -> Ptr CFmpzMat -> Ptr CFmpz -> IO CLong++-- Strong echelon form and Howell form -----------------------------------------++-- | /fmpz_mat_strong_echelon_form_mod/ /A/ /mod/ +-- +-- Transforms \(A\) such that \(A\) modulo @mod@ is the strong echelon form+-- of the input matrix modulo @mod@. The Howell form and the strong echelon+-- form are equal up to permutation of the rows, see < [FieHof2014]> for a+-- definition of the strong echelon form and the algorithm used here.+-- +-- \(A\) must have at least as many rows as columns.+foreign import ccall "fmpz_mat.h fmpz_mat_strong_echelon_form_mod"+ fmpz_mat_strong_echelon_form_mod :: Ptr CFmpzMat -> Ptr CFmpz -> IO ()++-- | /fmpz_mat_howell_form_mod/ /A/ /mod/ +-- +-- Transforms \(A\) such that \(A\) modulo @mod@ is the Howell form of the+-- input matrix modulo @mod@. For a definition of the Howell form see+-- < [StoMul1998]>. The Howell form is computed by first putting \(A\) into+-- strong echelon form and then ordering the rows.+-- +-- \(A\) must have at least as many rows as columns.+foreign import ccall "fmpz_mat.h fmpz_mat_howell_form_mod"+ fmpz_mat_howell_form_mod :: Ptr CNModMat -> Ptr CFmpz -> IO CLong++-- Nullspace -------------------------------------------------------------------++-- | /fmpz_mat_nullspace/ /B/ /A/ +-- +-- Computes a basis for the right rational nullspace of \(A\) and returns+-- the dimension of the nullspace (or nullity). \(B\) is set to a matrix+-- with linearly independent columns and maximal rank such that \(AB = 0\)+-- (i.e. \(Ab = 0\) for each column \(b\) in \(B\)), and the rank of \(B\)+-- is returned.+-- +-- In general, the entries in \(B\) will not be minimal: in particular, the+-- pivot entries in \(B\) will generally differ from unity. \(B\) must be+-- allocated with sufficient space to represent the result (at most+-- \(n \times n\) where \(n\) is the number of column of \(A\)).+foreign import ccall "fmpz_mat.h fmpz_mat_nullspace"+ fmpz_mat_nullspace :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO CLong++-- Echelon form ----------------------------------------------------------------++-- IMPLEMENTATION ???+-- -- | /fmpz_mat_rref_fraction_free/ /perm/ /B/ /den/ /A/ +-- -- +-- -- Computes an integer matrix @B@ and an integer @den@ such that @B \/ den@+-- -- is the unique row reduced echelon form (RREF) of @A@ and returns the+-- -- rank, i.e. the number of nonzero rows in @B@.+-- -- +-- -- Aliasing of @B@ and @A@ is allowed, with an in-place computation being+-- -- more efficient. The size of @B@ must be the same as that of @A@.+-- -- +-- -- The permutation order will be written to @perm@ unless this argument is+-- -- @NULL@. That is, row @i@ of the output matrix will correspond to row+-- -- @perm[i]@ of the input matrix.+-- -- +-- -- The denominator will always be a divisor of the determinant of (some+-- -- submatrix of) \(A\), but is not guaranteed to be minimal or canonical in+-- -- any other sense.+-- foreign import ccall "fmpz_mat.h fmpz_mat_rref_fraction_free"+-- fmpz_mat_rref_fraction_free :: Ptr CLong -> Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpzMat -> IO CLong++-- Hermite normal form ---------------------------------------------------------++-- | /fmpz_mat_hnf/ /H/ /A/ +-- +-- Computes an integer matrix @H@ such that @H@ is the unique (row) Hermite+-- normal form of @A@. The algorithm used is selected from the+-- implementations in FLINT to be the one most likely to be optimal, based+-- on the characteristics of the input matrix.+-- +-- Aliasing of @H@ and @A@ is allowed. The size of @H@ must be the same as+-- that of @A@.+foreign import ccall "fmpz_mat.h fmpz_mat_hnf"+ fmpz_mat_hnf :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_hnf_transform/ /H/ /U/ /A/ +-- +-- Computes an integer matrix @H@ such that @H@ is the unique (row) Hermite+-- normal form of @A@ along with the transformation matrix @U@ such that+-- \(UA = H\). The algorithm used is selected from the implementations in+-- FLINT as per @fmpz_mat_hnf@.+-- +-- Aliasing of @H@ and @A@ is allowed. The size of @H@ must be the same as+-- that of @A@ and @U@ must be square of compatible dimension (having the+-- same number of rows as @A@).+foreign import ccall "fmpz_mat.h fmpz_mat_hnf_transform"+ fmpz_mat_hnf_transform :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_hnf_classical/ /H/ /A/ +-- +-- Computes an integer matrix @H@ such that @H@ is the unique (row) Hermite+-- normal form of @A@. The algorithm used is straightforward and is+-- described, for example, in [Algorithm 2.4.4] < [Coh1996]>.+-- +-- Aliasing of @H@ and @A@ is allowed. The size of @H@ must be the same as+-- that of @A@.+foreign import ccall "fmpz_mat.h fmpz_mat_hnf_classical"+ fmpz_mat_hnf_classical :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_hnf_xgcd/ /H/ /A/ +-- +-- Computes an integer matrix @H@ such that @H@ is the unique (row) Hermite+-- normal form of @A@. The algorithm used is an improvement on the basic+-- algorithm and uses extended gcds to speed up computation, this method is+-- described, for example, in [Algorithm 2.4.5] < [Coh1996]>.+-- +-- Aliasing of @H@ and @A@ is allowed. The size of @H@ must be the same as+-- that of @A@.+foreign import ccall "fmpz_mat.h fmpz_mat_hnf_xgcd"+ fmpz_mat_hnf_xgcd :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_hnf_modular/ /H/ /A/ /D/ +-- +-- Computes an integer matrix @H@ such that @H@ is the unique (row) Hermite+-- normal form of the \(m\times n\) matrix @A@, where @A@ is assumed to be+-- of rank \(n\) and @D@ is known to be a positive multiple of the+-- determinant of the non-zero rows of @H@. The algorithm used here is due+-- to Domich, Kannan and Trotter < [DomKanTro1987]> and is also described+-- in [Algorithm 2.4.8] < [Coh1996]>.+-- +-- Aliasing of @H@ and @A@ is allowed. The size of @H@ must be the same as+-- that of @A@.+foreign import ccall "fmpz_mat.h fmpz_mat_hnf_modular"+ fmpz_mat_hnf_modular :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> IO ()++-- | /fmpz_mat_hnf_modular_eldiv/ /A/ /D/ +-- +-- Transforms the \(m\times n\) matrix @A@ into Hermite normal form, where+-- @A@ is assumed to be of rank \(n\) and @D@ is known to be a positive+-- multiple of the largest elementary divisor of @A@. The algorithm used+-- here is described in < [FieHof2014]>.+foreign import ccall "fmpz_mat.h fmpz_mat_hnf_modular_eldiv"+ fmpz_mat_hnf_modular_eldiv :: Ptr CFmpzMat -> Ptr CFmpz -> IO ()++-- | /fmpz_mat_hnf_minors/ /H/ /A/ +-- +-- Computes an integer matrix @H@ such that @H@ is the unique (row) Hermite+-- normal form of the \(m\times n\) matrix @A@, where @A@ is assumed to be+-- of rank \(n\). The algorithm used here is due to Kannan and Bachem+-- < [KanBac1979]> and takes the principal minors to Hermite normal form in+-- turn.+-- +-- Aliasing of @H@ and @A@ is allowed. The size of @H@ must be the same as+-- that of @A@.+foreign import ccall "fmpz_mat.h fmpz_mat_hnf_minors"+ fmpz_mat_hnf_minors :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_hnf_pernet_stein/ /H/ /A/ /state/ +-- +-- Computes an integer matrix @H@ such that @H@ is the unique (row) Hermite+-- normal form of the \(m\times n\) matrix @A@. The algorithm used here is+-- due to Pernet and Stein < [PernetStein2010]>.+-- +-- Aliasing of @H@ and @A@ is allowed. The size of @H@ must be the same as+-- that of @A@.+foreign import ccall "fmpz_mat.h fmpz_mat_hnf_pernet_stein"+ fmpz_mat_hnf_pernet_stein :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFRandState -> IO ()++-- | /fmpz_mat_is_in_hnf/ /A/ +-- +-- Checks that the given matrix is in Hermite normal form, returns 1 if so+-- and 0 otherwise.+foreign import ccall "fmpz_mat.h fmpz_mat_is_in_hnf"+ fmpz_mat_is_in_hnf :: Ptr CFmpzMat -> IO CInt++-- Smith normal form -----------------------------------------------------------++-- | /fmpz_mat_snf/ /S/ /A/ +-- +-- Computes an integer matrix @S@ such that @S@ is the unique Smith normal+-- form of @A@. The algorithm used is selected from the implementations in+-- FLINT to be the one most likely to be optimal, based on the+-- characteristics of the input matrix.+-- +-- Aliasing of @S@ and @A@ is allowed. The size of @S@ must be the same as+-- that of @A@.+foreign import ccall "fmpz_mat.h fmpz_mat_snf"+ fmpz_mat_snf :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_snf_diagonal/ /S/ /A/ +-- +-- Computes an integer matrix @S@ such that @S@ is the unique Smith normal+-- form of the diagonal matrix @A@. The algorithm used simply takes gcds of+-- pairs on the diagonal in turn until the Smith form is obtained.+-- +-- Aliasing of @S@ and @A@ is allowed. The size of @S@ must be the same as+-- that of @A@.+foreign import ccall "fmpz_mat.h fmpz_mat_snf_diagonal"+ fmpz_mat_snf_diagonal :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_snf_kannan_bachem/ /S/ /A/ +-- +-- Computes an integer matrix @S@ such that @S@ is the unique Smith normal+-- form of the diagonal matrix @A@. The algorithm used here is due to+-- Kannan and Bachem < [KanBac1979]>+-- +-- Aliasing of @S@ and @A@ is allowed. The size of @S@ must be the same as+-- that of @A@.+foreign import ccall "fmpz_mat.h fmpz_mat_snf_kannan_bachem"+ fmpz_mat_snf_kannan_bachem :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_snf_iliopoulos/ /S/ /A/ /mod/ +-- +-- Computes an integer matrix @S@ such that @S@ is the unique Smith normal+-- form of the nonsingular \(n\times n\) matrix @A@. The algorithm used is+-- due to Iliopoulos < [Iliopoulos1989]>.+-- +-- Aliasing of @S@ and @A@ is allowed. The size of @S@ must be the same as+-- that of @A@.+foreign import ccall "fmpz_mat.h fmpz_mat_snf_iliopoulos"+ fmpz_mat_snf_iliopoulos :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpz -> IO ()++-- | /fmpz_mat_is_in_snf/ /A/ +-- +-- Checks that the given matrix is in Smith normal form, returns 1 if so+-- and 0 otherwise.+foreign import ccall "fmpz_mat.h fmpz_mat_is_in_snf"+ fmpz_mat_is_in_snf :: Ptr CFmpzMat -> IO CInt++-- Special matrices ------------------------------------------------------------++-- | /fmpz_mat_gram/ /B/ /A/ +-- +-- Sets @B@ to the Gram matrix of the \(m\)-dimensional lattice @L@ in+-- \(n\)-dimensional Euclidean space \(R^n\) spanned by the rows of the+-- \(m \times n\) matrix @A@. Dimensions must be compatible. @A@ and @B@+-- are allowed to be the same object if @A@ is a square matrix.+foreign import ccall "fmpz_mat.h fmpz_mat_gram"+ fmpz_mat_gram :: Ptr CFmpzMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mat_is_hadamard/ /H/ +-- +-- Returns nonzero iff \(H\) is a Hadamard matrix, meaning that it is a+-- square matrix, only has entries that are \(\pm 1\), and satisfies+-- \(H^T = n H^{-1}\) where \(n\) is the matrix size.+foreign import ccall "fmpz_mat.h fmpz_mat_is_hadamard"+ fmpz_mat_is_hadamard :: Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_hadamard/ /H/ +-- +-- Attempts to set the matrix \(H\) to a Hadamard matrix, returning 1 if+-- successful and 0 if unsuccessful.+-- +-- A Hadamard matrix of size \(n\) can only exist if \(n\) is 1, 2, or a+-- multiple of 4. It is not known whether a Hadamard matrix exists for+-- every size that is a multiple of 4. This function uses the Paley+-- construction, which succeeds for all \(n\) of the form \(n = 2^e\) or+-- \(n = 2^e (q + 1)\) where \(q\) is an odd prime power. Orders \(n\) for+-- which Hadamard matrices are known to exist but for which this+-- construction fails are 92, 116, 156, ... (OEIS A046116).+foreign import ccall "fmpz_mat.h fmpz_mat_hadamard"+ fmpz_mat_hadamard :: Ptr CFmpzMat -> IO CInt++-- Conversions -----------------------------------------------------------------++-- | /fmpz_mat_get_d_mat/ /B/ /A/ +-- +-- Sets the entries of @B@ as doubles corresponding to the entries of @A@,+-- rounding down towards zero if the latter cannot be represented exactly.+-- The return value is -1 if any entry of @A@ is too large to fit in the+-- normal range of a double, and 0 otherwise.+foreign import ccall "fmpz_mat.h fmpz_mat_get_d_mat"+ fmpz_mat_get_d_mat :: Ptr CDMat -> Ptr CFmpzMat -> IO CInt++-- | /fmpz_mat_get_d_mat_transpose/ /B/ /A/ +-- +-- Sets the entries of @B@ as doubles corresponding to the entries of the+-- transpose of @A@, rounding down towards zero if the latter cannot be+-- represented exactly. The return value is -1 if any entry of @A@ is too+-- large to fit in the normal range of a double, and 0 otherwise.+foreign import ccall "fmpz_mat.h fmpz_mat_get_d_mat_transpose"+ fmpz_mat_get_d_mat_transpose :: Ptr CDMat -> Ptr CFmpzMat -> IO CInt++-- -- | /fmpz_mat_get_mpf_mat/ /B/ /A/ +-- -- +-- -- Sets the entries of @B@ as mpfs corresponding to the entries of @A@.+-- foreign import ccall "fmpz_mat.h fmpz_mat_get_mpf_mat"+-- fmpz_mat_get_mpf_mat :: Ptr CMpfMat -> Ptr CFmpzMat -> IO ()++-- Cholesky Decomposition ------------------------------------------------------++-- | /fmpz_mat_chol_d/ /R/ /A/ +-- +-- Computes @R@, the Cholesky factor of a symmetric, positive definite+-- matrix @A@ using the Cholesky decomposition process. (Sets @R@ such that+-- \(A = RR^{T}\) where @R@ is a lower triangular matrix.)+foreign import ccall "fmpz_mat.h fmpz_mat_chol_d"+ fmpz_mat_chol_d :: Ptr CDMat -> Ptr CFmpzMat -> IO ()++-- LLL -------------------------------------------------------------------------++-- | /fmpz_mat_is_reduced/ /A/ /delta/ /eta/ +-- +-- Returns a non-zero value if the basis @A@ is LLL-reduced with factor+-- (@delta@, @eta@), and otherwise returns zero. The second version assumes+-- @A@ is the Gram matrix of the basis.+foreign import ccall "fmpz_mat.h fmpz_mat_is_reduced"+ fmpz_mat_is_reduced :: Ptr CFmpzMat -> CDouble -> CDouble -> IO CInt++-- | /fmpz_mat_is_reduced_with_removal/ /A/ /delta/ /eta/ /gs_B/ /newd/ +-- +-- Returns a non-zero value if the basis @A@ is LLL-reduced with factor+-- (@delta@, @eta@) for each of the first @newd@ vectors and the squared+-- Gram-Schmidt length of each of the remaining \(i\)-th vectors (where+-- \(i \ge\) @newd@) is greater than @gs_B@, and otherwise returns zero.+-- The second version assumes @A@ is the Gram matrix of the basis.+foreign import ccall "fmpz_mat.h fmpz_mat_is_reduced_with_removal"+ fmpz_mat_is_reduced_with_removal :: Ptr CFmpzMat -> CDouble -> CDouble -> Ptr CFmpz -> CInt -> IO CInt++-- Classical LLL ---------------------------------------------------------------++-- | /fmpz_mat_lll_original/ /A/ /delta/ /eta/ +-- +-- Takes a basis \(x_1, x_2, \ldots, x_m\) of the lattice \(L \subset R^n\)+-- (as the rows of a \(m \times n\) matrix @A@). The output is an (@delta@,+-- @eta@)-reduced basis \(y_1, y_2, \ldots, y_m\) of the lattice \(L\) (as+-- the rows of the same \(m \times n\) matrix @A@).+foreign import ccall "fmpz_mat.h fmpz_mat_lll_original"+ fmpz_mat_lll_original :: Ptr CFmpzMat -> Ptr CFmpq -> Ptr CFmpq -> IO ()++-- Modified LLL ----------------------------------------------------------------++-- | /fmpz_mat_lll_storjohann/ /A/ /delta/ /eta/ +-- +-- Takes a basis \(x_1, x_2, \ldots, x_m\) of the lattice \(L \subset R^n\)+-- (as the rows of a \(m \times n\) matrix @A@). The output is an (@delta@,+-- @eta@)-reduced basis \(y_1, y_2, \ldots, y_m\) of the lattice \(L\) (as+-- the rows of the same \(m \times n\) matrix @A@). Uses a modified version+-- of LLL, which has better complexity in terms of the lattice dimension,+-- introduced by Storjohann.+-- +-- See \"Faster Algorithms for Integer Lattice Basis Reduction.\" Technical+-- Report 249. Zurich, Switzerland: Department Informatik, ETH. July 30,+-- 1996.+foreign import ccall "fmpz_mat.h fmpz_mat_lll_storjohann"+ fmpz_mat_lll_storjohann :: Ptr CFmpzMat -> Ptr CFmpq -> Ptr CFmpq -> IO ()+
+ src/Data/Number/Flint/Fmpz/Mat/Instances.hs view
@@ -0,0 +1,60 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Fmpz.Mat.Instances where++import System.IO.Unsafe++import Foreign.C.String+import Foreign.Marshal.Alloc ( free )+import Foreign.Storable++import Data.Number.Flint.Fmpz.Mat++instance Show FmpzMat where+ show x = unsafePerformIO $ do+ (_, cs) <- withFmpzMat x fmpz_mat_get_str_pretty+ s <- peekCString cs+ free cs+ return s++instance Eq FmpzMat where+ (==) x y = unsafePerformIO $ do+ (_, (_, flag)) <- withFmpzMat x $ \x -> do+ withFmpzMat y $ \y -> do+ fmpz_mat_equal x y+ return $ flag == 1++instance Num FmpzMat where+ (+) = lift2 fmpz_mat_add+ (-) = lift2 fmpz_mat_sub+ (*) = lift2 fmpz_mat_mul+ negate = lift1 fmpz_mat_neg+ fromInteger = undefined+ signum = undefined+ abs = undefined++instance Semigroup FmpzMat where+ (<>) = (*)++lift1 f x = unsafePerformIO $ do+ (_, (nx, mx)) <- withFmpzMat x $ \x -> do+ CFmpzMat _ nx mx _ <- peek x+ return (nx, mx)+ result <- newFmpzMat nx mx+ withFmpzMat x $ \x -> do+ withFmpzMat result $ \result -> do+ f result x+ return result+ +lift2 f x y = unsafePerformIO $ do+ (_, (nx, mx)) <- withFmpzMat x $ \x -> do+ CFmpzMat _ nx mx _ <- peek x+ return (nx, mx)+ (_, (ny, my)) <- withFmpzMat y $ \y -> do + CFmpzMat _ ny my _ <- peek y+ return (ny, my)+ result <- newFmpzMat nx my+ withFmpzMat result $ \z -> do+ withFmpzMat x $ \x -> do+ withFmpzMat y $ \y -> do+ f z x y+ return result
+ src/Data/Number/Flint/Fmpz/Mod.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Mod (+ module Data.Number.Flint.Fmpz.Mod.FFI,+) where++import Data.Number.Flint.Fmpz.Mod.FFI
+ src/Data/Number/Flint/Fmpz/Mod/FFI.hsc view
@@ -0,0 +1,283 @@+{-|+module : Data.Number.Flint.Fmpz.Mod.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Mod.FFI (+ -- * Arithmetic modulo integers+ -- * Context object+ FmpzModCtx (..)+ , CFmpzModCtx (..)+ , newFmpzModCtx+ , withFmpzModCtx+ , withNewFmpzModCtx+ , fmpz_mod_ctx_init+ , fmpz_mod_ctx_clear+ , fmpz_mod_ctx_set_modulus+ -- * Conversions+ , fmpz_mod_set_fmpz+ -- * Arithmetic+ , fmpz_mod_is_canonical+ , fmpz_mod_is_one+ , fmpz_mod_add+ , fmpz_mod_add_fmpz+ , fmpz_mod_sub+ , fmpz_mod_sub_fmpz+ , fmpz_mod_fmpz_sub+ , fmpz_mod_neg+ , fmpz_mod_mul+ , fmpz_mod_inv+ , fmpz_mod_divides+ , fmpz_mod_pow_ui+ , fmpz_mod_pow_fmpz+ -- * Discrete Logarithms via Pohlig-Hellman+ , fmpz_mod_discrete_log_pohlig_hellman_init+ , fmpz_mod_discrete_log_pohlig_hellman_clear+ , fmpz_mod_discrete_log_pohlig_hellman_precompute_prime+ , fmpz_mod_discrete_log_pohlig_hellman_primitive_root+ , fmpz_mod_discrete_log_pohlig_hellman_run+ , fmpz_next_smooth_prime+) where ++-- arithmetic modulo integers --------------------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_mod.h>++-- fmpz_mod_ctx_t --------------------------------------------------------------++data FmpzModCtx = FmpzModCtx {-# UNPACK #-} !(ForeignPtr CFmpzModCtx)+type CFmpzModCtx = CFlint FmpzModCtx++instance Storable CFmpzModCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mod_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mod_ctx_t}+ peek = error "CFmpzModCtx.peek: Not defined"+ poke = error "CFmpzModCtx.poke: Not defined"++newFmpzModCtx n = do+ p <- mallocForeignPtr+ withFmpz n $ \n -> + withForeignPtr p $ \p ->+ fmpz_mod_ctx_init p n+ addForeignPtrFinalizer p_fmpz_mod_ctx_clear p+ return $ FmpzModCtx p++{-# INLINE withFmpzModCtx #-}+withFmpzModCtx (FmpzModCtx p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpzModCtx p,)++{-# INLINE withNewFmpzModCtx #-}+withNewFmpzModCtx n f = newFmpzModCtx n >>= flip withFmpzModCtx f++-- Context object --------------------------------------------------------------++-- | /fmpz_mod_ctx_init/ /ctx/ /n/ +-- +-- Initialise @ctx@ for arithmetic modulo @n@, which is expected to be+-- positive.+foreign import ccall "fmpz_mod.h fmpz_mod_ctx_init"+ fmpz_mod_ctx_init :: Ptr CFmpzModCtx -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_ctx_clear/ /ctx/ +-- +-- Free any memory used by @ctx@.+foreign import ccall "fmpz_mod.h fmpz_mod_ctx_clear"+ fmpz_mod_ctx_clear :: Ptr CFmpzModCtx -> IO ()++foreign import ccall "fmpz_mod.h &fmpz_mod_ctx_clear"+ p_fmpz_mod_ctx_clear :: FunPtr (Ptr CFmpzModCtx -> IO ())++-- | /fmpz_mod_ctx_set_modulus/ /ctx/ /n/ +-- +-- Reconfigure @ctx@ for arithmetic modulo @n@.+foreign import ccall "fmpz_mod.h fmpz_mod_ctx_set_modulus"+ fmpz_mod_ctx_set_modulus :: Ptr CFmpzModCtx -> Ptr CFmpz -> IO ()++-- Conversions -----------------------------------------------------------------++-- | /fmpz_mod_set_fmpz/ /a/ /b/ /ctx/ +-- +-- Set @a@ to @b@ after reduction modulo the modulus.+foreign import ccall "fmpz_mod.h fmpz_mod_set_fmpz"+ fmpz_mod_set_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- Unless specified otherwise all functions here expect their relevant+-- arguments to be in the canonical range \([0,n)\). Comparison of elements+-- against each other or against zero can be accomplished with+-- func::fmpz_equal or func::fmpz_is_zero without a context.+--+-- | /fmpz_mod_is_canonical/ /a/ /ctx/ +-- +-- Return @1@ if \(a\) is in the canonical range \([0,n)\) and @0@+-- otherwise.+foreign import ccall "fmpz_mod.h fmpz_mod_is_canonical"+ fmpz_mod_is_canonical :: Ptr CFmpz -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_is_one/ /a/ /ctx/ +-- +-- Return @1@ if \(a\) is \(1\) modulo \(n\) and return @0@ otherwise.+foreign import ccall "fmpz_mod.h fmpz_mod_is_one"+ fmpz_mod_is_one :: Ptr CFmpz -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_add/ /a/ /b/ /c/ /ctx/ +-- +-- Set \(a\) to \(b+c\) modulo \(n\).+foreign import ccall "fmpz_mod.h fmpz_mod_add"+ fmpz_mod_add :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_add_fmpz/ /a/ /b/ /c/ /ctx/ +-- +-- Set \(a\) to \(b+c\) modulo \(n\) where only \(b\) is assumed to be+-- canonical.+foreign import ccall "fmpz_mod.h fmpz_mod_add_fmpz"+ fmpz_mod_add_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_sub/ /a/ /b/ /c/ /ctx/ +-- +-- Set \(a\) to \(b-c\) modulo \(n\).+foreign import ccall "fmpz_mod.h fmpz_mod_sub"+ fmpz_mod_sub :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_sub_fmpz/ /a/ /b/ /c/ /ctx/ +-- +-- Set \(a\) to \(b-c\) modulo \(n\) where only \(b\) is assumed to be+-- canonical.+foreign import ccall "fmpz_mod.h fmpz_mod_sub_fmpz"+ fmpz_mod_sub_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_fmpz_sub/ /a/ /b/ /c/ /ctx/ +-- +-- Set \(a\) to \(b-c\) modulo \(n\) where only \(c\) is assumed to be+-- canonical.+foreign import ccall "fmpz_mod.h fmpz_mod_fmpz_sub"+ fmpz_mod_fmpz_sub :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_neg/ /a/ /b/ /ctx/ +-- +-- Set \(a\) to \(-b\) modulo \(n\).+foreign import ccall "fmpz_mod.h fmpz_mod_neg"+ fmpz_mod_neg :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_mul/ /a/ /b/ /c/ /ctx/ +-- +-- Set \(a\) to \(b*c\) modulo \(n\).+foreign import ccall "fmpz_mod.h fmpz_mod_mul"+ fmpz_mod_mul :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_inv/ /a/ /b/ /ctx/ +-- +-- Set \(a\) to \(b^{-1}\) modulo \(n\). This function expects that \(b\)+-- is invertible modulo \(n\) and throws if this not the case.+-- Invertibility maybe tested with func:fmpz_mod_pow_fmpz or+-- func:fmpz_mod_divides.+foreign import ccall "fmpz_mod.h fmpz_mod_inv"+ fmpz_mod_inv :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_divides/ /a/ /b/ /c/ /ctx/ +-- +-- If \(a*c = b \mod n\) has a solution for \(a\) return \(1\) and set+-- \(a\) to such a solution. Otherwise return \(0\) and leave \(a\)+-- undefined.+foreign import ccall "fmpz_mod.h fmpz_mod_divides"+ fmpz_mod_divides :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_pow_ui/ /a/ /b/ /e/ /ctx/ +-- +-- Set \(a\) to \(b^e\) modulo \(n\).+foreign import ccall "fmpz_mod.h fmpz_mod_pow_ui"+ fmpz_mod_pow_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_pow_fmpz/ /a/ /b/ /e/ /ctx/ +-- +-- Try to set \(a\) to \(b^e\) modulo \(n\). If \(e < 0\) and \(b\) is not+-- invertible modulo \(n\), the return is \(0\). Otherwise, the return is+-- \(1\).+foreign import ccall "fmpz_mod.h fmpz_mod_pow_fmpz"+ fmpz_mod_pow_fmpz :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO CInt++-- Discrete Logarithms via Pohlig-Hellman --------------------------------------++-- fmpz_mod_discrete_log_pohlig_hellman_t --------------------------------------++data FmpzModDiscreteLogPohligHellmann = FmpzModDiscreteLogPohligHellmann {-# UNPACK #-} !(ForeignPtr CFmpzModDiscreteLogPohligHellmann)+type CFmpzModDiscreteLogPohligHellmann = CFlint FmpzModDiscreteLogPohligHellmann++instance Storable CFmpzModDiscreteLogPohligHellmann where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mod_discrete_log_pohlig_hellman_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mod_discrete_log_pohlig_hellman_t}+ peek = error "CCFmpzModDiscreteLogPohligHellmann.peek: Not defined"+ poke = error "CCFmpzModDiscreteLogPohligHellmann.poke: Not defined"++newCFmpzModDiscreteLogPohligHellmann = do+ p <- mallocForeignPtr+ withForeignPtr p fmpz_mod_discrete_log_pohlig_hellman_init+ addForeignPtrFinalizer p_fmpz_mod_discrete_log_pohlig_hellman_clear p+ return $ FmpzModDiscreteLogPohligHellmann p+ +-- | /fmpz_mod_discrete_log_pohlig_hellman_init/ /L/ +-- +-- Initialize @L@. Upon initialization @L@ is not ready for computation.+foreign import ccall "fmpz_mod.h fmpz_mod_discrete_log_pohlig_hellman_init"+ fmpz_mod_discrete_log_pohlig_hellman_init :: Ptr CFmpzModDiscreteLogPohligHellmann -> IO ()++-- | /fmpz_mod_discrete_log_pohlig_hellman_clear/ /L/ +-- +-- Free any space used by @L@.+foreign import ccall "fmpz_mod.h fmpz_mod_discrete_log_pohlig_hellman_clear"+ fmpz_mod_discrete_log_pohlig_hellman_clear :: Ptr CFmpzModDiscreteLogPohligHellmann -> IO ()++foreign import ccall "fmpz_mod.h &fmpz_mod_discrete_log_pohlig_hellman_clear"+ p_fmpz_mod_discrete_log_pohlig_hellman_clear :: FunPtr (Ptr CFmpzModDiscreteLogPohligHellmann -> IO ())+ +-- | /fmpz_mod_discrete_log_pohlig_hellman_precompute_prime/ /L/ /p/ +-- +-- Configure @L@ for discrete logarithms modulo @p@ to an internally chosen+-- base. It is assumed that @p@ is prime. The return is an estimate on the+-- number of multiplications needed for one run.+foreign import ccall "fmpz_mod.h fmpz_mod_discrete_log_pohlig_hellman_precompute_prime"+ fmpz_mod_discrete_log_pohlig_hellman_precompute_prime :: Ptr CFmpzModDiscreteLogPohligHellmann -> Ptr CFmpz -> IO CDouble++-- | /fmpz_mod_discrete_log_pohlig_hellman_primitive_root/ /L/ +-- +-- Return the internally stored base.+foreign import ccall "fmpz_mod.h fmpz_mod_discrete_log_pohlig_hellman_primitive_root"+ fmpz_mod_discrete_log_pohlig_hellman_primitive_root :: Ptr CFmpzModDiscreteLogPohligHellmann -> IO (Ptr CFmpz)++-- | /fmpz_mod_discrete_log_pohlig_hellman_run/ /x/ /L/ /y/ +-- +-- Set @x@ to the logarithm of @y@ with respect to the internally stored+-- base. @y@ is expected to be reduced modulo the @p@. The function is+-- undefined if the logarithm does not exist.+foreign import ccall "fmpz_mod.h fmpz_mod_discrete_log_pohlig_hellman_run"+ fmpz_mod_discrete_log_pohlig_hellman_run :: Ptr CFmpz -> Ptr CFmpzModDiscreteLogPohligHellmann -> Ptr CFmpz -> IO ()++-- | /fmpz_next_smooth_prime/ /a/ /b/ +-- +-- Either return \(1\) and set \(a\) to a smooth prime strictly greater+-- than \(b\), or return \(0\) and set \(a\) to \(0\). The smooth primes+-- returned by this function currently have no prime factor of \(a-1\)+-- greater than \(23\), but this should not be relied upon.+foreign import ccall "fmpz_mod.h fmpz_next_smooth_prime"+ fmpz_next_smooth_prime :: Ptr CFmpz -> Ptr CFmpz -> IO CInt+
+ src/Data/Number/Flint/Fmpz/Mod/MPoly.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Mod.MPoly (+ module Data.Number.Flint.Fmpz.Mod.MPoly.FFI+ ) where++import Data.Number.Flint.Fmpz.Mod.MPoly.FFI
+ src/Data/Number/Flint/Fmpz/Mod/MPoly/FFI.hsc view
@@ -0,0 +1,1192 @@+{-|+module : Data.Number.Flint.Fmpz.Mod.MPoly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Mod.MPoly.FFI (+ -- * Multivariate polynomials over the integers mod n+ FmpzModMPoly (..)+ , CFmpzModMPoly (..)+ , newFmpzModMPoly+ , withFmpzModMPoly+ -- * Context object+ , FmpzModMPolyCtx (..)+ , CFmpzModMPolyCtx (..)+ , newFmpzModMPolyCtx+ , withFmpzModMPolyCtx+ , fmpz_mod_mpoly_ctx_init+ , fmpz_mod_mpoly_ctx_nvars+ , fmpz_mod_mpoly_ctx_ord+ , fmpz_mod_mpoly_ctx_get_modulus+ , fmpz_mod_mpoly_ctx_clear+ -- * Memory management+ , fmpz_mod_mpoly_init+ , fmpz_mod_mpoly_init2+ , fmpz_mod_mpoly_init3+ , fmpz_mod_mpoly_clear+ -- * Input\/Output+ , fmpz_mod_mpoly_get_str_pretty+ , fmpz_mod_mpoly_fprint_pretty+ , fmpz_mod_mpoly_print_pretty+ , fmpz_mod_mpoly_set_str_pretty+ -- * Basic manipulation+ , fmpz_mod_mpoly_gen+ , fmpz_mod_mpoly_is_gen+ , fmpz_mod_mpoly_set+ , fmpz_mod_mpoly_equal+ , fmpz_mod_mpoly_swap+ -- * Constants+ , fmpz_mod_mpoly_is_fmpz+ , fmpz_mod_mpoly_get_fmpz+ , fmpz_mod_mpoly_set_fmpz+ , fmpz_mod_mpoly_set_ui+ , fmpz_mod_mpoly_set_si+ , fmpz_mod_mpoly_zero+ , fmpz_mod_mpoly_one+ , fmpz_mod_mpoly_equal_fmpz+ , fmpz_mod_mpoly_equal_ui+ , fmpz_mod_mpoly_equal_si+ , fmpz_mod_mpoly_is_zero+ , fmpz_mod_mpoly_is_one+ -- * Degrees+ , fmpz_mod_mpoly_degrees_fit_si+ , fmpz_mod_mpoly_degrees_fmpz+ , fmpz_mod_mpoly_degrees_si+ , fmpz_mod_mpoly_degree_fmpz+ , fmpz_mod_mpoly_degree_si+ , fmpz_mod_mpoly_total_degree_fits_si+ , fmpz_mod_mpoly_total_degree_fmpz+ , fmpz_mod_mpoly_total_degree_si+ , fmpz_mod_mpoly_used_vars+ -- * Coefficients+ , fmpz_mod_mpoly_get_coeff_fmpz_monomial+ , fmpz_mod_mpoly_set_coeff_fmpz_monomial+ , fmpz_mod_mpoly_get_coeff_fmpz_fmpz+ , fmpz_mod_mpoly_get_coeff_fmpz_ui+ , fmpz_mod_mpoly_set_coeff_fmpz_fmpz+ , fmpz_mod_mpoly_set_coeff_ui_fmpz+ , fmpz_mod_mpoly_set_coeff_si_fmpz+ , fmpz_mod_mpoly_set_coeff_fmpz_ui+ , fmpz_mod_mpoly_set_coeff_ui_ui+ , fmpz_mod_mpoly_set_coeff_si_ui+ , fmpz_mod_mpoly_get_coeff_vars_ui+ -- * Comparison+ , fmpz_mod_mpoly_cmp+ -- * Container operations+ , fmpz_mod_mpoly_is_canonical+ , fmpz_mod_mpoly_length+ , fmpz_mod_mpoly_resize+ , fmpz_mod_mpoly_get_term_coeff_fmpz+ , fmpz_mod_mpoly_set_term_coeff_fmpz+ , fmpz_mod_mpoly_set_term_coeff_ui+ , fmpz_mod_mpoly_set_term_coeff_si+ , fmpz_mod_mpoly_term_exp_fits_si+ , fmpz_mod_mpoly_term_exp_fits_ui+ , fmpz_mod_mpoly_get_term_exp_fmpz+ , fmpz_mod_mpoly_get_term_exp_ui+ , fmpz_mod_mpoly_get_term_exp_si+ , fmpz_mod_mpoly_get_term_var_exp_ui+ , fmpz_mod_mpoly_get_term_var_exp_si+ , fmpz_mod_mpoly_set_term_exp_fmpz+ , fmpz_mod_mpoly_set_term_exp_ui+ , fmpz_mod_mpoly_get_term+ , fmpz_mod_mpoly_get_term_monomial+ , fmpz_mod_mpoly_push_term_fmpz_fmpz+ , fmpz_mod_mpoly_push_term_ui_fmpz+ , fmpz_mod_mpoly_push_term_si_fmpz+ , fmpz_mod_mpoly_push_term_fmpz_ui+ , fmpz_mod_mpoly_push_term_ui_ui+ , fmpz_mod_mpoly_push_term_si_ui+ , fmpz_mod_mpoly_sort_terms+ , fmpz_mod_mpoly_combine_like_terms+ -- , fmpz_mod_mpoly_reverse+ -- * Random generation+ , fmpz_mod_mpoly_randtest_bound+ , fmpz_mod_mpoly_randtest_bounds+ , fmpz_mod_mpoly_randtest_bits+ -- * Addition\/Subtraction+ , fmpz_mod_mpoly_add_fmpz+ , fmpz_mod_mpoly_add_ui+ , fmpz_mod_mpoly_add_si+ , fmpz_mod_mpoly_sub_fmpz+ , fmpz_mod_mpoly_sub_ui+ , fmpz_mod_mpoly_sub_si+ , fmpz_mod_mpoly_add+ , fmpz_mod_mpoly_sub+ -- * Scalar operations+ , fmpz_mod_mpoly_neg+ , fmpz_mod_mpoly_scalar_mul_fmpz+ , fmpz_mod_mpoly_scalar_mul_ui+ , fmpz_mod_mpoly_scalar_mul_si+ , fmpz_mod_mpoly_scalar_addmul_fmpz+ , fmpz_mod_mpoly_make_monic+ -- * Differentiation+ , fmpz_mod_mpoly_derivative+ -- * Evaluation+ , fmpz_mod_mpoly_evaluate_all_fmpz+ , fmpz_mod_mpoly_evaluate_one_fmpz+ -- , fmpz_mod_mpoly_compose_fmpz_poly+ , fmpz_mod_mpoly_compose_fmpz_mod_mpoly_geobucket+ , fmpz_mod_mpoly_compose_fmpz_mod_mpoly+ -- , fmpz_mod_mpoly_compose_fmpz_mod_mpoly_gen+ -- * Multiplication+ , fmpz_mod_mpoly_mul+ , fmpz_mod_mpoly_mul_johnson+ , fmpz_mod_mpoly_mul_dense+ -- * Powering+ , fmpz_mod_mpoly_pow_fmpz+ , fmpz_mod_mpoly_pow_ui+ -- * Division+ , fmpz_mod_mpoly_divides+ , fmpz_mod_mpoly_div+ , fmpz_mod_mpoly_divrem+ , fmpz_mod_mpoly_divrem_ideal+ -- * Greatest Common Divisor+ , fmpz_mod_mpoly_term_content+ , fmpz_mod_mpoly_content_vars+ , fmpz_mod_mpoly_gcd+ , fmpz_mod_mpoly_gcd_cofactors+ , fmpz_mod_mpoly_gcd_brown+ , fmpz_mod_mpoly_gcd_hensel+ , fmpz_mod_mpoly_gcd_subresultant+ , fmpz_mod_mpoly_gcd_zippel+ , fmpz_mod_mpoly_gcd_zippel2+ , fmpz_mod_mpoly_resultant+ , fmpz_mod_mpoly_discriminant+ -- * Square Root+ , fmpz_mod_mpoly_sqrt+ , fmpz_mod_mpoly_is_square+ , fmpz_mod_mpoly_quadratic_root+ -- * Univariate Functions+ , fmpz_mod_mpoly_univar_init+ , fmpz_mod_mpoly_univar_clear+ , fmpz_mod_mpoly_univar_swap+ , fmpz_mod_mpoly_to_univar+ , fmpz_mod_mpoly_from_univar+ , fmpz_mod_mpoly_univar_degree_fits_si+ , fmpz_mod_mpoly_univar_length+ , fmpz_mod_mpoly_univar_get_term_exp_si+ , fmpz_mod_mpoly_univar_get_term_coeff+ , fmpz_mod_mpoly_univar_swap_term_coeff+ , fmpz_mod_mpoly_univar_set_coeff_ui+ , fmpz_mod_mpoly_univar_resultant+ , fmpz_mod_mpoly_univar_discriminant+ -- * Internal Functions+ , fmpz_mod_mpoly_inflate+ , fmpz_mod_mpoly_deflate+ , fmpz_mod_mpoly_deflation+) where ++-- Multivariate polynomials over the integers mod n ----------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpq+import Data.Number.Flint.MPoly+import Data.Number.Flint.Fmpz.Mod++#include <flint/flint.h>+#include <flint/fmpz_mod_mpoly.h>++-- fmpz_mod_mpoly_t ------------------------------------------------------------++data FmpzModMPoly = FmpzModMPoly {-# UNPACK #-} !(ForeignPtr CFmpzModMPoly)+data CFmpzModMPoly = CFmpzModMPoly ++instance Storable CFmpzModMPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mod_mpoly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mod_mpoly_t}+ peek = error "CFmpzModMPoly.peek: Not defined"+ poke = error "CFmpzModMPoly.poke: Not defined"++-- | Create a new `FmpzModMPoly`+newFmpzModMPoly ctx@(FmpzModMPolyCtx pctx) = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withFmpzModMPolyCtx ctx $ \ctx -> do + fmpz_mod_mpoly_init p ctx+ addForeignPtrFinalizerEnv p_fmpz_mod_mpoly_clear p pctx + return $ FmpzModMPoly p++{-# INLINE withFmpzModMPoly #-}+withFmpzModMPoly (FmpzModMPoly p) f = do+ withForeignPtr p $ \fp -> (FmpzModMPoly p,) <$> f fp++-- fmpz_mod_mpoly_univar_t -----------------------------------------------------++data FmpzModMPolyUnivar = FmpzModMPolyUnivar {-# UNPACK #-} !(ForeignPtr CFmpzModMPolyUnivar)+data CFmpzModMPolyUnivar = CFmpzModMPolyUnivar ++instance Storable CFmpzModMPolyUnivar where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mod_mpoly_univar_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mod_mpoly_univar_t}+ peek = error "CFmpzModMPolyUnivar.peek: Not defined"+ poke = error "CFmpzModMPolyUnivar.poke: Not defined"++-- | Create a new `FmpzModMPolyUnivar`+newFmpzModMPolyUnivar ctx@(FmpzModMPolyCtx pctx) = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withFmpzModMPolyCtx ctx $ \ctx -> do + fmpz_mod_mpoly_univar_init p ctx+ addForeignPtrFinalizerEnv p_fmpz_mod_mpoly_univar_clear p pctx+ return $ FmpzModMPolyUnivar p++{-# INLINE withFmpzModMPolyUnivar #-}+withFmpzModMPolyUnivar (FmpzModMPolyUnivar p) f = do+ withForeignPtr p $ \fp -> (FmpzModMPolyUnivar p,) <$> f fp+ +-- fmpz_mod_mpoly_ctx_t --------------------------------------------------------++data FmpzModMPolyCtx = FmpzModMPolyCtx {-# UNPACK #-} !(ForeignPtr CFmpzModMPolyCtx)+data CFmpzModMPolyCtx++instance Storable CFmpzModMPolyCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mod_mpoly_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mod_mpoly_ctx_t}+ peek = error "CFmpzModMPolyCtx.peek: Not defined"+ poke = error "CFmpzModMPolyCtx.poke: Not defined"++-- | Create a new `FmpzModMPolyCtx`+newFmpzModMPolyCtx nvars ord p= do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ fmpz_mod_mpoly_ctx_init x nvars ord p+ addForeignPtrFinalizer p_fmpz_mod_mpoly_ctx_clear x+ return $ FmpzModMPolyCtx x++-- | Use a `FmpzModMPolyCtx`+{-# INLINE withFmpzModMPolyCtx #-}+withFmpzModMPolyCtx (FmpzModMPolyCtx p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpzModMPolyCtx p,)++-- Context object --------------------------------------------------------------++-- | /fmpz_mod_mpoly_ctx_init/ /ctx/ /nvars/ /ord/ /p/ +--+-- Initialise a context object for a polynomial ring modulo /n/ with+-- /nvars/ variables and ordering /ord/. The possibilities for the ordering+-- are @ORD_LEX@, @ORD_DEGLEX@ and @ORD_DEGREVLEX@.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_ctx_init"+ fmpz_mod_mpoly_ctx_init :: Ptr CFmpzModMPolyCtx -> CLong -> Ptr COrdering -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_mpoly_ctx_nvars/ /ctx/ +--+-- Return the number of variables used to initialize the context.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_ctx_nvars"+ fmpz_mod_mpoly_ctx_nvars :: Ptr CFmpzModMPolyCtx -> IO CLong++-- | /fmpz_mod_mpoly_ctx_ord/ /ctx/ +--+-- Return the ordering used to initialize the context.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_ctx_ord"+ fmpz_mod_mpoly_ctx_ord :: Ptr CFmpzModMPolyCtx -> IO (Ptr COrdering)++-- | /fmpz_mod_mpoly_ctx_get_modulus/ /n/ /ctx/ +--+-- Set /n/ to the modulus used to initialize the context.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_ctx_get_modulus"+ fmpz_mod_mpoly_ctx_get_modulus :: Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_ctx_clear/ /ctx/ +--+-- Release up any space allocated by an /ctx/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_ctx_clear"+ fmpz_mod_mpoly_ctx_clear :: Ptr CFmpzModMPolyCtx -> IO ()++foreign import ccall "fmpz_mod_mpoly.h &fmpz_mod_mpoly_ctx_clear"+ p_fmpz_mod_mpoly_ctx_clear :: FunPtr (Ptr CFmpzModMPolyCtx -> IO ())++-- Memory management -----------------------------------------------------------++-- | /fmpz_mod_mpoly_init/ /A/ /ctx/ +--+-- Initialise /A/ for use with the given an initialised context object. Its+-- value is set to zero.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_init"+ fmpz_mod_mpoly_init :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_init2/ /A/ /alloc/ /ctx/ +--+-- Initialise /A/ for use with the given an initialised context object. Its+-- value is set to zero. It is allocated with space for /alloc/ terms and+-- at least @MPOLY_MIN_BITS@ bits for the exponents.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_init2"+ fmpz_mod_mpoly_init2 :: Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_init3/ /A/ /alloc/ /bits/ /ctx/ +--+-- Initialise /A/ for use with the given an initialised context object. Its+-- value is set to zero. It is allocated with space for /alloc/ terms and+-- /bits/ bits for the exponents.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_init3"+ fmpz_mod_mpoly_init3 :: Ptr CFmpzModMPoly -> CLong -> CFBitCnt -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_clear/ /A/ /ctx/ +--+-- Release any space allocated for /A/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_clear"+ fmpz_mod_mpoly_clear :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++foreign import ccall "fmpz_mod_mpoly.h &fmpz_mod_mpoly_clear"+ p_fmpz_mod_mpoly_clear :: FunPtr (Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ())++-- Input\/Output ---------------------------------------------------------------++-- | /fmpz_mod_mpoly_get_str_pretty/ /A/ /x/ /ctx/ +--+-- Return a string, which the user is responsible for cleaning up,+-- representing /A/, given an array of variable strings /x/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_str_pretty"+ fmpz_mod_mpoly_get_str_pretty :: Ptr CFmpzModMPoly -> Ptr (Ptr CChar) -> Ptr CFmpzModMPolyCtx -> IO CString++-- | /fmpz_mod_mpoly_fprint_pretty/ /file/ /A/ /x/ /ctx/ +--+-- Print a string representing /A/ to /file/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_fprint_pretty"+ fmpz_mod_mpoly_fprint_pretty :: Ptr CFile -> Ptr CFmpzModMPoly -> Ptr (Ptr CChar) -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_print_pretty/ /A/ /x/ /ctx/ +--+-- Print a string representing /A/ to @stdout@.+fmpz_mod_mpoly_print_pretty :: Ptr CFmpzModMPoly+ -> Ptr (Ptr CChar)+ -> Ptr CFmpzModMPolyCtx+ -> IO CInt+fmpz_mod_mpoly_print_pretty a x ctx = do+ printCStr (\a -> fmpz_mod_mpoly_get_str_pretty a x ctx) a++-- | /fmpz_mod_mpoly_set_str_pretty/ /A/ /str/ /x/ /ctx/ +--+-- Set /A/ to the polynomial in the null-terminates string /str/ given an+-- array /x/ of variable strings. If parsing /str/ fails, /A/ is set to+-- zero, and \(-1\) is returned. Otherwise, \(0\) is returned. The+-- operations @+@, @-@, @*@, and @\/@ are permitted along with integers and+-- the variables in /x/. The character @^@ must be immediately followed by+-- the (integer) exponent. If any division is not exact, parsing fails.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_str_pretty"+ fmpz_mod_mpoly_set_str_pretty :: Ptr CFmpzModMPoly -> CString -> Ptr (Ptr CChar) -> Ptr CFmpzModMPolyCtx -> IO CInt++-- Basic manipulation ----------------------------------------------------------++-- | /fmpz_mod_mpoly_gen/ /A/ /var/ /ctx/ +--+-- Set /A/ to the variable of index /var/, where \(var = 0\) corresponds to+-- the variable with the most significance with respect to the ordering.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_gen"+ fmpz_mod_mpoly_gen :: Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_is_gen/ /A/ /var/ /ctx/ +--+-- If \(var \ge 0\), return \(1\) if /A/ is equal to the \(var\)-th+-- generator, otherwise return \(0\). If \(var < 0\), return \(1\) if the+-- polynomial is equal to any generator, otherwise return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_is_gen"+ fmpz_mod_mpoly_is_gen :: Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_set/ /A/ /B/ /ctx/ +--+-- Set /A/ to /B/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set"+ fmpz_mod_mpoly_set :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_equal/ /A/ /B/ /ctx/ +--+-- Return \(1\) if /A/ is equal to /B/, else return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_equal"+ fmpz_mod_mpoly_equal :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_swap/ /poly1/ /poly2/ /ctx/ +--+-- Efficiently swap /A/ and /B/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_swap"+ fmpz_mod_mpoly_swap :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- Constants -------------------------------------------------------------------++-- | /fmpz_mod_mpoly_is_fmpz/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is a constant, else return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_is_fmpz"+ fmpz_mod_mpoly_is_fmpz :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_get_fmpz/ /c/ /A/ /ctx/ +--+-- Assuming that /A/ is a constant, set /c/ to this constant. This function+-- throws if /A/ is not a constant.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_fmpz"+ fmpz_mod_mpoly_get_fmpz :: Ptr CFmpz -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_set_fmpz/ /A/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_fmpz"+ fmpz_mod_mpoly_set_fmpz :: Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_set_ui/ /A/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_ui"+ fmpz_mod_mpoly_set_ui :: Ptr CFmpzModMPoly -> CULong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_set_si/ /A/ /c/ /ctx/ +--+-- Set /A/ to the constant /c/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_si"+ fmpz_mod_mpoly_set_si :: Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_zero/ /A/ /ctx/ +--+-- Set /A/ to the constant \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_zero"+ fmpz_mod_mpoly_zero :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_one/ /A/ /ctx/ +--+-- Set /A/ to the constant \(1\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_one"+ fmpz_mod_mpoly_one :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_equal_fmpz/ /A/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_equal_fmpz"+ fmpz_mod_mpoly_equal_fmpz :: Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO CInt+-- | /fmpz_mod_mpoly_equal_ui/ /A/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_equal_ui"+ fmpz_mod_mpoly_equal_ui :: Ptr CFmpzModMPoly -> CULong -> Ptr CFmpzModMPolyCtx -> IO CInt+-- | /fmpz_mod_mpoly_equal_si/ /A/ /c/ /ctx/ +--+-- Return \(1\) if /A/ is equal to the constant /c/, else return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_equal_si"+ fmpz_mod_mpoly_equal_si :: Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_is_zero/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is the constant \(0\), else return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_is_zero"+ fmpz_mod_mpoly_is_zero :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_is_one/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is the constant \(1\), else return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_is_one"+ fmpz_mod_mpoly_is_one :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- Degrees ---------------------------------------------------------------------++-- | /fmpz_mod_mpoly_degrees_fit_si/ /A/ /ctx/ +--+-- Return \(1\) if the degrees of /A/ with respect to each variable fit+-- into an @slong@, otherwise return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_degrees_fit_si"+ fmpz_mod_mpoly_degrees_fit_si :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_degrees_fmpz/ /degs/ /A/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_degrees_fmpz"+ fmpz_mod_mpoly_degrees_fmpz :: Ptr (Ptr CFmpz) -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_degrees_si/ /degs/ /A/ /ctx/ +--+-- Set /degs/ to the degrees of /A/ with respect to each variable. If /A/+-- is zero, all degrees are set to \(-1\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_degrees_si"+ fmpz_mod_mpoly_degrees_si :: Ptr CLong -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_degree_fmpz/ /deg/ /A/ /var/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_degree_fmpz"+ fmpz_mod_mpoly_degree_fmpz :: Ptr CFmpz -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_degree_si/ /A/ /var/ /ctx/ +--+-- Either return or set /deg/ to the degree of /A/ with respect to the+-- variable of index /var/. If /A/ is zero, the degree is defined to be+-- \(-1\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_degree_si"+ fmpz_mod_mpoly_degree_si :: Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO CLong++-- | /fmpz_mod_mpoly_total_degree_fits_si/ /A/ /ctx/ +--+-- Return \(1\) if the total degree of /A/ fits into an @slong@, otherwise+-- return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_total_degree_fits_si"+ fmpz_mod_mpoly_total_degree_fits_si :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_total_degree_fmpz/ /tdeg/ /A/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_total_degree_fmpz"+ fmpz_mod_mpoly_total_degree_fmpz :: Ptr CFmpz -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_total_degree_si/ /A/ /ctx/ +--+-- Either return or set /tdeg/ to the total degree of /A/. If /A/ is zero,+-- the total degree is defined to be \(-1\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_total_degree_si"+ fmpz_mod_mpoly_total_degree_si :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CLong++-- | /fmpz_mod_mpoly_used_vars/ /used/ /A/ /ctx/ +--+-- For each variable index /i/, set @used[i]@ to nonzero if the variable of+-- index /i/ appears in /A/ and to zero otherwise.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_used_vars"+ fmpz_mod_mpoly_used_vars :: Ptr CInt -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- Coefficients ----------------------------------------------------------------++-- | /fmpz_mod_mpoly_get_coeff_fmpz_monomial/ /c/ /A/ /M/ /ctx/ +--+-- Assuming that /M/ is a monomial, set /c/ to the coefficient of the+-- corresponding monomial in /A/. This function throws if /M/ is not a+-- monomial.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_coeff_fmpz_monomial"+ fmpz_mod_mpoly_get_coeff_fmpz_monomial :: Ptr CFmpz -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_set_coeff_fmpz_monomial/ /A/ /c/ /M/ /ctx/ +--+-- Assuming that /M/ is a monomial, set the coefficient of the+-- corresponding monomial in /A/ to /c/. This function throws if /M/ is not+-- a monomial.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_coeff_fmpz_monomial"+ fmpz_mod_mpoly_set_coeff_fmpz_monomial :: Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_get_coeff_fmpz_fmpz/ /c/ /A/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_coeff_fmpz_fmpz"+ fmpz_mod_mpoly_get_coeff_fmpz_fmpz :: Ptr CFmpz -> Ptr CFmpzModMPoly -> Ptr (Ptr CFmpz) -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_get_coeff_fmpz_ui/ /c/ /A/ /exp/ /ctx/ +--+-- Set /c/ to the coefficient of the monomial with exponent vector /exp/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_coeff_fmpz_ui"+ fmpz_mod_mpoly_get_coeff_fmpz_ui :: Ptr CFmpz -> Ptr CFmpzModMPoly -> Ptr CULong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_set_coeff_fmpz_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_coeff_fmpz_fmpz"+ fmpz_mod_mpoly_set_coeff_fmpz_fmpz :: Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr (Ptr CFmpz) -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_set_coeff_ui_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_coeff_ui_fmpz"+ fmpz_mod_mpoly_set_coeff_ui_fmpz :: Ptr CFmpzModMPoly -> CULong -> Ptr (Ptr CFmpz) -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_set_coeff_si_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_coeff_si_fmpz"+ fmpz_mod_mpoly_set_coeff_si_fmpz :: Ptr CFmpzModMPoly -> CLong -> Ptr (Ptr CFmpz) -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_set_coeff_fmpz_ui/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_coeff_fmpz_ui"+ fmpz_mod_mpoly_set_coeff_fmpz_ui :: Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CULong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_set_coeff_ui_ui/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_coeff_ui_ui"+ fmpz_mod_mpoly_set_coeff_ui_ui :: Ptr CFmpzModMPoly -> CULong -> Ptr CULong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_set_coeff_si_ui/ /A/ /c/ /exp/ /ctx/ +--+-- Set the coefficient of the monomial with exponent vector /exp/ to /c/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_coeff_si_ui"+ fmpz_mod_mpoly_set_coeff_si_ui :: Ptr CFmpzModMPoly -> CLong -> Ptr CULong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_get_coeff_vars_ui/ /C/ /A/ /vars/ /exps/ /length/ /ctx/ +--+-- Set /C/ to the coefficient of /A/ with respect to the variables in+-- /vars/ with powers in the corresponding array /exps/. Both /vars/ and+-- /exps/ point to array of length /length/. It is assumed that+-- \(0 < length \le nvars(A)\) and that the variables in /vars/ are+-- distinct.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_coeff_vars_ui"+ fmpz_mod_mpoly_get_coeff_vars_ui :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CLong -> Ptr CULong -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fmpz_mod_mpoly_cmp/ /A/ /B/ /ctx/ +--+-- Return \(1\) (resp. \(-1\), or \(0\)) if /A/ is after (resp. before,+-- same as) /B/ in some arbitrary but fixed total ordering of the+-- polynomials. This ordering agrees with the usual ordering of monomials+-- when /A/ and /B/ are both monomials.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_cmp"+ fmpz_mod_mpoly_cmp :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- Container operations --------------------------------------------------------+++++-- | /fmpz_mod_mpoly_is_canonical/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is in canonical form. Otherwise, return \(0\). To be+-- in canonical form, all of the terms must have nonzero coefficient, and+-- the terms must be sorted from greatest to least.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_is_canonical"+ fmpz_mod_mpoly_is_canonical :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_length/ /A/ /ctx/ +--+-- Return the number of terms in /A/. If the polynomial is in canonical+-- form, this will be the number of nonzero coefficients.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_length"+ fmpz_mod_mpoly_length :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CLong++-- | /fmpz_mod_mpoly_resize/ /A/ /new_length/ /ctx/ +--+-- Set the length of /A/ to @new_length@. Terms are either deleted from the+-- end, or new zero terms are appended.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_resize"+ fmpz_mod_mpoly_resize :: Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_get_term_coeff_fmpz/ /c/ /A/ /i/ /ctx/ +--+-- Set /c/ to the coefficient of the term of index /i/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_term_coeff_fmpz"+ fmpz_mod_mpoly_get_term_coeff_fmpz :: Ptr CFmpz -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_set_term_coeff_fmpz/ /A/ /i/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_term_coeff_fmpz"+ fmpz_mod_mpoly_set_term_coeff_fmpz :: Ptr CFmpzModMPoly -> CLong -> Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_set_term_coeff_ui/ /A/ /i/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_term_coeff_ui"+ fmpz_mod_mpoly_set_term_coeff_ui :: Ptr CFmpzModMPoly -> CLong -> CULong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_set_term_coeff_si/ /A/ /i/ /c/ /ctx/ +--+-- Set the coefficient of the term of index /i/ to /c/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_term_coeff_si"+ fmpz_mod_mpoly_set_term_coeff_si :: Ptr CFmpzModMPoly -> CLong -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_term_exp_fits_si/ /poly/ /i/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_term_exp_fits_si"+ fmpz_mod_mpoly_term_exp_fits_si :: Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO CInt+-- | /fmpz_mod_mpoly_term_exp_fits_ui/ /poly/ /i/ /ctx/ +--+-- Return \(1\) if all entries of the exponent vector of the term of index+-- /i/ fit into an @slong@ (resp. a @ulong@). Otherwise, return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_term_exp_fits_ui"+ fmpz_mod_mpoly_term_exp_fits_ui :: Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_get_term_exp_fmpz/ /exp/ /A/ /i/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_term_exp_fmpz"+ fmpz_mod_mpoly_get_term_exp_fmpz :: Ptr (Ptr CFmpz) -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_get_term_exp_ui/ /exp/ /A/ /i/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_term_exp_ui"+ fmpz_mod_mpoly_get_term_exp_ui :: Ptr CULong -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_get_term_exp_si/ /exp/ /A/ /i/ /ctx/ +--+-- Set /exp/ to the exponent vector of the term of index /i/. The @_ui@+-- (resp. @_si@) version throws if any entry does not fit into a @ulong@+-- (resp. @slong@).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_term_exp_si"+ fmpz_mod_mpoly_get_term_exp_si :: Ptr CLong -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_get_term_var_exp_ui/ /A/ /i/ /var/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_term_var_exp_ui"+ fmpz_mod_mpoly_get_term_var_exp_ui :: Ptr CFmpzModMPoly -> CLong -> CLong -> Ptr CFmpzModMPolyCtx -> IO CULong+-- | /fmpz_mod_mpoly_get_term_var_exp_si/ /A/ /i/ /var/ /ctx/ +--+-- Return the exponent of the variable /var/ of the term of index /i/. This+-- function throws if the exponent does not fit into a @ulong@ (resp.+-- @slong@).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_term_var_exp_si"+ fmpz_mod_mpoly_get_term_var_exp_si :: Ptr CFmpzModMPoly -> CLong -> CLong -> Ptr CFmpzModMPolyCtx -> IO CLong++-- | /fmpz_mod_mpoly_set_term_exp_fmpz/ /A/ /i/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_term_exp_fmpz"+ fmpz_mod_mpoly_set_term_exp_fmpz :: Ptr CFmpzModMPoly -> CLong -> Ptr (Ptr CFmpz) -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_set_term_exp_ui/ /A/ /i/ /exp/ /ctx/ +--+-- Set the exponent vector of the term of index /i/ to /exp/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_set_term_exp_ui"+ fmpz_mod_mpoly_set_term_exp_ui :: Ptr CFmpzModMPoly -> CLong -> Ptr CULong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_get_term/ /M/ /A/ /i/ /ctx/ +--+-- Set /M/ to the term of index /i/ in /A/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_term"+ fmpz_mod_mpoly_get_term :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_get_term_monomial/ /M/ /A/ /i/ /ctx/ +--+-- Set /M/ to the monomial of the term of index /i/ in /A/. The coefficient+-- of /M/ will be one.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_get_term_monomial"+ fmpz_mod_mpoly_get_term_monomial :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_push_term_fmpz_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_push_term_fmpz_fmpz"+ fmpz_mod_mpoly_push_term_fmpz_fmpz :: Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr (Ptr CFmpz) -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_push_term_ui_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_push_term_ui_fmpz"+ fmpz_mod_mpoly_push_term_ui_fmpz :: Ptr CFmpzModMPoly -> CULong -> Ptr (Ptr CFmpz) -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_push_term_si_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_push_term_si_fmpz"+ fmpz_mod_mpoly_push_term_si_fmpz :: Ptr CFmpzModMPoly -> CLong -> Ptr (Ptr CFmpz) -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_push_term_fmpz_ui/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_push_term_fmpz_ui"+ fmpz_mod_mpoly_push_term_fmpz_ui :: Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CULong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_push_term_ui_ui/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_push_term_ui_ui"+ fmpz_mod_mpoly_push_term_ui_ui :: Ptr CFmpzModMPoly -> CULong -> Ptr CULong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_push_term_si_ui/ /A/ /c/ /exp/ /ctx/ +--+-- Append a term to /A/ with coefficient /c/ and exponent vector /exp/.+-- This function runs in constant average time.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_push_term_si_ui"+ fmpz_mod_mpoly_push_term_si_ui :: Ptr CFmpzModMPoly -> CLong -> Ptr CULong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_sort_terms/ /A/ /ctx/ +--+-- Sort the terms of /A/ into the canonical ordering dictated by the+-- ordering in /ctx/. This function simply reorders the terms: It does not+-- combine like terms, nor does it delete terms with coefficient zero. This+-- function runs in linear time in the size of /A/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_sort_terms"+ fmpz_mod_mpoly_sort_terms :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_combine_like_terms/ /A/ /ctx/ +--+-- Combine adjacent like terms in /A/ and delete terms with coefficient+-- zero. If the terms of /A/ were sorted to begin with, the result will be+-- in canonical form. This function runs in linear time in the size of /A/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_combine_like_terms"+ fmpz_mod_mpoly_combine_like_terms :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- -- | /fmpz_mod_mpoly_reverse/ /A/ /B/ /ctx/ +-- --+-- -- Set /A/ to the reversal of /B/.+-- foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_reverse"+-- fmpz_mod_mpoly_reverse :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- Random generation -----------------------------------------------------------++-- | /fmpz_mod_mpoly_randtest_bound/ /A/ /state/ /length/ /exp_bound/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents in+-- the range @[0, exp_bound - 1]@. The exponents of each variable are+-- generated by calls to @n_randint(state, exp_bound)@.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_randtest_bound"+ fmpz_mod_mpoly_randtest_bound :: Ptr CFmpzModMPoly -> Ptr CFRandState -> CLong -> CULong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_randtest_bounds/ /A/ /state/ /length/ /exp_bounds/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents in+-- the range @[0, exp_bounds[i] - 1]@. The exponents of the variable of+-- index /i/ are generated by calls to @n_randint(state, exp_bounds[i])@.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_randtest_bounds"+ fmpz_mod_mpoly_randtest_bounds :: Ptr CFmpzModMPoly -> Ptr CFRandState -> CLong -> Ptr CULong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_randtest_bits/ /A/ /state/ /length/ /exp_bits/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents+-- whose packed form does not exceed the given bit count.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_randtest_bits"+ fmpz_mod_mpoly_randtest_bits :: Ptr CFmpzModMPoly -> Ptr CFRandState -> CLong -> CMpLimb -> Ptr CFmpzModMPolyCtx -> IO ()++-- Addition\/Subtraction -------------------------------------------------------++-- | /fmpz_mod_mpoly_add_fmpz/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_add_fmpz"+ fmpz_mod_mpoly_add_fmpz :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_add_ui/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_add_ui"+ fmpz_mod_mpoly_add_ui :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CULong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_add_si/ /A/ /B/ /c/ /ctx/ +--+-- Set /A/ to \(B + c\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_add_si"+ fmpz_mod_mpoly_add_si :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_sub_fmpz/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_sub_fmpz"+ fmpz_mod_mpoly_sub_fmpz :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_sub_ui/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_sub_ui"+ fmpz_mod_mpoly_sub_ui :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CULong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_sub_si/ /A/ /B/ /c/ /ctx/ +--+-- Set /A/ to \(B - c\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_sub_si"+ fmpz_mod_mpoly_sub_si :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_add/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B + C\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_add"+ fmpz_mod_mpoly_add :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_sub/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B - C\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_sub"+ fmpz_mod_mpoly_sub :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- Scalar operations -----------------------------------------------------------++-- | /fmpz_mod_mpoly_neg/ /A/ /B/ /ctx/ +--+-- Set /A/ to \(-B\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_neg"+ fmpz_mod_mpoly_neg :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_scalar_mul_fmpz/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_scalar_mul_fmpz"+ fmpz_mod_mpoly_scalar_mul_fmpz :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_scalar_mul_ui/ /A/ /B/ /c/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_scalar_mul_ui"+ fmpz_mod_mpoly_scalar_mul_ui :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CULong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_scalar_mul_si/ /A/ /B/ /c/ /ctx/ +--+-- Set /A/ to \(B \times c\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_scalar_mul_si"+ fmpz_mod_mpoly_scalar_mul_si :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_scalar_addmul_fmpz/ /A/ /B/ /C/ /d/ /ctx/ +--+-- Sets /A/ to \(B + C \times d\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_scalar_addmul_fmpz"+ fmpz_mod_mpoly_scalar_addmul_fmpz :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_make_monic/ /A/ /B/ /ctx/ +--+-- Set /A/ to /B/ divided by the leading coefficient of /B/. This throws if+-- /B/ is zero or the leading coefficient is not invertible.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_make_monic"+ fmpz_mod_mpoly_make_monic :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- Differentiation -------------------------------------------------------------++-- | /fmpz_mod_mpoly_derivative/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to the derivative of /B/ with respect to the variable of index+-- /var/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_derivative"+ fmpz_mod_mpoly_derivative :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- Evaluation ------------------------------------------------------------------+++++-- | /fmpz_mod_mpoly_evaluate_all_fmpz/ /eval/ /A/ /vals/ /ctx/ +--+-- Set /ev/ to the evaluation of /A/ where the variables are replaced by+-- the corresponding elements of the array /vals/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_evaluate_all_fmpz"+ fmpz_mod_mpoly_evaluate_all_fmpz :: Ptr CFmpz -> Ptr CFmpzModMPoly -> Ptr (Ptr CFmpz) -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_evaluate_one_fmpz/ /A/ /B/ /var/ /val/ /ctx/ +--+-- Set /A/ to the evaluation of /B/ where the variable of index /var/ is+-- replaced by /val/. Return \(1\) for success and \(0\) for failure.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_evaluate_one_fmpz"+ fmpz_mod_mpoly_evaluate_one_fmpz :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO ()++-- -- | /fmpz_mod_mpoly_compose_fmpz_poly/ /A/ /B/ /C/ /ctxB/ +-- --+-- -- Set /A/ to the evaluation of /B/ where the variables are replaced by the+-- -- corresponding elements of the array /C/. The context object of /B/ is+-- -- /ctxB/. Return \(1\) for success and \(0\) for failure.+-- foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_compose_fmpz_poly"+-- fmpz_mod_mpoly_compose_fmpz_poly :: Ptr CFmpzPoly -> Ptr CFmpzModMPoly -> Ptr (Ptr CFmpzPoly) -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_compose_fmpz_mod_mpoly_geobucket/ /A/ /B/ /C/ /ctxB/ /ctxAC/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_compose_fmpz_mod_mpoly_geobucket"+ fmpz_mod_mpoly_compose_fmpz_mod_mpoly_geobucket :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr (Ptr (Ptr CFmpzModMPoly)) -> Ptr CFmpzModMPolyCtx -> Ptr CFmpzModMPolyCtx -> IO CInt+-- | /fmpz_mod_mpoly_compose_fmpz_mod_mpoly/ /A/ /B/ /C/ /ctxB/ /ctxAC/ +--+-- Set /A/ to the evaluation of /B/ where the variables are replaced by the+-- corresponding elements of the array /C/. Both /A/ and the elements of+-- /C/ have context object /ctxAC/, while /B/ has context object /ctxB/.+-- The length of the array /C/ is the number of variables in /ctxB/.+-- Neither /A/ nor /B/ is allowed to alias any other polynomial. Return+-- \(1\) for success and \(0\) for failure. The main method attempts to+-- perform the calculation using matrices and chooses heuristically between+-- the @geobucket@ and @horner@ methods if needed.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_compose_fmpz_mod_mpoly"+ fmpz_mod_mpoly_compose_fmpz_mod_mpoly :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr (Ptr (Ptr CFmpzModMPoly)) -> Ptr CFmpzModMPolyCtx -> Ptr CFmpzModMPolyCtx -> IO CInt++-- -- | /fmpz_mod_mpoly_compose_fmpz_mod_mpoly_gen/ /A/ /B/ /c/ /ctxB/ /ctxAC/ +-- --+-- -- Set /A/ to the evaluation of /B/ where the variable of index /i/ in+-- -- /ctxB/ is replaced by the variable of index @c[i]@ in /ctxAC/. The+-- -- length of the array /C/ is the number of variables in /ctxB/. If any+-- -- @c[i]@ is negative, the corresponding variable of /B/ is replaced by+-- -- zero. Otherwise, it is expected that @c[i]@ is less than the number of+-- -- variables in /ctxAC/.+-- foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_compose_fmpz_mod_mpoly_gen"+-- fmpz_mod_mpoly_compose_fmpz_mod_mpoly_gen :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CLong -> Ptr CFmpzModMPolyCtx -> Ptr CFmpzModMPolyCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /fmpz_mod_mpoly_mul/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B \times C\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_mul"+ fmpz_mod_mpoly_mul :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_mul_johnson/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B \times C\) using Johnson\'s heap-based method.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_mul_johnson"+ fmpz_mod_mpoly_mul_johnson :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_mul_dense/ /A/ /B/ /C/ /ctx/ +--+-- Try to set /A/ to \(B \times C\) using dense arithmetic. If the return+-- is \(0\), the operation was unsuccessful. Otherwise, it was successful+-- and the return is \(1\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_mul_dense"+ fmpz_mod_mpoly_mul_dense :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- Powering --------------------------------------------------------------------+++++-- | /fmpz_mod_mpoly_pow_fmpz/ /A/ /B/ /k/ /ctx/ +--+-- Set /A/ to /B/ raised to the \(k\)-th power. Return \(1\) for success+-- and \(0\) for failure.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_pow_fmpz"+ fmpz_mod_mpoly_pow_fmpz :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_pow_ui/ /A/ /B/ /k/ /ctx/ +--+-- Set /A/ to /B/ raised to the \(k\)-th power. Return \(1\) for success+-- and \(0\) for failure.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_pow_ui"+ fmpz_mod_mpoly_pow_ui :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CULong -> Ptr CFmpzModMPolyCtx -> IO CInt++-- Division --------------------------------------------------------------------++-- The division functions assume that the modulus is prime.+--+-- | /fmpz_mod_mpoly_divides/ /Q/ /A/ /B/ /ctx/ +--+-- If /A/ is divisible by /B/, set /Q/ to the exact quotient and return+-- \(1\). Otherwise, set /Q/ to zero and return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_divides"+ fmpz_mod_mpoly_divides :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_div/ /Q/ /A/ /B/ /ctx/ +--+-- Set /Q/ to the quotient of /A/ by /B/, discarding the remainder.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_div"+ fmpz_mod_mpoly_div :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_divrem/ /Q/ /R/ /A/ /B/ /ctx/ +--+-- Set /Q/ and /R/ to the quotient and remainder of /A/ divided by /B/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_divrem"+ fmpz_mod_mpoly_divrem :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_divrem_ideal/ /Q/ /R/ /A/ /B/ /len/ /ctx/ +--+-- This function is as per @fmpz_mod_mpoly_divrem@ except that it takes an+-- array of divisor polynomials /B/ and it returns an array of quotient+-- polynomials /Q/. The number of divisor (and hence quotient) polynomials,+-- is given by /len/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_divrem_ideal"+ fmpz_mod_mpoly_divrem_ideal :: Ptr (Ptr (Ptr CFmpzModMPoly)) -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr (Ptr (Ptr CFmpzModMPoly)) -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- Greatest Common Divisor -----------------------------------------------------++-- | /fmpz_mod_mpoly_term_content/ /M/ /A/ /ctx/ +--+-- Set /M/ to the GCD of the terms of /A/. If /A/ is zero, /M/ will be+-- zero. Otherwise, /M/ will be a monomial with coefficient one.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_term_content"+ fmpz_mod_mpoly_term_content :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_content_vars/ /g/ /A/ /vars/ /vars_length/ /ctx/ +--+-- Set /g/ to the GCD of the coefficients of /A/ when viewed as a+-- polynomial in the variables /vars/. Return \(1\) for success and \(0\)+-- for failure. Upon success, /g/ will be independent of the variables+-- /vars/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_content_vars"+ fmpz_mod_mpoly_content_vars :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CLong -> CLong -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_gcd/ /G/ /A/ /B/ /ctx/ +--+-- Try to set /G/ to the monic GCD of /A/ and /B/. The GCD of zero and zero+-- is defined to be zero. If the return is \(1\) the function was+-- successful. Otherwise the return is \(0\) and /G/ is left untouched.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_gcd"+ fmpz_mod_mpoly_gcd :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_gcd_cofactors/ /G/ /Abar/ /Bbar/ /A/ /B/ /ctx/ +--+-- Do the operation of @fmpz_mod_mpoly_gcd@ and also compute \(Abar = A/G\)+-- and \(Bbar = B/G\) if successful.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_gcd_cofactors"+ fmpz_mod_mpoly_gcd_cofactors :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_gcd_brown/ /G/ /A/ /B/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_gcd_brown"+ fmpz_mod_mpoly_gcd_brown :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt+-- | /fmpz_mod_mpoly_gcd_hensel/ /G/ /A/ /B/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_gcd_hensel"+ fmpz_mod_mpoly_gcd_hensel :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt+-- | /fmpz_mod_mpoly_gcd_subresultant/ /G/ /A/ /B/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_gcd_subresultant"+ fmpz_mod_mpoly_gcd_subresultant :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt+-- | /fmpz_mod_mpoly_gcd_zippel/ /G/ /A/ /B/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_gcd_zippel"+ fmpz_mod_mpoly_gcd_zippel :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt+-- | /fmpz_mod_mpoly_gcd_zippel2/ /G/ /A/ /B/ /ctx/ +--+-- Try to set /G/ to the GCD of /A/ and /B/ using various algorithms.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_gcd_zippel2"+ fmpz_mod_mpoly_gcd_zippel2 :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_resultant/ /R/ /A/ /B/ /var/ /ctx/ +--+-- Try to set /R/ to the resultant of /A/ and /B/ with respect to the+-- variable of index /var/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_resultant"+ fmpz_mod_mpoly_resultant :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_discriminant/ /D/ /A/ /var/ /ctx/ +--+-- Try to set /D/ to the discriminant of /A/ with respect to the variable+-- of index /var/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_discriminant"+ fmpz_mod_mpoly_discriminant :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO CInt++-- Square Root -----------------------------------------------------------------++-- The square root functions assume that the modulus is prime for correct+-- operation.+--+-- | /fmpz_mod_mpoly_sqrt/ /Q/ /A/ /ctx/ +--+-- If \(Q^2=A\) has a solution, set /Q/ to a solution and return \(1\),+-- otherwise return \(0\) and set /Q/ to zero.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_sqrt"+ fmpz_mod_mpoly_sqrt :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_is_square/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is a perfect square, otherwise return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_is_square"+ fmpz_mod_mpoly_is_square :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_quadratic_root/ /Q/ /A/ /B/ /ctx/ +--+-- If \(Q^2+AQ=B\) has a solution, set /Q/ to a solution and return \(1\),+-- otherwise return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_quadratic_root"+ fmpz_mod_mpoly_quadratic_root :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- Univariate Functions --------------------------------------------------------++-- | /fmpz_mod_mpoly_univar_init/ /A/ /ctx/ +--+-- Initialize /A/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_univar_init"+ fmpz_mod_mpoly_univar_init :: Ptr CFmpzModMPolyUnivar -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_univar_clear/ /A/ /ctx/ +--+-- Clear /A/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_univar_clear"+ fmpz_mod_mpoly_univar_clear :: Ptr CFmpzModMPolyUnivar -> Ptr CFmpzModMPolyCtx -> IO ()++foreign import ccall "fmpz_mod_mpoly.h &fmpz_mod_mpoly_univar_clear"+ p_fmpz_mod_mpoly_univar_clear :: FunPtr (Ptr CFmpzModMPolyUnivar -> Ptr CFmpzModMPolyCtx -> IO ())+ +-- | /fmpz_mod_mpoly_univar_swap/ /A/ /B/ /ctx/ +--+-- Swap /A/ and /B/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_univar_swap"+ fmpz_mod_mpoly_univar_swap :: Ptr CFmpzModMPolyUnivar -> Ptr CFmpzModMPolyUnivar -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_to_univar/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to a univariate form of /B/ by pulling out the variable of index+-- /var/. The coefficients of /A/ will still belong to the content /ctx/+-- but will not depend on the variable of index /var/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_to_univar"+ fmpz_mod_mpoly_to_univar :: Ptr CFmpzModMPolyUnivar -> Ptr CFmpzModMPoly -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_from_univar/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to the normal form of /B/ by putting in the variable of index+-- /var/. This function is undefined if the coefficients of /B/ depend on+-- the variable of index /var/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_from_univar"+ fmpz_mod_mpoly_from_univar :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyUnivar -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_univar_degree_fits_si/ /A/ /ctx/ +--+-- Return \(1\) if the degree of /A/ with respect to the main variable fits+-- an @slong@. Otherwise, return \(0\).+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_univar_degree_fits_si"+ fmpz_mod_mpoly_univar_degree_fits_si :: Ptr CFmpzModMPolyUnivar -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_univar_length/ /A/ /ctx/ +--+-- Return the number of terms in /A/ with respect to the main variable.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_univar_length"+ fmpz_mod_mpoly_univar_length :: Ptr CFmpzModMPolyUnivar -> Ptr CFmpzModMPolyCtx -> IO CLong++-- | /fmpz_mod_mpoly_univar_get_term_exp_si/ /A/ /i/ /ctx/ +--+-- Return the exponent of the term of index /i/ of /A/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_univar_get_term_exp_si"+ fmpz_mod_mpoly_univar_get_term_exp_si :: Ptr CFmpzModMPolyUnivar -> CLong -> Ptr CFmpzModMPolyCtx -> IO CLong++-- | /fmpz_mod_mpoly_univar_get_term_coeff/ /c/ /A/ /i/ /ctx/ +foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_univar_get_term_coeff"+ fmpz_mod_mpoly_univar_get_term_coeff :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyUnivar -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_univar_swap_term_coeff/ /c/ /A/ /i/ /ctx/ +--+-- Set (resp. swap) /c/ to (resp. with) the coefficient of the term of+-- index /i/ of /A/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_univar_swap_term_coeff"+ fmpz_mod_mpoly_univar_swap_term_coeff :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyUnivar -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_univar_set_coeff_ui/ /Ax/ /e/ /c/ /ctx/ +--+-- Set the coefficient of \(X^e\) in /Ax/ to /c/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_univar_set_coeff_ui"+ fmpz_mod_mpoly_univar_set_coeff_ui :: Ptr CFmpzModMPolyUnivar -> CULong -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_univar_resultant/ /R/ /Ax/ /Bx/ /ctx/ +--+-- Try to set /R/ to the resultant of /Ax/ and /Bx/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_univar_resultant"+ fmpz_mod_mpoly_univar_resultant :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyUnivar -> Ptr CFmpzModMPolyUnivar -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_univar_discriminant/ /D/ /Ax/ /ctx/ +--+-- Try to set /D/ to the discriminant of /Ax/.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_univar_discriminant"+ fmpz_mod_mpoly_univar_discriminant :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyUnivar -> Ptr CFmpzModMPolyCtx -> IO CInt++-- Internal Functions ----------------------------------------------------------++-- | /fmpz_mod_mpoly_inflate/ /A/ /B/ /shift/ /stride/ /ctx/ +--+-- Apply the function @e -> shift[v] + stride[v]*e@ to each exponent @e@+-- corresponding to the variable @v@. It is assumed that each shift and+-- stride is not negative.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_inflate"+ fmpz_mod_mpoly_inflate :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_deflate/ /A/ /B/ /shift/ /stride/ /ctx/ +--+-- Apply the function @e -> (e - shift[v])\/stride[v]@ to each exponent @e@+-- corresponding to the variable @v@. If any @stride[v]@ is zero, the+-- corresponding numerator @e - shift[v]@ is assumed to be zero, and the+-- quotient is defined as zero. This allows the function to undo the+-- operation performed by @fmpz_mod_mpoly_inflate@ when possible.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_deflate"+ fmpz_mod_mpoly_deflate :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPoly -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_deflation/ /shift/ /stride/ /A/ /ctx/ +--+-- For each variable \(v\) let \(S_v\) be the set of exponents appearing on+-- \(v\). Set @shift[v]@ to \(\operatorname{min}(S_v)\) and set @stride[v]@+-- to \(\operatorname{gcd}(S-\operatorname{min}(S_v))\). If /A/ is zero,+-- all shifts and strides are set to zero.+foreign import ccall "fmpz_mod_mpoly.h fmpz_mod_mpoly_deflation"+ fmpz_mod_mpoly_deflation :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO ()+
+ src/Data/Number/Flint/Fmpz/Mod/MPoly/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Mod.MPoly.Factor (+ module Data.Number.Flint.Fmpz.Mod.MPoly.Factor.FFI,+) where++import Data.Number.Flint.Fmpz.Mod.MPoly.Factor.FFI
+ src/Data/Number/Flint/Fmpz/Mod/MPoly/Factor/FFI.hsc view
@@ -0,0 +1,159 @@+{-|+module : Data.Number.Flint.Fmpz.Mod.MPoly.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Mod.MPoly.Factor.FFI (+ -- * Factorisation of multivariate polynomials over the integers mod n+ FmpzModMPolyFactor (..)+ , CFmpzModMPolyFactor (..)+ , newFmpzModMPolyFactor+ , withFmpzModMPolyFactor+ -- * Memory management+ , fmpz_mod_mpoly_factor_init+ , fmpz_mod_mpoly_factor_clear+ -- * Basic manipulation+ , fmpz_mod_mpoly_factor_swap+ , fmpz_mod_mpoly_factor_length+ , fmpz_mod_mpoly_factor_get_constant_fmpz+ , fmpz_mod_mpoly_factor_get_base+ , fmpz_mod_mpoly_factor_swap_base+ , fmpz_mod_mpoly_factor_get_exp_si+ , fmpz_mod_mpoly_factor_sort+ -- * Factorisation+ , fmpz_mod_mpoly_factor_squarefree+ , fmpz_mod_mpoly_factor+) where++-- Factorisation of multivariate polynomials over the integers mod n -----------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpq+import Data.Number.Flint.MPoly+import Data.Number.Flint.Fmpz.Mod+import Data.Number.Flint.Fmpz.Mod.MPoly++#include <flint/flint.h>+#include <flint/fmpz_mod_mpoly.h>+#include <flint/fmpz_mod_mpoly_factor.h>++-- fmpz_mod_mpoly_t ------------------------------------------------------------++data FmpzModMPolyFactor = FmpzModMPolyFactor {-# UNPACK #-} !(ForeignPtr CFmpzModMPolyFactor)+data CFmpzModMPolyFactor = CFmpzModMPolyFactor ++instance Storable CFmpzModMPolyFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mod_mpoly_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mod_mpoly_factor_t}+ peek = error "CFmpzModMPolyFactor.peek: Not defined"+ poke = error "CFmpzModMPolyFactor.poke: Not defined"++-- | Create a new `FmpzModMPolyFactor`+newFmpzModMPolyFactor ctx@(FmpzModMPolyCtx pctx) = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withFmpzModMPolyCtx ctx $ \ctx -> do + fmpz_mod_mpoly_factor_init p ctx+ addForeignPtrFinalizerEnv p_fmpz_mod_mpoly_factor_clear p pctx + return $ FmpzModMPolyFactor p++{-# INLINE withFmpzModMPolyFactor #-}+withFmpzModMPolyFactor (FmpzModMPolyFactor p) f = do+ withForeignPtr p $ \fp -> (FmpzModMPolyFactor p,) <$> f fp++-- Memory management -----------------------------------------------------------++-- | /fmpz_mod_mpoly_factor_init/ /f/ /ctx/ +--+-- Initialise /f/.+foreign import ccall "fmpz_mod_mpoly_factor.h fmpz_mod_mpoly_factor_init"+ fmpz_mod_mpoly_factor_init :: Ptr CFmpzModMPolyFactor -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_factor_clear/ /f/ /ctx/ +--+-- Clear /f/.+foreign import ccall "fmpz_mod_mpoly_factor.h fmpz_mod_mpoly_factor_clear"+ fmpz_mod_mpoly_factor_clear :: Ptr CFmpzModMPolyFactor -> Ptr CFmpzModMPolyCtx -> IO ()++foreign import ccall "fmpz_mod_mpoly_factor.h &fmpz_mod_mpoly_factor_clear"+ p_fmpz_mod_mpoly_factor_clear :: FunPtr (Ptr CFmpzModMPolyFactor -> Ptr CFmpzModMPolyCtx -> IO ())++-- Basic manipulation ----------------------------------------------------------++-- | /fmpz_mod_mpoly_factor_swap/ /f/ /g/ /ctx/ +--+-- Efficiently swap /f/ and /g/.+foreign import ccall "fmpz_mod_mpoly_factor.h fmpz_mod_mpoly_factor_swap"+ fmpz_mod_mpoly_factor_swap :: Ptr CFmpzModMPolyFactor -> Ptr CFmpzModMPolyFactor -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_factor_length/ /f/ /ctx/ +--+-- Return the length of the product in /f/.+foreign import ccall "fmpz_mod_mpoly_factor.h fmpz_mod_mpoly_factor_length"+ fmpz_mod_mpoly_factor_length :: Ptr CFmpzModMPolyFactor -> Ptr CFmpzModMPolyCtx -> IO CLong++-- | /fmpz_mod_mpoly_factor_get_constant_fmpz/ /c/ /f/ /ctx/ +--+-- Set /c/ to the constant of /f/.+foreign import ccall "fmpz_mod_mpoly_factor.h fmpz_mod_mpoly_factor_get_constant_fmpz"+ fmpz_mod_mpoly_factor_get_constant_fmpz :: Ptr CFmpz -> Ptr CFmpzModMPolyFactor -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_factor_get_base/ /B/ /f/ /i/ /ctx/ +foreign import ccall "fmpz_mod_mpoly_factor.h fmpz_mod_mpoly_factor_get_base"+ fmpz_mod_mpoly_factor_get_base :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyFactor -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()+-- | /fmpz_mod_mpoly_factor_swap_base/ /B/ /f/ /i/ /ctx/ +--+-- Set (resp. swap) /B/ to (resp. with) the base of the term of index /i/+-- in /f/.+foreign import ccall "fmpz_mod_mpoly_factor.h fmpz_mod_mpoly_factor_swap_base"+ fmpz_mod_mpoly_factor_swap_base :: Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyFactor -> CLong -> Ptr CFmpzModMPolyCtx -> IO ()++-- | /fmpz_mod_mpoly_factor_get_exp_si/ /f/ /i/ /ctx/ +--+-- Return the exponent of the term of index /i/ in /f/. It is assumed to+-- fit an @slong@.+foreign import ccall "fmpz_mod_mpoly_factor.h fmpz_mod_mpoly_factor_get_exp_si"+ fmpz_mod_mpoly_factor_get_exp_si :: Ptr CFmpzModMPolyFactor -> CLong -> Ptr CFmpzModMPolyCtx -> IO CLong++-- | /fmpz_mod_mpoly_factor_sort/ /f/ /ctx/ +--+-- Sort the product of /f/ first by exponent and then by base.+foreign import ccall "fmpz_mod_mpoly_factor.h fmpz_mod_mpoly_factor_sort"+ fmpz_mod_mpoly_factor_sort :: Ptr CFmpzModMPolyFactor -> Ptr CFmpzModMPolyCtx -> IO ()++-- Factorisation ---------------------------------------------------------------+++++-- | /fmpz_mod_mpoly_factor_squarefree/ /f/ /A/ /ctx/ +--+-- Set /f/ to a factorization of /A/ where the bases are primitive and+-- pairwise relatively prime. If the product of all irreducible factors+-- with a given exponent is desired, it is recommended to call+-- @fmpz_mod_mpoly_factor_sort@ and then multiply the bases with the+-- desired exponent.+foreign import ccall "fmpz_mod_mpoly_factor.h fmpz_mod_mpoly_factor_squarefree"+ fmpz_mod_mpoly_factor_squarefree :: Ptr CFmpzModMPolyFactor -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt++-- | /fmpz_mod_mpoly_factor/ /f/ /A/ /ctx/ +--+-- Set /f/ to a factorization of /A/ where the bases are irreducible.+foreign import ccall "fmpz_mod_mpoly_factor.h fmpz_mod_mpoly_factor"+ fmpz_mod_mpoly_factor :: Ptr CFmpzModMPolyFactor -> Ptr CFmpzModMPoly -> Ptr CFmpzModMPolyCtx -> IO CInt+
+ src/Data/Number/Flint/Fmpz/Mod/Mat.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Mod.Mat (+ module Data.Number.Flint.Fmpz.Mod.Mat.FFI+ ) where++import Data.Number.Flint.Fmpz.Mod.Mat.FFI
+ src/Data/Number/Flint/Fmpz/Mod/Mat/FFI.hsc view
@@ -0,0 +1,588 @@+{-|+module : Data.Number.Flint.Fmpz.Mod.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Mod.Mat.FFI (+ -- * Matrices over integers mod n+ FmpzModMat (..)+ , CFmpzModMat (..)+ -- * Constructors+ , newFmpzModMat+ , withFmpzModMat+ , withNewFmpzModMat+ -- * Element access+ , fmpz_mod_mat_entry+ , fmpz_mod_mat_set_entry+ -- * Memory management+ , fmpz_mod_mat_init+ , fmpz_mod_mat_init_set+ , fmpz_mod_mat_clear+ , fmpz_mod_mat_nrows+ , fmpz_mod_mat_ncols+ , _fmpz_mod_mat_set_mod+ , fmpz_mod_mat_one+ , fmpz_mod_mat_zero+ , fmpz_mod_mat_swap+ , fmpz_mod_mat_swap_entrywise+ , fmpz_mod_mat_is_empty+ , fmpz_mod_mat_is_square+ , _fmpz_mod_mat_reduce+ -- * Random generation+ , fmpz_mod_mat_randtest+ -- * Windows and concatenation+ , fmpz_mod_mat_window_init+ , fmpz_mod_mat_window_clear+ , fmpz_mod_mat_concat_horizontal+ , fmpz_mod_mat_concat_vertical+ -- * Input and output+ , fmpz_mod_mat_print_pretty+ -- * Comparison+ , fmpz_mod_mat_is_zero+ -- * Set and transpose+ , fmpz_mod_mat_set+ , fmpz_mod_mat_transpose+ -- * Conversions+ , fmpz_mod_mat_set_fmpz_mat+ , fmpz_mod_mat_get_fmpz_mat+ -- * Addition and subtraction+ , fmpz_mod_mat_add+ , fmpz_mod_mat_sub+ , fmpz_mod_mat_neg+ -- * Scalar arithmetic+ , fmpz_mod_mat_scalar_mul_si+ , fmpz_mod_mat_scalar_mul_ui+ , fmpz_mod_mat_scalar_mul_fmpz+ -- * Matrix multiplication+ , fmpz_mod_mat_mul+ , _fmpz_mod_mat_mul_classical_threaded_pool_op+ -- , _fmpz_mod_mat_mul_classical_threaded_op+ , fmpz_mod_mat_mul_classical_threaded+ , fmpz_mod_mat_sqr+ , fmpz_mod_mat_mul_fmpz_vec+ , fmpz_mod_mat_fmpz_vec_mul+ -- * Trace+ , fmpz_mod_mat_trace+ -- * Gaussian elimination+ , fmpz_mod_mat_rref+ -- * Strong echelon form and Howell form+ , fmpz_mod_mat_strong_echelon_form+ , fmpz_mod_mat_howell_form+ -- * Inverse+ , fmpz_mod_mat_inv+ -- * LU decomposition+ , fmpz_mod_mat_lu+ -- * Triangular solving+ , fmpz_mod_mat_solve_tril+ , fmpz_mod_mat_solve_triu+ -- * Solving+ , fmpz_mod_mat_solve+ , fmpz_mod_mat_can_solve+ -- * Transforms+ , fmpz_mod_mat_similarity+) where++-- matrices over integers mod n ------------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.ThreadPool++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Mod+import Data.Number.Flint.Fmpq++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpq.h>+#include <flint/fmpz_mod_mat.h>++-- fmpz_mod_mat_t --------------------------------------------------------------++data FmpzModMat = FmpzModMat {-# UNPACK #-} !(ForeignPtr CFmpzModMat)+data CFmpzModMat = CFmpzModMat (Ptr CFmpzMat) (Ptr CFmpz)++instance Storable CFmpzModMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mod_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mod_mat_t}+ peek ptr = CFmpzModMat+ <$> #{peek fmpz_mod_mat_struct, mat} ptr+ <*> #{peek fmpz_mod_mat_struct, mod} ptr+ poke = undefined++newFmpzModMat nrows ncols n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFmpz n $ \n -> + fmpz_mod_mat_init x nrows ncols n+ addForeignPtrFinalizer p_fmpz_mod_mat_clear x+ return $ FmpzModMat x++{-# INLINE withFmpzModMat #-}+withFmpzModMat (FmpzModMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FmpzModMat x,)++{-# INLINE withNewFmpzModMat #-}+withNewFmpzModMat nrows ncols n f =+ newFmpzModMat nrows ncols n >>= flip withFmpzModMat f+ +-- Element access --------------------------------------------------------------++-- | /fmpz_mod_mat_entry/ /mat/ /i/ /j/ +-- +-- Return a reference to the element at row @i@ and column @j@ of @mat@.+fmpz_mod_mat_entry :: Ptr CFmpzModMat -> CLong -> CLong -> IO (Ptr CFmpz)+fmpz_mod_mat_entry mat i j = do+ CFmpzModMat a _ <- peek mat+ fmpz_mat_entry a i j+ +-- | /fmpz_mod_mat_set_entry/ /mat/ /i/ /j/ /val/ +-- +-- Set the entry at row @i@ and column @j@ of @mat@ to @val@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_set_entry"+ fmpz_mod_mat_set_entry :: Ptr CFmpzModMat -> CLong -> CLong -> Ptr CFmpz -> IO ()++-- Memory management -----------------------------------------------------------++-- | /fmpz_mod_mat_init/ /mat/ /rows/ /cols/ /n/ +-- +-- Initialise @mat@ as a matrix with the given number of @rows@ and @cols@+-- and modulus @n@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_init"+ fmpz_mod_mat_init :: Ptr CFmpzModMat -> CLong -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_mat_init_set/ /mat/ /src/ +-- +-- Initialise @mat@ and set it equal to the matrix @src@, including the+-- number of rows and columns and the modulus.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_init_set"+ fmpz_mod_mat_init_set :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_clear/ /mat/ +-- +-- Clear @mat@ and release any memory it used.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_clear"+ fmpz_mod_mat_clear :: Ptr CFmpzModMat -> IO ()++foreign import ccall "fmpz_mod_mat.h &fmpz_mod_mat_clear"+ p_fmpz_mod_mat_clear :: FunPtr (Ptr CFmpzModMat -> IO ())++-- Basic manipulation ----------------------------------------------------------++-- | /fmpz_mod_mat_nrows/ /mat/ +-- +-- Return the number of rows of @mat@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_nrows"+ fmpz_mod_mat_nrows :: Ptr CFmpzModMat -> IO CLong++-- | /fmpz_mod_mat_ncols/ /mat/ +-- +-- Return the number of columns of @mat@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_ncols"+ fmpz_mod_mat_ncols :: Ptr CFmpzModMat -> IO CLong++-- | /_fmpz_mod_mat_set_mod/ /mat/ /n/ +-- +-- Set the modulus of the matrix @mat@ to @n@.+foreign import ccall "fmpz_mod_mat.h _fmpz_mod_mat_set_mod"+ _fmpz_mod_mat_set_mod :: Ptr CFmpzModMat -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_mat_one/ /mat/ +-- +-- Set @mat@ to the identity matrix (ones down the diagonal).+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_one"+ fmpz_mod_mat_one :: Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_zero/ /mat/ +-- +-- Set @mat@ to the zero matrix.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_zero"+ fmpz_mod_mat_zero :: Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_swap/ /mat1/ /mat2/ +-- +-- Efficiently swap the matrices @mat1@ and @mat2@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_swap"+ fmpz_mod_mat_swap :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_swap_entrywise/ /mat1/ /mat2/ +-- +-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_swap_entrywise"+ fmpz_mod_mat_swap_entrywise :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_is_empty/ /mat/ +-- +-- Return \(1\) if @mat@ has either zero rows or columns.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_is_empty"+ fmpz_mod_mat_is_empty :: Ptr CFmpzModMat -> IO CInt++-- | /fmpz_mod_mat_is_square/ /mat/ +-- +-- Return \(1\) if @mat@ has the same number of rows and columns.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_is_square"+ fmpz_mod_mat_is_square :: Ptr CFmpzModMat -> IO CInt++-- | /_fmpz_mod_mat_reduce/ /mat/ +-- +-- Reduce all the entries of @mat@ by the modulus @n@. This function is+-- only needed internally.+foreign import ccall "fmpz_mod_mat.h _fmpz_mod_mat_reduce"+ _fmpz_mod_mat_reduce :: Ptr CFmpzModMat -> IO ()++-- Random generation -----------------------------------------------------------++-- | /fmpz_mod_mat_randtest/ /mat/ /state/ +-- +-- Generate a random matrix with the existing dimensions and entries in+-- \([0, n)\) where @n@ is the modulus.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_randtest"+ fmpz_mod_mat_randtest :: Ptr CFmpzModMat -> Ptr CFRandState -> IO ()++-- Windows and concatenation ---------------------------------------------------++-- | /fmpz_mod_mat_window_init/ /window/ /mat/ /r1/ /c1/ /r2/ /c2/ +-- +-- Initializes the matrix @window@ to be an @r2 - r1@ by @c2 - c1@+-- submatrix of @mat@ whose @(0, 0)@ entry is the @(r1, c1)@ entry of+-- @mat@. The memory for the elements of @window@ is shared with @mat@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_window_init"+ fmpz_mod_mat_window_init :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> CLong -> CLong -> CLong -> CLong -> IO ()++-- | /fmpz_mod_mat_window_clear/ /window/ +-- +-- Clears the matrix @window@ and releases any memory that it uses. Note+-- that the memory to the underlying matrix that @window@ points to is not+-- freed.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_window_clear"+ fmpz_mod_mat_window_clear :: Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_concat_horizontal/ /res/ /mat1/ /mat2/ +-- +-- Sets @res@ to vertical concatenation of (@mat1@, @mat2@) in that order.+-- Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ : \(k \times n\),+-- @res@ : \((m + k) \times n\).+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_concat_horizontal"+ fmpz_mod_mat_concat_horizontal :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_concat_vertical/ /res/ /mat1/ /mat2/ +-- +-- Sets @res@ to horizontal concatenation of (@mat1@, @mat2@) in that+-- order. Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ :+-- \(m \times k\), @res@ : \(m \times (n + k)\).+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_concat_vertical"+ fmpz_mod_mat_concat_vertical :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- Input and output ------------------------------------------------------------++-- | /fmpz_mod_mat_print_pretty/ /mat/ +-- +-- Prints the given matrix to @stdout@. The format is an opening square+-- bracket then on each line a row of the matrix, followed by a closing+-- square bracket. Each row is written as an opening square bracket+-- followed by a space separated list of coefficients followed by a closing+-- square bracket.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_print_pretty"+ fmpz_mod_mat_print_pretty :: Ptr CFmpzModMat -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fmpz_mod_mat_is_zero/ /mat/ +-- +-- Return \(1\) if @mat@ is the zero matrix.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_is_zero"+ fmpz_mod_mat_is_zero :: Ptr CFmpzModMat -> IO CInt++-- Set and transpose -----------------------------------------------------------++-- | /fmpz_mod_mat_set/ /B/ /A/ +-- +-- Set @B@ to equal @A@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_set"+ fmpz_mod_mat_set :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_transpose/ /B/ /A/ +-- +-- Set @B@ to the transpose of @A@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_transpose"+ fmpz_mod_mat_transpose :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- Conversions -----------------------------------------------------------------++-- | /fmpz_mod_mat_set_fmpz_mat/ /A/ /B/ +-- +-- Set @A@ to the matrix @B@ reducing modulo the modulus of @A@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_set_fmpz_mat"+ fmpz_mod_mat_set_fmpz_mat :: Ptr CFmpzModMat -> Ptr CFmpzMat -> IO ()++-- | /fmpz_mod_mat_get_fmpz_mat/ /A/ /B/ +-- +-- Set @A@ to a lift of @B@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_get_fmpz_mat"+ fmpz_mod_mat_get_fmpz_mat :: Ptr CFmpzMat -> Ptr CFmpzModMat -> IO ()++-- Addition and subtraction ----------------------------------------------------++-- | /fmpz_mod_mat_add/ /C/ /A/ /B/ +-- +-- Set @C@ to \(A + B\).+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_add"+ fmpz_mod_mat_add :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_sub/ /C/ /A/ /B/ +-- +-- Set @C@ to \(A - B\).+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_sub"+ fmpz_mod_mat_sub :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_neg/ /B/ /A/ +-- +-- Set @B@ to \(-A\).+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_neg"+ fmpz_mod_mat_neg :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- Scalar arithmetic -----------------------------------------------------------++-- | /fmpz_mod_mat_scalar_mul_si/ /B/ /A/ /c/ +-- +-- Set @B@ to \(cA\) where @c@ is a constant.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_scalar_mul_si"+ fmpz_mod_mat_scalar_mul_si :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> CLong -> IO ()++-- | /fmpz_mod_mat_scalar_mul_ui/ /B/ /A/ /c/ +-- +-- Set @B@ to \(cA\) where @c@ is a constant.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_scalar_mul_ui"+ fmpz_mod_mat_scalar_mul_ui :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> CLong -> IO ()++-- | /fmpz_mod_mat_scalar_mul_fmpz/ /B/ /A/ /c/ +-- +-- Set @B@ to \(cA\) where @c@ is a constant.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_scalar_mul_fmpz"+ fmpz_mod_mat_scalar_mul_fmpz :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpz -> IO ()++-- Matrix multiplication -------------------------------------------------------++-- | /fmpz_mod_mat_mul/ /C/ /A/ /B/ +-- +-- Set @C@ to @A\\times B@. The number of rows of @B@ must match the number+-- of columns of @A@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_mul"+ fmpz_mod_mat_mul :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- | /_fmpz_mod_mat_mul_classical_threaded_pool_op/ /D/ /C/ /A/ /B/ /op/ /threads/ /num_threads/ +-- +-- Set @D@ to @A\\times B + op*C@ where @op@ is @+1@, @-1@ or @0@.+foreign import ccall "fmpz_mod_mat.h _fmpz_mod_mat_mul_classical_threaded_pool_op"+ _fmpz_mod_mat_mul_classical_threaded_pool_op :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> CInt -> Ptr CThreadPoolHandle -> CLong -> IO ()++-- -- | /_fmpz_mod_mat_mul_classical_threaded_op/ /D/ /C/ /A/ /B/ /op/ +-- -- +-- -- Set @D@ to @A\\times B + op*C@ where @op@ is @+1@, @-1@ or @0@.+-- foreign import ccall "fmpz_mod_mat.h _fmpz_mod_mat_mul_classical_threaded_op"+-- _fmpz_mod_mat_mul_classical_threaded_op :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> CInt -> IO ()++-- | /fmpz_mod_mat_mul_classical_threaded/ /C/ /A/ /B/ +-- +-- Set @C@ to @A\\times B@. The number of rows of @B@ must match the number+-- of columns of @A@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_mul_classical_threaded"+ fmpz_mod_mat_mul_classical_threaded :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_sqr/ /B/ /A/ +-- +-- Set @B@ to @A^2@. The matrix @A@ must be square.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_sqr"+ fmpz_mod_mat_sqr :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_mul_fmpz_vec/ /c/ /A/ /b/ /blen/ +-- +-- Compute a matrix-vector product of @A@ and @(b, blen)@ and store the+-- result in @c@. The vector @(b, blen)@ is either truncated or+-- zero-extended to the number of columns of @A@. The number entries+-- written to @c@ is always equal to the number of rows of @A@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_mul_fmpz_vec"+ fmpz_mod_mat_mul_fmpz_vec :: Ptr CFmpz -> Ptr CFmpzModMat -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_mod_mat_fmpz_vec_mul/ /c/ /a/ /alen/ /B/ +-- +-- Compute a vector-matrix product of @(a, alen)@ and @B@ and and store the+-- result in @c@. The vector @(a, alen)@ is either truncated or+-- zero-extended to the number of rows of @B@. The number entries written+-- to @c@ is always equal to the number of columns of @B@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_fmpz_vec_mul"+ fmpz_mod_mat_fmpz_vec_mul :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModMat -> IO ()++-- Trace -----------------------------------------------------------------------++-- | /fmpz_mod_mat_trace/ /trace/ /mat/ +-- +-- Set @trace@ to the trace of the matrix @mat@.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_trace"+ fmpz_mod_mat_trace :: Ptr CFmpz -> Ptr CFmpzModMat -> IO ()++-- Gaussian elimination --------------------------------------------------------++-- | /fmpz_mod_mat_rref/ /perm/ /mat/ +-- +-- Uses Gauss-Jordan elimination to set @mat@ to its reduced row echelon+-- form and returns the rank of @mat@.+-- +-- If @perm@ is non-@NULL@, the permutation of rows in the matrix will also+-- be applied to @perm@.+-- +-- The modulus is assumed to be prime.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_rref"+ fmpz_mod_mat_rref :: Ptr CLong -> Ptr CFmpzModMat -> IO CLong++-- Strong echelon form and Howell form -----------------------------------------++-- | /fmpz_mod_mat_strong_echelon_form/ /mat/ +-- +-- Transforms \(mat\) into the strong echelon form of \(mat\). The Howell+-- form and the strong echelon form are equal up to permutation of the+-- rows, see < [FieHof2014]> for a definition of the strong echelon form+-- and the algorithm used here.+-- +-- \(mat\) must have at least as many rows as columns.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_strong_echelon_form"+ fmpz_mod_mat_strong_echelon_form :: Ptr CFmpzModMat -> IO ()++-- | /fmpz_mod_mat_howell_form/ /mat/ +-- +-- Transforms \(mat\) into the Howell form of \(mat\). For a definition of+-- the Howell form see < [StoMul1998]>. The Howell form is computed by+-- first putting \(mat\) into strong echelon form and then ordering the+-- rows.+-- +-- \(mat\) must have at least as many rows as columns.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_howell_form"+ fmpz_mod_mat_howell_form :: Ptr CFmpzModMat -> IO CLong++-- Inverse ---------------------------------------------------------------------++-- | /fmpz_mod_mat_inv/ /B/ /A/ /ctx/ +-- +-- Sets \(B = A^{-1}\) and returns \(1\) if \(A\) is invertible. If \(A\)+-- is singular, returns \(0\) and sets the elements of \(B\) to undefined+-- values.+-- +-- \(A\) and \(B\) must be square matrices with the same dimensions.+-- +-- The modulus is assumed to be prime.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_inv"+ fmpz_mod_mat_inv :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModCtx -> IO CInt++-- LU decomposition ------------------------------------------------------------++-- | /fmpz_mod_mat_lu/ /P/ /A/ /rank_check/ /ctx/ +-- +-- Computes a generalised LU decomposition \(LU = PA\) of a given matrix+-- \(A\), returning the rank of \(A\).+-- +-- If \(A\) is a nonsingular square matrix, it will be overwritten with a+-- unit diagonal lower triangular matrix \(L\) and an upper triangular+-- matrix \(U\) (the diagonal of \(L\) will not be stored explicitly).+-- +-- If \(A\) is an arbitrary matrix of rank \(r\), \(U\) will be in row+-- echelon form having \(r\) nonzero rows, and \(L\) will be lower+-- triangular but truncated to \(r\) columns, having implicit ones on the+-- \(r\) first entries of the main diagonal. All other entries will be+-- zero.+-- +-- If a nonzero value for @rank_check@ is passed, the function will abandon+-- the output matrix in an undefined state and return 0 if \(A\) is+-- detected to be rank-deficient.+-- +-- The modulus is assumed to be prime.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_lu"+ fmpz_mod_mat_lu :: Ptr CLong -> Ptr CFmpzModMat -> CInt -> Ptr CFmpzModCtx -> IO CLong++-- Triangular solving ----------------------------------------------------------++-- | /fmpz_mod_mat_solve_tril/ /X/ /L/ /B/ /unit/ /ctx/ +-- +-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- Automatically chooses between the classical and recursive algorithms.+-- +-- The modulus is assumed to be prime.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_solve_tril"+ fmpz_mod_mat_solve_tril :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> CInt -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_mat_solve_triu/ /X/ /U/ /B/ /unit/ /ctx/ +-- +-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- Automatically chooses between the classical and recursive algorithms.+-- +-- The modulus is assumed to be prime.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_solve_triu"+ fmpz_mod_mat_solve_triu :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> CInt -> Ptr CFmpzModCtx -> IO ()++-- Solving ---------------------------------------------------------------------++-- | /fmpz_mod_mat_solve/ /X/ /A/ /B/ /ctx/ +-- +-- Solves the matrix-matrix equation \(AX = B\).+-- +-- Returns \(1\) if \(A\) has full rank; otherwise returns \(0\) and sets+-- the elements of \(X\) to undefined values.+-- +-- The matrix \(A\) must be square.+-- +-- The modulus is assumed to be prime.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_solve"+ fmpz_mod_mat_solve :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_mat_can_solve/ /X/ /A/ /B/ /ctx/ +-- +-- Solves the matrix-matrix equation \(AX = B\) over \(Fp\).+-- +-- Returns \(1\) if a solution exists; otherwise returns \(0\) and sets the+-- elements of \(X\) to zero. If more than one solution exists, one of the+-- valid solutions is given.+-- +-- There are no restrictions on the shape of \(A\) and it may be singular.+-- +-- The modulus is assumed to be prime.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_can_solve"+ fmpz_mod_mat_can_solve :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFmpzModCtx -> IO CInt++-- Transforms ------------------------------------------------------------------++-- | /fmpz_mod_mat_similarity/ /M/ /r/ /d/ /ctx/ +-- +-- Applies a similarity transform to the \(n\times n\) matrix \(M\)+-- in-place.+-- +-- If \(P\) is the \(n\times n\) identity matrix the zero entries of whose+-- row \(r\) (0-indexed) have been replaced by \(d\), this transform is+-- equivalent to \(M = P^{-1}MP\).+-- +-- Similarity transforms preserve the determinant, characteristic+-- polynomial and minimal polynomial.+-- +-- The value \(d\) is required to be reduced modulo the modulus of the+-- entries in the matrix.+-- +-- The modulus is assumed to be prime.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_similarity"+ fmpz_mod_mat_similarity :: Ptr CFmpzModMat -> CLong -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()+
+ src/Data/Number/Flint/Fmpz/Mod/Poly.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Mod.Poly (+ module Data.Number.Flint.Fmpz.Mod.Poly.FFI+ ) where++import Data.Number.Flint.Fmpz.Mod.Poly.FFI
+ src/Data/Number/Flint/Fmpz/Mod/Poly/FFI.hsc view
@@ -0,0 +1,2981 @@+{-|+module : Data.Number.Flint.Fmpz.Mod.Poly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Mod.Poly.FFI (+ -- * Polynomials over integers mod n+ FmpzModPoly (..)+ , CFmpzModPoly (..)+ , newFmpzModPoly+ , withFmpzModPoly+ , withNewFmpzModPoly+ -- * Memory management+ , fmpz_mod_poly_init+ , fmpz_mod_poly_init2+ , fmpz_mod_poly_clear+ , fmpz_mod_poly_realloc+ , fmpz_mod_poly_fit_length+ , _fmpz_mod_poly_normalise+ , _fmpz_mod_poly_set_length+ , fmpz_mod_poly_truncate+ , fmpz_mod_poly_set_trunc+ -- * Randomisation+ , fmpz_mod_poly_randtest+ , fmpz_mod_poly_randtest_irreducible+ , fmpz_mod_poly_randtest_not_zero+ , fmpz_mod_poly_randtest_monic+ , fmpz_mod_poly_randtest_monic_irreducible+ , fmpz_mod_poly_randtest_monic_primitive+ , fmpz_mod_poly_randtest_trinomial+ , fmpz_mod_poly_randtest_trinomial_irreducible+ , fmpz_mod_poly_randtest_pentomial+ , fmpz_mod_poly_randtest_pentomial_irreducible+ , fmpz_mod_poly_randtest_sparse_irreducible+ -- * Attributes+ , fmpz_mod_poly_degree+ , fmpz_mod_poly_length+ , fmpz_mod_poly_lead+ -- * Assignment and basic manipulation+ , fmpz_mod_poly_set+ , fmpz_mod_poly_swap+ , fmpz_mod_poly_zero+ , fmpz_mod_poly_one+ , fmpz_mod_poly_zero_coeffs+ , fmpz_mod_poly_reverse+ -- * Conversion+ , fmpz_mod_poly_set_ui+ , fmpz_mod_poly_set_fmpz+ , fmpz_mod_poly_set_fmpz_poly+ , fmpz_mod_poly_get_fmpz_poly+ , fmpz_mod_poly_get_nmod_poly+ , fmpz_mod_poly_set_nmod_poly+ -- * Comparison+ , fmpz_mod_poly_equal+ , fmpz_mod_poly_equal_trunc+ , fmpz_mod_poly_is_zero+ , fmpz_mod_poly_is_one+ , fmpz_mod_poly_is_gen+ -- * Getting and setting coefficients+ , fmpz_mod_poly_set_coeff_fmpz+ , fmpz_mod_poly_set_coeff_ui+ , fmpz_mod_poly_get_coeff_fmpz+ -- , fmpz_mod_poly_set_coeff_mpz+ -- , fmpz_mod_poly_get_coeff_mpz+ -- * Shifting+ , _fmpz_mod_poly_shift_left+ , fmpz_mod_poly_shift_left+ , _fmpz_mod_poly_shift_right+ , fmpz_mod_poly_shift_right+ -- * Addition and subtraction+ , _fmpz_mod_poly_add+ , fmpz_mod_poly_add+ , fmpz_mod_poly_add_series+ , _fmpz_mod_poly_sub+ , fmpz_mod_poly_sub+ , fmpz_mod_poly_sub_series+ , _fmpz_mod_poly_neg+ , fmpz_mod_poly_neg+ -- * Scalar multiplication and division+ , _fmpz_mod_poly_scalar_mul_fmpz+ , fmpz_mod_poly_scalar_mul_fmpz+ , fmpz_mod_poly_scalar_addmul_fmpz+ , _fmpz_mod_poly_scalar_div_fmpz+ , fmpz_mod_poly_scalar_div_fmpz+ -- * Multiplication+ , _fmpz_mod_poly_mul+ , fmpz_mod_poly_mul+ , _fmpz_mod_poly_mullow+ , fmpz_mod_poly_mullow+ , _fmpz_mod_poly_sqr+ , fmpz_mod_poly_sqr+ , fmpz_mod_poly_mulhigh+ , _fmpz_mod_poly_mulmod+ , fmpz_mod_poly_mulmod+ , _fmpz_mod_poly_mulmod_preinv+ , fmpz_mod_poly_mulmod_preinv+ -- * Products+ , _fmpz_mod_poly_product_roots_fmpz_vec+ , fmpz_mod_poly_product_roots_fmpz_vec+ , fmpz_mod_poly_find_distinct_nonzero_roots+ , _fmpz_mod_poly_pow+ , fmpz_mod_poly_pow+ , _fmpz_mod_poly_pow_trunc+ , fmpz_mod_poly_pow_trunc+ , _fmpz_mod_poly_pow_trunc_binexp+ , fmpz_mod_poly_pow_trunc_binexp+ , _fmpz_mod_poly_powmod_ui_binexp+ , fmpz_mod_poly_powmod_ui_binexp+ , _fmpz_mod_poly_powmod_ui_binexp_preinv+ , fmpz_mod_poly_powmod_ui_binexp_preinv+ , _fmpz_mod_poly_powmod_fmpz_binexp+ , fmpz_mod_poly_powmod_fmpz_binexp+ , _fmpz_mod_poly_powmod_fmpz_binexp_preinv+ , fmpz_mod_poly_powmod_fmpz_binexp_preinv+ , _fmpz_mod_poly_powmod_x_fmpz_preinv+ , fmpz_mod_poly_powmod_x_fmpz_preinv+ , _fmpz_mod_poly_powers_mod_preinv_naive+ , fmpz_mod_poly_powers_mod_naive+ , _fmpz_mod_poly_powers_mod_preinv_threaded_pool+ , fmpz_mod_poly_powers_mod_bsgs+ , fmpz_mod_poly_frobenius_powers_2exp_precomp+ , fmpz_mod_poly_frobenius_powers_2exp_clear+ , fmpz_mod_poly_frobenius_power+ , fmpz_mod_poly_frobenius_powers_precomp+ , fmpz_mod_poly_frobenius_powers_clear+ -- * Division+ , _fmpz_mod_poly_divrem_basecase+ , fmpz_mod_poly_divrem_basecase+ , _fmpz_mod_poly_divrem_newton_n_preinv+ , fmpz_mod_poly_divrem_newton_n_preinv+ -- , _fmpz_mod_poly_div_basecase -- deprecated+ -- , fmpz_mod_poly_div_basecase -- deprecated+ -- , _fmpz_mod_poly_div_divconquer_recursive -- deprecated+ -- , _fmpz_mod_poly_div_newton -- deprecated+ -- , fmpz_mod_poly_div_newton -- deprecated+ , _fmpz_mod_poly_div_newton_n_preinv+ , fmpz_mod_poly_div_newton_n_preinv+ , fmpz_mod_poly_remove+ , _fmpz_mod_poly_rem_basecase+ , fmpz_mod_poly_rem_basecase+ -- , _fmpz_mod_poly_divrem_divconquer_recursive -- deprecated+ -- , _fmpz_mod_poly_divrem_divconquer -- deprecated+ -- , _fmpz_mod_poly_div_divconquer -- deprecated+ -- , fmpz_mod_poly_div_divconquer -- deprecated+ -- , fmpz_mod_poly_divrem_divconquer -- deprecated+ , _fmpz_mod_poly_div+ , fmpz_mod_poly_div+ , _fmpz_mod_poly_divrem+ , fmpz_mod_poly_divrem+ , fmpz_mod_poly_divrem_f+ , _fmpz_mod_poly_rem+ -- , _fmpz_mod_poly_rem_f+ -- , fmpz_mod_poly_rem+ -- * Divisibility testing+ , _fmpz_mod_poly_divides_classical+ , fmpz_mod_poly_divides_classical+ , _fmpz_mod_poly_divides+ , fmpz_mod_poly_divides+ -- * Power series inversion+ -- , _fmpz_mod_poly_inv_series_newton+ -- , fmpz_mod_poly_inv_series_newton+ -- , fmpz_mod_poly_inv_series_newton_f+ , _fmpz_mod_poly_inv_series+ , fmpz_mod_poly_inv_series+ , fmpz_mod_poly_inv_series_f+ -- * Power series division+ , _fmpz_mod_poly_div_series+ , fmpz_mod_poly_div_series+ -- * Greatest common divisor+ , fmpz_mod_poly_make_monic+ , fmpz_mod_poly_make_monic_f+ -- , _fmpz_mod_poly_gcd_euclidean+ -- , fmpz_mod_poly_gcd_euclidean+ , _fmpz_mod_poly_gcd+ , fmpz_mod_poly_gcd+ , _fmpz_mod_poly_gcd_euclidean_f+ , fmpz_mod_poly_gcd_euclidean_f+ , _fmpz_mod_poly_gcd_f+ , fmpz_mod_poly_gcd_f+ , _fmpz_mod_poly_hgcd+ -- , _fmpz_mod_poly_gcd_hgcd+ -- , fmpz_mod_poly_gcd_hgcd+ -- , _fmpz_mod_poly_xgcd_euclidean+ , _fmpz_mod_poly_xgcd_euclidean_f+ -- , fmpz_mod_poly_xgcd_euclidean+ , fmpz_mod_poly_xgcd_euclidean_f+ -- , _fmpz_mod_poly_xgcd_hgcd+ -- , fmpz_mod_poly_xgcd_hgcd+ , _fmpz_mod_poly_xgcd+ , fmpz_mod_poly_xgcd+ , fmpz_mod_poly_xgcd_f+ , _fmpz_mod_poly_gcdinv_euclidean+ , fmpz_mod_poly_gcdinv_euclidean+ , _fmpz_mod_poly_gcdinv_euclidean_f+ , fmpz_mod_poly_gcdinv_euclidean_f+ , _fmpz_mod_poly_gcdinv+ , _fmpz_mod_poly_gcdinv_f+ , fmpz_mod_poly_gcdinv+ , fmpz_mod_poly_gcdinv_f+ , _fmpz_mod_poly_invmod+ , _fmpz_mod_poly_invmod_f+ , fmpz_mod_poly_invmod+ , fmpz_mod_poly_invmod_f+ -- * Minpoly+ , _fmpz_mod_poly_minpoly_bm+ , fmpz_mod_poly_minpoly_bm+ , _fmpz_mod_poly_minpoly_hgcd+ , fmpz_mod_poly_minpoly_hgcd+ , _fmpz_mod_poly_minpoly+ , fmpz_mod_poly_minpoly+ -- * Resultant+ , _fmpz_mod_poly_resultant_euclidean+ , fmpz_mod_poly_resultant_euclidean+ , _fmpz_mod_poly_resultant_hgcd+ , fmpz_mod_poly_resultant_hgcd+ , _fmpz_mod_poly_resultant+ , fmpz_mod_poly_resultant+ -- * Discriminant+ , _fmpz_mod_poly_discriminant+ , fmpz_mod_poly_discriminant+ -- * Derivative+ , _fmpz_mod_poly_derivative+ , fmpz_mod_poly_derivative+ -- * Evaluation+ , _fmpz_mod_poly_evaluate_fmpz+ , fmpz_mod_poly_evaluate_fmpz+ -- * Multipoint evaluation+ , _fmpz_mod_poly_evaluate_fmpz_vec_iter+ , fmpz_mod_poly_evaluate_fmpz_vec_iter+ , _fmpz_mod_poly_evaluate_fmpz_vec_fast_precomp+ , _fmpz_mod_poly_evaluate_fmpz_vec_fast+ , fmpz_mod_poly_evaluate_fmpz_vec_fast+ , _fmpz_mod_poly_evaluate_fmpz_vec+ , fmpz_mod_poly_evaluate_fmpz_vec+ -- * Composition+ -- , _fmpz_mod_poly_compose_horner+ -- , fmpz_mod_poly_compose_horner+ --, _fmpz_mod_poly_compose_divconquer+ --, fmpz_mod_poly_compose_divconquer+ , _fmpz_mod_poly_compose+ , fmpz_mod_poly_compose+ -- * Square roots+ , _fmpz_mod_poly_invsqrt_series+ , fmpz_mod_poly_invsqrt_series+ , _fmpz_mod_poly_sqrt_series+ , fmpz_mod_poly_sqrt_series+ , _fmpz_mod_poly_sqrt+ , fmpz_mod_poly_sqrt+ -- * Modular composition+ , _fmpz_mod_poly_compose_mod+ , fmpz_mod_poly_compose_mod+ , _fmpz_mod_poly_compose_mod_horner+ , fmpz_mod_poly_compose_mod_horner+ , _fmpz_mod_poly_compose_mod_brent_kung+ , fmpz_mod_poly_compose_mod_brent_kung+ , _fmpz_mod_poly_reduce_matrix_mod_poly+ , _fmpz_mod_poly_precompute_matrix_worker+ , _fmpz_mod_poly_precompute_matrix+ , fmpz_mod_poly_precompute_matrix+ , _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker+ , _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv+ , fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv+ , _fmpz_mod_poly_compose_mod_brent_kung_preinv+ , fmpz_mod_poly_compose_mod_brent_kung_preinv+ , _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv+ , fmpz_mod_poly_compose_mod_brent_kung_vec_preinv+ , _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool+ , fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool+ , fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded+ -- * Subproduct trees+ , _fmpz_mod_poly_tree_alloc+ , _fmpz_mod_poly_tree_free+ , _fmpz_mod_poly_tree_build+ -- * Radix conversion+ , _fmpz_mod_poly_radix_init+ , fmpz_mod_poly_radix_init+ , _fmpz_mod_poly_radix+ , fmpz_mod_poly_radix+ -- * Input and output+ , _fmpz_mod_poly_fprint+ , fmpz_mod_poly_fprint+ , fmpz_mod_poly_fprint_pretty+ , fmpz_mod_poly_print+ , fmpz_mod_poly_print_pretty+ -- * Inflation and deflation+ , fmpz_mod_poly_inflate+ , fmpz_mod_poly_deflate+ , fmpz_mod_poly_deflation+ -- * Berlekamp-Massey Algorithm+ , fmpz_mod_berlekamp_massey_init+ , fmpz_mod_berlekamp_massey_clear+ , fmpz_mod_berlekamp_massey_start_over+ , fmpz_mod_berlekamp_massey_add_points+ , fmpz_mod_berlekamp_massey_reduce+ , fmpz_mod_berlekamp_massey_point_count+ , fmpz_mod_berlekamp_massey_points+ , fmpz_mod_berlekamp_massey_V_poly+ , fmpz_mod_berlekamp_massey_R_poly+ -- * Characteristic polynomial+ , fmpz_mod_mat_charpoly+ -- * Minimal polynomial+ , fmpz_mod_mat_minpoly+) where ++-- Polynomials over integers mod n ---------------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpz.Mod+import Data.Number.Flint.Fmpz.Mod.Mat+import Data.Number.Flint.NMod.Types+import Data.Number.Flint.ThreadPool++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_mod_poly.h>++-- fmpz_mod_poly_t -------------------------------------------------------------++data FmpzModPoly = FmpzModPoly {-# UNPACK #-} !(ForeignPtr CFmpzModPoly)+data CFmpzModPoly = CFmpzModPoly (Ptr CFmpz) CLong CLong++newFmpzModPoly ctx@(FmpzModCtx mtx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpzModCtx ctx $ \ctx -> do+ fmpz_mod_poly_init x ctx+ addForeignPtrFinalizerEnv p_fmpz_mod_poly_clear x mtx+ return $ FmpzModPoly x++{-# INLINE withFmpzModPoly #-}+withFmpzModPoly (FmpzModPoly x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FmpzModPoly x,)++{-# INLINE withNewFmpzModPoly #-}+withNewFmpzModPoly n f = do+ x <- newFmpzModPoly n+ withFmpzModPoly x $ \x -> f x++instance Storable CFmpzModPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mod_poly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mod_poly_t}+ peek ptr = return CFmpzModPoly + `ap` #{peek fmpz_mod_poly_struct, coeffs} ptr+ `ap` #{peek fmpz_mod_poly_struct, alloc } ptr+ `ap` #{peek fmpz_mod_poly_struct, length} ptr+ poke = error "poke undefined for CFmpzModPoly"+ +-- various other structures ----------------------------------------------------++data FmpzModBerlekampMassey = FmpzModBerlekampMassey {-# UNPACK #-} !(ForeignPtr CFmpzModBerlekampMassey)+type CFmpzModBerlekampMassey = CFlint FmpzModBerlekampMassey++data FmpzModPolyRadix = FmpzModPolyRadix {-# UNPACK #-} !(ForeignPtr CFmpzModPolyRadix)+type CFmpzModPolyRadix = CFlint FmpzModPolyRadix++data FmpzModPolyFrobeniusPowers = FmpzModPolyFrobeniusPowers {-# UNPACK #-} !(ForeignPtr CFmpzModPolyFrobeniusPowers)+type CFmpzModPolyFrobeniusPowers = CFlint FmpzModPolyFrobeniusPowers++data FmpzModPolyFrobeniusPowers2Exp = FmpzModPolyFrobeniusPowers2Exp {-# UNPACK #-} !(ForeignPtr CFmpzModPolyFrobeniusPowers2Exp)+type CFmpzModPolyFrobeniusPowers2Exp = CFlint FmpzModPolyFrobeniusPowers2Exp++-- Memory management -----------------------------------------------------------++-- | /fmpz_mod_poly_init/ /poly/ /ctx/ +-- +-- Initialises @poly@ for use with context @ctx@ and set it to zero. A+-- corresponding call to @fmpz_mod_poly_clear@ must be made to free the+-- memory used by the polynomial.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_init"+ fmpz_mod_poly_init :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_init2/ /poly/ /alloc/ /ctx/ +-- +-- Initialises @poly@ with space for at least @alloc@ coefficients and sets+-- the length to zero. The allocated coefficients are all set to zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_init2"+ fmpz_mod_poly_init2 :: Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_clear/ /poly/ /ctx/ +-- +-- Clears the given polynomial, releasing any memory used. It must be+-- reinitialised in order to be used again.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_clear"+ fmpz_mod_poly_clear :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++foreign import ccall "fmpz_mod_poly.h &fmpz_mod_poly_clear"+ p_fmpz_mod_poly_clear :: FunPtr (Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ())++-- | /fmpz_mod_poly_realloc/ /poly/ /alloc/ /ctx/ +-- +-- Reallocates the given polynomial to have space for @alloc@ coefficients.+-- If @alloc@ is zero the polynomial is cleared and then reinitialised. If+-- the current length is greater than @alloc@ the polynomial is first+-- truncated to length @alloc@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_realloc"+ fmpz_mod_poly_realloc :: Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_fit_length/ /poly/ /len/ /ctx/ +-- +-- If @len@ is greater than the number of coefficients currently allocated,+-- then the polynomial is reallocated to have space for at least @len@+-- coefficients. No data is lost when calling this function.+-- +-- The function efficiently deals with the case where it is called many+-- times in small increments by at least doubling the number of allocated+-- coefficients when length is larger than the number of coefficients+-- currently allocated.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_fit_length"+ fmpz_mod_poly_fit_length :: Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_normalise/ /poly/ +-- +-- Sets the length of @poly@ so that the top coefficient is non-zero. If+-- all coefficients are zero, the length is set to zero. This function is+-- mainly used internally, as all functions guarantee normalisation.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_normalise"+ _fmpz_mod_poly_normalise :: Ptr CFmpzModPoly -> IO ()++-- | /_fmpz_mod_poly_set_length/ /poly/ /len/ +-- +-- Demotes the coefficients of @poly@ beyond @len@ and sets the length of+-- @poly@ to @len@.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_set_length"+ _fmpz_mod_poly_set_length :: Ptr CFmpzModPoly -> CLong -> IO ()++-- | /fmpz_mod_poly_truncate/ /poly/ /len/ /ctx/ +-- +-- If the current length of @poly@ is greater than @len@, it is truncated+-- to have the given length. Discarded coefficients are not necessarily set+-- to zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_truncate"+ fmpz_mod_poly_truncate :: Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_set_trunc/ /res/ /poly/ /n/ /ctx/ +-- +-- Notionally truncate @poly@ to length \(n\) and set @res@ to the result.+-- The result is normalised.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_set_trunc"+ fmpz_mod_poly_set_trunc :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Randomisation ---------------------------------------------------------------++-- | /fmpz_mod_poly_randtest/ /f/ /state/ /len/ /ctx/ +-- +-- Sets the polynomial~\`f\` to a random polynomial of length up~@len@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_randtest"+ fmpz_mod_poly_randtest :: Ptr CFmpzModPoly -> Ptr CFRandState -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_randtest_irreducible/ /f/ /state/ /len/ /ctx/ +-- +-- Sets the polynomial~\`f\` to a random irreducible polynomial of length+-- up~@len@, assuming @len@ is positive.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_randtest_irreducible"+ fmpz_mod_poly_randtest_irreducible :: Ptr CFmpzModPoly -> Ptr CFRandState -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_randtest_not_zero/ /f/ /state/ /len/ /ctx/ +-- +-- Sets the polynomial~\`f\` to a random polynomial of length up~@len@,+-- assuming @len@ is positive.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_randtest_not_zero"+ fmpz_mod_poly_randtest_not_zero :: Ptr CFmpzModPoly -> Ptr CFRandState -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_randtest_monic/ /poly/ /state/ /len/ /ctx/ +-- +-- Generates a random monic polynomial with length @len@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_randtest_monic"+ fmpz_mod_poly_randtest_monic :: Ptr CFmpzModPoly -> Ptr CFRandState -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_randtest_monic_irreducible/ /poly/ /state/ /len/ /ctx/ +-- +-- Generates a random monic irreducible polynomial with length @len@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_randtest_monic_irreducible"+ fmpz_mod_poly_randtest_monic_irreducible :: Ptr CFmpzModPoly -> Ptr CFRandState -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_randtest_monic_primitive/ /poly/ /state/ /len/ /ctx/ +-- +-- Generates a random monic irreducible primitive polynomial with length+-- @len@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_randtest_monic_primitive"+ fmpz_mod_poly_randtest_monic_primitive :: Ptr CFmpzModPoly -> Ptr CFRandState -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_randtest_trinomial/ /poly/ /state/ /len/ /ctx/ +-- +-- Generates a random monic trinomial of length @len@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_randtest_trinomial"+ fmpz_mod_poly_randtest_trinomial :: Ptr CFmpzModPoly -> Ptr CFRandState -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_randtest_trinomial_irreducible/ /poly/ /state/ /len/ /max_attempts/ /ctx/ +-- +-- Attempts to set @poly@ to a monic irreducible trinomial of length @len@.+-- It will generate up to @max_attempts@ trinomials in attempt to find an+-- irreducible one. If @max_attempts@ is @0@, then it will keep generating+-- trinomials until an irreducible one is found. Returns \(1\) if one is+-- found and \(0\) otherwise.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_randtest_trinomial_irreducible"+ fmpz_mod_poly_randtest_trinomial_irreducible :: Ptr CFmpzModPoly -> Ptr CFRandState -> CLong -> CLong -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_randtest_pentomial/ /poly/ /state/ /len/ /ctx/ +-- +-- Generates a random monic pentomial of length @len@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_randtest_pentomial"+ fmpz_mod_poly_randtest_pentomial :: Ptr CFmpzModPoly -> Ptr CFRandState -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_randtest_pentomial_irreducible/ /poly/ /state/ /len/ /max_attempts/ /ctx/ +-- +-- Attempts to set @poly@ to a monic irreducible pentomial of length @len@.+-- It will generate up to @max_attempts@ pentomials in attempt to find an+-- irreducible one. If @max_attempts@ is @0@, then it will keep generating+-- pentomials until an irreducible one is found. Returns \(1\) if one is+-- found and \(0\) otherwise.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_randtest_pentomial_irreducible"+ fmpz_mod_poly_randtest_pentomial_irreducible :: Ptr CFmpzModPoly -> Ptr CFRandState -> CLong -> CLong -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_randtest_sparse_irreducible/ /poly/ /state/ /len/ /ctx/ +-- +-- Attempts to set @poly@ to a sparse, monic irreducible polynomial with+-- length @len@. It attempts to find an irreducible trinomial. If that does+-- not succeed, it attempts to find a irreducible pentomial. If that fails,+-- then @poly@ is just set to a random monic irreducible polynomial.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_randtest_sparse_irreducible"+ fmpz_mod_poly_randtest_sparse_irreducible :: Ptr CFmpzModPoly -> Ptr CFRandState -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Attributes ------------------------------------------------------------------++-- | /fmpz_mod_poly_degree/ /poly/ /ctx/ +-- +-- Returns the degree of the polynomial. The degree of the zero polynomial+-- is defined to be \(-1\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_degree"+ fmpz_mod_poly_degree :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CLong++-- | /fmpz_mod_poly_length/ /poly/ /ctx/ +-- +-- Returns the length of the polynomial, which is one more than its degree.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_length"+ fmpz_mod_poly_length :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CLong++-- | /fmpz_mod_poly_lead/ /poly/ /ctx/ +-- +-- Returns a pointer to the first leading coefficient of @poly@ if this is+-- non-zero, otherwise returns @NULL@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_lead"+ fmpz_mod_poly_lead :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO (Ptr CFmpz)++-- Assignment and basic manipulation -------------------------------------------++-- | /fmpz_mod_poly_set/ /poly1/ /poly2/ /ctx/ +-- +-- Sets the polynomial @poly1@ to the value of @poly2@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_set"+ fmpz_mod_poly_set :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_swap/ /poly1/ /poly2/ /ctx/ +-- +-- Swaps the two polynomials. This is done efficiently by swapping pointers+-- rather than individual coefficients.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_swap"+ fmpz_mod_poly_swap :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_zero/ /poly/ /ctx/ +-- +-- Sets @poly@ to the zero polynomial.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_zero"+ fmpz_mod_poly_zero :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_one/ /poly/ /ctx/ +-- +-- Sets @poly@ to the constant polynomial \(1\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_one"+ fmpz_mod_poly_one :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_zero_coeffs/ /poly/ /i/ /j/ /ctx/ +-- +-- Sets the coefficients of \(X^k\) for \(k \in [i, j)\) in the polynomial+-- to zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_zero_coeffs"+ fmpz_mod_poly_zero_coeffs :: Ptr CFmpzModPoly -> CLong -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_reverse/ /res/ /poly/ /n/ /ctx/ +-- +-- This function considers the polynomial @poly@ to be of length \(n\),+-- notionally truncating and zero padding if required, and reverses the+-- result. Since the function normalises its result @res@ may be of length+-- less than \(n\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_reverse"+ fmpz_mod_poly_reverse :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Conversion ------------------------------------------------------------------++-- | /fmpz_mod_poly_set_ui/ /f/ /c/ /ctx/ +-- +-- Sets the polynomial \(f\) to the constant \(c\) reduced modulo \(p\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_set_ui"+ fmpz_mod_poly_set_ui :: Ptr CFmpzModPoly -> CULong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_set_fmpz/ /f/ /c/ /ctx/ +-- +-- Sets the polynomial \(f\) to the constant \(c\) reduced modulo \(p\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_set_fmpz"+ fmpz_mod_poly_set_fmpz :: Ptr CFmpzModPoly -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_set_fmpz_poly/ /f/ /g/ /ctx/ +-- +-- Sets \(f\) to \(g\) reduced modulo \(p\), where \(p\) is the modulus+-- that is part of the data structure of \(f\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_set_fmpz_poly"+ fmpz_mod_poly_set_fmpz_poly :: Ptr CFmpzModPoly -> Ptr CFmpzPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_get_fmpz_poly/ /f/ /g/ /ctx/ +-- +-- Sets \(f\) to \(g\). This is done simply by lifting the coefficients of+-- \(g\) taking representatives \([0, p) \subset \mathbf{Z}\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_get_fmpz_poly"+ fmpz_mod_poly_get_fmpz_poly :: Ptr CFmpzPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_get_nmod_poly/ /f/ /g/ +-- +-- Sets \(f\) to \(g\) assuming the modulus of both polynomials is the same+-- (no checking is performed).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_get_nmod_poly"+ fmpz_mod_poly_get_nmod_poly :: Ptr CNModPoly -> Ptr CFmpzModPoly -> IO ()++-- | /fmpz_mod_poly_set_nmod_poly/ /f/ /g/ +-- +-- Sets \(f\) to \(g\) assuming the modulus of both polynomials is the same+-- (no checking is performed).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_set_nmod_poly"+ fmpz_mod_poly_set_nmod_poly :: Ptr CFmpzModPoly -> Ptr CNModPoly -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fmpz_mod_poly_equal/ /poly1/ /poly2/ /ctx/ +-- +-- Returns non-zero if the two polynomials are equal, otherwise returns+-- zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_equal"+ fmpz_mod_poly_equal :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_equal_trunc/ /poly1/ /poly2/ /n/ /ctx/ +-- +-- Notionally truncates the two polynomials to length \(n\) and returns+-- non-zero if the two polynomials are equal, otherwise returns zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_equal_trunc"+ fmpz_mod_poly_equal_trunc :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_is_zero/ /poly/ /ctx/ +-- +-- Returns non-zero if the polynomial is zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_is_zero"+ fmpz_mod_poly_is_zero :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_is_one/ /poly/ /ctx/ +-- +-- Returns non-zero if the polynomial is the constant \(1\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_is_one"+ fmpz_mod_poly_is_one :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_is_gen/ /poly/ /ctx/ +-- +-- Returns non-zero if the polynomial is the degree \(1\) polynomial \(x\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_is_gen"+ fmpz_mod_poly_is_gen :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- Getting and setting coefficients --------------------------------------------++-- | /fmpz_mod_poly_set_coeff_fmpz/ /poly/ /n/ /x/ /ctx/ +-- +-- Sets the coefficient of \(X^n\) in the polynomial to \(x\), assuming+-- \(n \geq 0\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_set_coeff_fmpz"+ fmpz_mod_poly_set_coeff_fmpz :: Ptr CFmpzModPoly -> CLong -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_set_coeff_ui/ /poly/ /n/ /x/ /ctx/ +-- +-- Sets the coefficient of \(X^n\) in the polynomial to \(x\), assuming+-- \(n \geq 0\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_set_coeff_ui"+ fmpz_mod_poly_set_coeff_ui :: Ptr CFmpzModPoly -> CLong -> CULong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_get_coeff_fmpz/ /x/ /poly/ /n/ /ctx/ +-- +-- Sets \(x\) to the coefficient of \(X^n\) in the polynomial, assuming+-- \(n \geq 0\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_get_coeff_fmpz"+ fmpz_mod_poly_get_coeff_fmpz :: Ptr CFmpz -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- -- | /fmpz_mod_poly_set_coeff_mpz/ /poly/ /n/ /x/ /ctx/ +-- -- +-- -- Sets the coefficient of \(X^n\) in the polynomial to \(x\), assuming+-- -- \(n \geq 0\).+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_set_coeff_mpz"+-- fmpz_mod_poly_set_coeff_mpz :: Ptr CFmpzModPoly -> CLong -> Ptr CMpz -> Ptr CFmpzModCtx -> IO ()++-- -- | /fmpz_mod_poly_get_coeff_mpz/ /x/ /poly/ /n/ /ctx/ +-- -- +-- -- Sets \(x\) to the coefficient of \(X^n\) in the polynomial, assuming+-- -- \(n \geq 0\).+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_get_coeff_mpz"+-- fmpz_mod_poly_get_coeff_mpz :: Ptr CMpz -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Shifting --------------------------------------------------------------------++-- | /_fmpz_mod_poly_shift_left/ /res/ /poly/ /len/ /n/ /ctx/ +-- +-- Sets @(res, len + n)@ to @(poly, len)@ shifted left by \(n\)+-- coefficients.+-- +-- Inserts zero coefficients at the lower end. Assumes that @len@ and \(n\)+-- are positive, and that @res@ fits @len + n@ elements. Supports aliasing+-- between @res@ and @poly@.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_shift_left"+ _fmpz_mod_poly_shift_left :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_shift_left/ /f/ /g/ /n/ /ctx/ +-- +-- Sets @res@ to @poly@ shifted left by \(n\) coeffs. Zero coefficients are+-- inserted.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_shift_left"+ fmpz_mod_poly_shift_left :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_shift_right/ /res/ /poly/ /len/ /n/ /ctx/ +-- +-- Sets @(res, len - n)@ to @(poly, len)@ shifted right by \(n\)+-- coefficients.+-- +-- Assumes that @len@ and \(n\) are positive, that @len > n@, and that+-- @res@ fits @len - n@ elements. Supports aliasing between @res@ and+-- @poly@, although in this case the top coefficients of @poly@ are not set+-- to zero.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_shift_right"+ _fmpz_mod_poly_shift_right :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_shift_right/ /f/ /g/ /n/ /ctx/ +-- +-- Sets @res@ to @poly@ shifted right by \(n\) coefficients. If \(n\) is+-- equal to or greater than the current length of @poly@, @res@ is set to+-- the zero polynomial.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_shift_right"+ fmpz_mod_poly_shift_right :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Addition and subtraction ----------------------------------------------------++-- | /_fmpz_mod_poly_add/ /res/ /poly1/ /len1/ /poly2/ /len2/ /p/ +-- +-- Sets @res@ to the sum of @(poly1, len1)@ and @(poly2, len2)@. It is+-- assumed that @res@ has sufficient space for the longer of the two+-- polynomials.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_add"+ _fmpz_mod_poly_add :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_add/ /res/ /poly1/ /poly2/ /ctx/ +-- +-- Sets @res@ to the sum of @poly1@ and @poly2@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_add"+ fmpz_mod_poly_add :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_add_series/ /res/ /poly1/ /poly2/ /n/ /ctx/ +-- +-- Notionally truncate @poly1@ and @poly2@ to length \(n\) and set @res@ to+-- the sum.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_add_series"+ fmpz_mod_poly_add_series :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_sub/ /res/ /poly1/ /len1/ /poly2/ /len2/ /p/ +-- +-- Sets @res@ to @(poly1, len1)@ minus @(poly2, len2)@. It is assumed that+-- @res@ has sufficient space for the longer of the two polynomials.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_sub"+ _fmpz_mod_poly_sub :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_sub/ /res/ /poly1/ /poly2/ /ctx/ +-- +-- Sets @res@ to @poly1@ minus @poly2@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_sub"+ fmpz_mod_poly_sub :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_sub_series/ /res/ /poly1/ /poly2/ /n/ /ctx/ +-- +-- Notionally truncate @poly1@ and @poly2@ to length \(n\) and set @res@ to+-- the difference.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_sub_series"+ fmpz_mod_poly_sub_series :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_neg/ /res/ /poly/ /len/ /p/ +-- +-- Sets @(res, len)@ to the negative of @(poly, len)@ modulo \(p\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_neg"+ _fmpz_mod_poly_neg :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_neg/ /res/ /poly/ /ctx/ +-- +-- Sets @res@ to the negative of @poly@ modulo \(p\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_neg"+ fmpz_mod_poly_neg :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- Scalar multiplication and division ------------------------------------------++-- | /_fmpz_mod_poly_scalar_mul_fmpz/ /res/ /poly/ /len/ /x/ /p/ +-- +-- Sets @(res, len@) to @(poly, len)@ multiplied by \(x\), reduced modulo+-- \(p\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_scalar_mul_fmpz"+ _fmpz_mod_poly_scalar_mul_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_scalar_mul_fmpz/ /res/ /poly/ /x/ /ctx/ +-- +-- Sets @res@ to @poly@ multiplied by \(x\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_scalar_mul_fmpz"+ fmpz_mod_poly_scalar_mul_fmpz :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_scalar_addmul_fmpz/ /rop/ /op/ /x/ /ctx/ +-- +-- Adds to @rop@ the product of @op@ by the scalar @x@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_scalar_addmul_fmpz"+ fmpz_mod_poly_scalar_addmul_fmpz :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_scalar_div_fmpz/ /res/ /poly/ /len/ /x/ /p/ +-- +-- Sets @(res, len@) to @(poly, len)@ divided by \(x\) (i.e. multiplied by+-- the inverse of \(x \pmod{p}\)). The result is reduced modulo \(p\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_scalar_div_fmpz"+ _fmpz_mod_poly_scalar_div_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_scalar_div_fmpz/ /res/ /poly/ /x/ /ctx/ +-- +-- Sets @res@ to @poly@ divided by \(x\), (i.e. multiplied by the inverse+-- of \(x \pmod{p}\)). The result is reduced modulo \(p\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_scalar_div_fmpz"+ fmpz_mod_poly_scalar_div_fmpz :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /_fmpz_mod_poly_mul/ /res/ /poly1/ /len1/ /poly2/ /len2/ /p/ +-- +-- Sets @(res, len1 + len2 - 1)@ to the product of @(poly1, len1)@ and+-- @(poly2, len2)@. Assumes @len1 >= len2 > 0@. Allows zero-padding of the+-- two input polynomials.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_mul"+ _fmpz_mod_poly_mul :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_mul/ /res/ /poly1/ /poly2/ /ctx/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_mul"+ fmpz_mod_poly_mul :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_mullow/ /res/ /poly1/ /len1/ /poly2/ /len2/ /p/ /n/ +-- +-- Sets @(res, n)@ to the lowest \(n\) coefficients of the product of+-- @(poly1, len1)@ and @(poly2, len2)@.+-- +-- Assumes @len1 >= len2 > 0@ and @0 \< n \<= len1 + len2 - 1@. Allows for+-- zero-padding in the inputs. Does not support aliasing between the inputs+-- and the output.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_mullow"+ _fmpz_mod_poly_mullow :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_mod_poly_mullow/ /res/ /poly1/ /poly2/ /n/ /ctx/ +-- +-- Sets @res@ to the lowest \(n\) coefficients of the product of @poly1@+-- and @poly2@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_mullow"+ fmpz_mod_poly_mullow :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_sqr/ /res/ /poly/ /len/ /p/ +-- +-- Sets @res@ to the square of @poly@.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_sqr"+ _fmpz_mod_poly_sqr :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_sqr/ /res/ /poly/ /ctx/ +-- +-- Computes @res@ as the square of @poly@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_sqr"+ fmpz_mod_poly_sqr :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_mulhigh/ /res/ /poly1/ /poly2/ /start/ /ctx/ +-- +-- Computes the product of @poly1@ and @poly2@ and writes the coefficients+-- from @start@ onwards into the high coefficients of @res@, the remaining+-- coefficients being arbitrary.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_mulhigh"+ fmpz_mod_poly_mulhigh :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_mulmod/ /res/ /poly1/ /len1/ /poly2/ /len2/ /f/ /lenf/ /p/ +-- +-- Sets @res, len1 + len2 - 1@ to the remainder of the product of @poly1@+-- and @poly2@ upon polynomial division by @f@.+-- +-- It is required that @len1 + len2 - lenf > 0@, which is equivalent to+-- requiring that the result will actually be reduced. Otherwise, simply+-- use @_fmpz_mod_poly_mul@ instead.+-- +-- Aliasing of @f@ and @res@ is not permitted.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_mulmod"+ _fmpz_mod_poly_mulmod :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_mulmod/ /res/ /poly1/ /poly2/ /f/ /ctx/ +-- +-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_mulmod"+ fmpz_mod_poly_mulmod :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_mulmod_preinv/ /res/ /poly1/ /len1/ /poly2/ /len2/ /f/ /lenf/ /finv/ /lenfinv/ /p/ +-- +-- Sets @res, len1 + len2 - 1@ to the remainder of the product of @poly1@+-- and @poly2@ upon polynomial division by @f@.+-- +-- It is required that @finv@ is the inverse of the reverse of @f@ mod+-- @x^lenf@. It is required that @len1 + len2 - lenf > 0@, which is+-- equivalent to requiring that the result will actually be reduced. It is+-- required that @len1 \< lenf@ and @len2 \< lenf@. Otherwise, simply use+-- @_fmpz_mod_poly_mul@ instead.+-- +-- Aliasing of @f@ or @finv@ and @res@ is not permitted.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_mulmod_preinv"+ _fmpz_mod_poly_mulmod_preinv :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_mulmod_preinv/ /res/ /poly1/ /poly2/ /f/ /finv/ /ctx/ +-- +-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@. @finv@ is the inverse of the reverse of @f@.+-- It is required that @poly1@ and @poly2@ are reduced modulo @f@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_mulmod_preinv"+ fmpz_mod_poly_mulmod_preinv :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- Products --------------------------------------------------------------------++-- | /_fmpz_mod_poly_product_roots_fmpz_vec/ /poly/ /xs/ /n/ /f/ +-- +-- Sets @(poly, n + 1)@ to the monic polynomial which is the product of+-- \((x - x_0)(x - x_1) \cdots (x - x_{n-1})\), the roots \(x_i\) being+-- given by @xs@. It is required that the roots are canonical.+-- +-- Aliasing of the input and output is not allowed.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_product_roots_fmpz_vec"+ _fmpz_mod_poly_product_roots_fmpz_vec :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_product_roots_fmpz_vec/ /poly/ /xs/ /n/ /f/ /ctx/ +-- +-- Sets @poly@ to the monic polynomial which is the product of+-- \((x - x_0)(x - x_1) \cdots (x - x_{n-1})\), the roots \(x_i\) being+-- given by @xs@. It is required that the roots are canonical.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_product_roots_fmpz_vec"+ fmpz_mod_poly_product_roots_fmpz_vec :: Ptr CFmpzModPoly -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_find_distinct_nonzero_roots/ /roots/ /A/ /ctx/ +-- +-- If @A@ has \(\deg(A)\) distinct nonzero roots in \(\mathbb{F}_p\), write+-- these roots out to @roots[0]@ to @roots[deg(A) - 1]@ and return @1@.+-- Otherwise, return @0@. It is assumed that @A@ is nonzero and that the+-- modulus of @A@ is prime. This function uses Rabin\'s probabilistic+-- method via gcd\'s with \((x + \delta)^{\frac{p-1}{2}} - 1\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_find_distinct_nonzero_roots"+ fmpz_mod_poly_find_distinct_nonzero_roots :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- Powering+--++++-- | /_fmpz_mod_poly_pow/ /rop/ /op/ /len/ /e/ /p/ +-- +-- Sets @rop = poly^e@, assuming that \(e > 1\) and @elen > 0@, and that+-- @res@ has space for @e*(len - 1) + 1@ coefficients. Does not support+-- aliasing.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_pow"+ _fmpz_mod_poly_pow :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_pow/ /rop/ /op/ /e/ /ctx/ +-- +-- Computes @rop = poly^e@. If \(e\) is zero, returns one, so that in+-- particular @0^0 = 1@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_pow"+ fmpz_mod_poly_pow :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CULong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_pow_trunc/ /res/ /poly/ /e/ /trunc/ /p/ +-- +-- Sets @res@ to the low @trunc@ coefficients of @poly@ (assumed to be zero+-- padded if necessary to length @trunc@) to the power @e@. This is+-- equivalent to doing a powering followed by a truncation. We require that+-- @res@ has enough space for @trunc@ coefficients, that @trunc > 0@ and+-- that @e > 1@. Aliasing is not permitted.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_pow_trunc"+ _fmpz_mod_poly_pow_trunc :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_pow_trunc/ /res/ /poly/ /e/ /trunc/ /ctx/ +-- +-- Sets @res@ to the low @trunc@ coefficients of @poly@ to the power @e@.+-- This is equivalent to doing a powering followed by a truncation.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_pow_trunc"+ fmpz_mod_poly_pow_trunc :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CULong -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_pow_trunc_binexp/ /res/ /poly/ /e/ /trunc/ /p/ +-- +-- Sets @res@ to the low @trunc@ coefficients of @poly@ (assumed to be zero+-- padded if necessary to length @trunc@) to the power @e@. This is+-- equivalent to doing a powering followed by a truncation. We require that+-- @res@ has enough space for @trunc@ coefficients, that @trunc > 0@ and+-- that @e > 1@. Aliasing is not permitted. Uses the binary exponentiation+-- method.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_pow_trunc_binexp"+ _fmpz_mod_poly_pow_trunc_binexp :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_pow_trunc_binexp/ /res/ /poly/ /e/ /trunc/ /ctx/ +-- +-- Sets @res@ to the low @trunc@ coefficients of @poly@ to the power @e@.+-- This is equivalent to doing a powering followed by a truncation. Uses+-- the binary exponentiation method.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_pow_trunc_binexp"+ fmpz_mod_poly_pow_trunc_binexp :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CULong -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_powmod_ui_binexp/ /res/ /poly/ /e/ /f/ /lenf/ /p/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_powmod_ui_binexp"+ _fmpz_mod_poly_powmod_ui_binexp :: Ptr CFmpz -> Ptr CFmpz -> CULong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_powmod_ui_binexp/ /res/ /poly/ /e/ /f/ /ctx/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_powmod_ui_binexp"+ fmpz_mod_poly_powmod_ui_binexp :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CULong -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_powmod_ui_binexp_preinv/ /res/ /poly/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /p/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_powmod_ui_binexp_preinv"+ _fmpz_mod_poly_powmod_ui_binexp_preinv :: Ptr CFmpz -> Ptr CFmpz -> CULong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_powmod_ui_binexp_preinv/ /res/ /poly/ /e/ /f/ /finv/ /ctx/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_powmod_ui_binexp_preinv"+ fmpz_mod_poly_powmod_ui_binexp_preinv :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CULong -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_powmod_fmpz_binexp/ /res/ /poly/ /e/ /f/ /lenf/ /p/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_powmod_fmpz_binexp"+ _fmpz_mod_poly_powmod_fmpz_binexp :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_powmod_fmpz_binexp/ /res/ /poly/ /e/ /f/ /ctx/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_powmod_fmpz_binexp"+ fmpz_mod_poly_powmod_fmpz_binexp :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_powmod_fmpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /p/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_powmod_fmpz_binexp_preinv"+ _fmpz_mod_poly_powmod_fmpz_binexp_preinv :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_powmod_fmpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /finv/ /ctx/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_powmod_fmpz_binexp_preinv"+ fmpz_mod_poly_powmod_fmpz_binexp_preinv :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_powmod_x_fmpz_preinv/ /res/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /p/ +-- +-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e > 0@. We require @finv@ to be the+-- inverse of the reverse of @f@.+-- +-- We require @lenf > 2@. The output @res@ must have room for @lenf - 1@+-- coefficients.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_powmod_x_fmpz_preinv"+ _fmpz_mod_poly_powmod_x_fmpz_preinv :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_powmod_x_fmpz_preinv/ /res/ /e/ /f/ /finv/ /ctx/ +-- +-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e >= 0@. We require @finv@ to be the+-- inverse of the reverse of \`\`+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_powmod_x_fmpz_preinv"+ fmpz_mod_poly_powmod_x_fmpz_preinv :: Ptr CFmpzModPoly -> Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_powers_mod_preinv_naive/ /res/ /f/ /flen/ /n/ /g/ /glen/ /ginv/ /ginvlen/ /p/ +-- +-- Compute @f^0, f^1, ..., f^(n-1) mod g@, where @g@ has length @glen@ and+-- @f@ is reduced mod @g@ and has length @flen@ (possibly zero spaced).+-- Assumes @res@ is an array of @n@ arrays each with space for at least+-- @glen - 1@ coefficients and that @flen > 0@. We require that @ginv@ of+-- length @ginvlen@ is set to the power series inverse of the reverse of+-- @g@.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_powers_mod_preinv_naive"+ _fmpz_mod_poly_powers_mod_preinv_naive :: Ptr (Ptr CFmpz) -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_powers_mod_naive/ /res/ /f/ /n/ /g/ /ctx/ +-- +-- Set the entries of the array @res@ to @f^0, f^1, ..., f^(n-1) mod g@. No+-- aliasing is permitted between the entries of @res@ and either of the+-- inputs.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_powers_mod_naive"+ fmpz_mod_poly_powers_mod_naive :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_powers_mod_preinv_threaded_pool/ /res/ /f/ /flen/ /n/ /g/ /glen/ /ginv/ /ginvlen/ /p/ /threads/ /num_threads/ +-- +-- Compute @f^0, f^1, ..., f^(n-1) mod g@, where @g@ has length @glen@ and+-- @f@ is reduced mod @g@ and has length @flen@ (possibly zero spaced).+-- Assumes @res@ is an array of @n@ arrays each with space for at least+-- @glen - 1@ coefficients and that @flen > 0@. We require that @ginv@ of+-- length @ginvlen@ is set to the power series inverse of the reverse of+-- @g@.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_powers_mod_preinv_threaded_pool"+ _fmpz_mod_poly_powers_mod_preinv_threaded_pool :: Ptr (Ptr CFmpz) -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CThreadPoolHandle -> CLong -> IO ()++-- | /fmpz_mod_poly_powers_mod_bsgs/ /res/ /f/ /n/ /g/ /ctx/ +-- +-- Set the entries of the array @res@ to @f^0, f^1, ..., f^(n-1) mod g@. No+-- aliasing is permitted between the entries of @res@ and either of the+-- inputs.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_powers_mod_bsgs"+ fmpz_mod_poly_powers_mod_bsgs :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_frobenius_powers_2exp_precomp/ /pow/ /f/ /finv/ /m/ /ctx/ +-- +-- If @p = f->p@, compute \(x^{(p^1)}\), \(x^{(p^2)}\), \(x^{(p^4)}\), ...,+-- \(x^{(p^{(2^l)})} \pmod{f}\) where \(2^l\) is the greatest power of+-- \(2\) less than or equal to \(m\).+-- +-- Allows construction of \(x^{(p^k)}\) for \(k = 0\), \(1\), ...,+-- \(x^{(p^m)} \pmod{f}\) using @fmpz_mod_poly_frobenius_power@.+-- +-- Requires precomputed inverse of \(f\), i.e. newton inverse.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_frobenius_powers_2exp_precomp"+ fmpz_mod_poly_frobenius_powers_2exp_precomp :: Ptr CFmpzModPolyFrobeniusPowers2Exp -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CULong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_frobenius_powers_2exp_clear/ /pow/ /ctx/ +-- +-- Clear resources used by the @fmpz_mod_poly_frobenius_powers_2exp_t@+-- struct.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_frobenius_powers_2exp_clear"+ fmpz_mod_poly_frobenius_powers_2exp_clear :: Ptr CFmpzModPolyFrobeniusPowers2Exp -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_frobenius_power/ /res/ /pow/ /f/ /m/ /ctx/ +-- +-- If @p = f->p@, compute \(x^{(p^m)} \pmod{f}\).+-- +-- Requires precomputed frobenius powers supplied by+-- @fmpz_mod_poly_frobenius_powers_2exp_precomp@.+-- +-- If \(m == 0\) and \(f\) has degree \(0\) or \(1\), this performs a+-- division. However an impossible inverse by the leading coefficient of+-- \(f\) will have been caught by+-- @fmpz_mod_poly_frobenius_powers_2exp_precomp@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_frobenius_power"+ fmpz_mod_poly_frobenius_power :: Ptr CFmpzModPoly -> Ptr CFmpzModPolyFrobeniusPowers2Exp -> Ptr CFmpzModPoly -> CULong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_frobenius_powers_precomp/ /pow/ /f/ /finv/ /m/ /ctx/ +-- +-- If @p = f->p@, compute \(x^{(p^0)}\), \(x^{(p^1)}\), \(x^{(p^2)}\),+-- \(x^{(p^3)}\), ..., \(x^{(p^m)} \pmod{f}\).+-- +-- Requires precomputed inverse of \(f\), i.e. newton inverse.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_frobenius_powers_precomp"+ fmpz_mod_poly_frobenius_powers_precomp :: Ptr CFmpzModPolyFrobeniusPowers -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CULong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_frobenius_powers_clear/ /pow/ /ctx/ +-- +-- Clear resources used by the @fmpz_mod_poly_frobenius_powers_t@ struct.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_frobenius_powers_clear"+ fmpz_mod_poly_frobenius_powers_clear :: Ptr CFmpzModPolyFrobeniusPowers -> Ptr CFmpzModCtx -> IO ()++-- Division --------------------------------------------------------------------++-- | /_fmpz_mod_poly_divrem_basecase/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- +-- Computes @(Q, lenA - lenB + 1)@, @(R, lenA)@ such that \(A = B Q + R\)+-- with \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- Assumes that the leading coefficient of \(B\) is invertible modulo+-- \(p\), and that @invB@ is the inverse.+-- +-- Assumes that \(\operatorname{len}(A), \operatorname{len}(B) > 0\).+-- Allows zero-padding in @(A, lenA)@. \(R\) and \(A\) may be aliased, but+-- apart from this no aliasing of input and output operands is allowed.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_divrem_basecase"+ _fmpz_mod_poly_divrem_basecase :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_divrem_basecase/ /Q/ /R/ /A/ /B/ /ctx/ +-- +-- Computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- Assumes that the leading coefficient of \(B\) is invertible modulo+-- \(p\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_divrem_basecase"+ fmpz_mod_poly_divrem_basecase :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_divrem_newton_n_preinv/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /Binv/ /lenBinv/ /mod/ +-- +-- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R)\) less than @lenB@, where \(A\) is of length+-- @lenA@ and \(B\) is of length @lenB@. We require that \(Q\) have space+-- for @lenA - lenB + 1@ coefficients. Furthermore, we assume that \(Binv\)+-- is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\). The algorithm used is to call+-- @div_newton_n_preinv@ and then multiply out and compute the remainder.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_divrem_newton_n_preinv"+ _fmpz_mod_poly_divrem_newton_n_preinv :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_divrem_newton_n_preinv/ /Q/ /R/ /A/ /B/ /Binv/ /ctx/ +-- +-- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R) < \operatorname{len}(B)\). We assume \(Binv\) is+-- the inverse of the reverse of \(B\) mod \(x^{\operatorname{len}(B)}\).+-- +-- It is required that the length of \(A\) is less than or equal to 2*the+-- length of \(B\) - 2.+-- +-- The algorithm used is to call @div_newton_n@ and then multiply out and+-- compute the remainder.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_divrem_newton_n_preinv"+ fmpz_mod_poly_divrem_newton_n_preinv :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- -- | /_fmpz_mod_poly_div_basecase/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- -- +-- -- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- -- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\) but only sets+-- -- @(Q, lenA - lenB + 1)@.+-- -- +-- -- Requires temporary space @(R, lenA)@. Allows aliasing only between \(A\)+-- -- and \(R\). Allows zero-padding in \(A\) but not in \(B\). Assumes that+-- -- the leading coefficient of \(B\) is a unit modulo \(p\).+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_div_basecase"+-- _fmpz_mod_poly_div_basecase :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- -- | /fmpz_mod_poly_div_basecase/ /Q/ /A/ /B/ /ctx/ +-- -- +-- -- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- -- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\) assuming that+-- -- the leading term of \(B\) is a unit.+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_div_basecase"+-- fmpz_mod_poly_div_basecase :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- -- | /_fmpz_mod_poly_div_divconquer_recursive/ /Q/ /W/ /A/ /B/ /lenB/ /invB/ /p/ +-- -- +-- -- [Computes \(Q\) and \(R\) such that \(A = BQ + R\) with \(\operatorname{len}(R)\) less than]+-- -- @lenB@, where @A@ is of length @2 * lenB - 1@ and @B@ is of length+-- -- @lenB@. We require that @Q@ have space for @lenB@ coefficients and+-- -- that @W@ be temporary space of size @2*lenB@.+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_div_divconquer_recursive"+-- _fmpz_mod_poly_div_divconquer_recursive :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- -- | /_fmpz_mod_poly_div_newton/ /Q/ /A/ /lenA/ /B/ /lenB/ /p/ +-- -- +-- -- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- -- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\) but only sets+-- -- @(Q, lenA - lenB + 1)@.+-- -- +-- -- Assumes that the leading coefficient of \(B\) is a unit modulo \(p\).+-- -- +-- -- Reverses the polynomials, divides the resulting series using Newton+-- -- iteration, then reverses the result.+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_div_newton"+-- _fmpz_mod_poly_div_newton :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- -- | /fmpz_mod_poly_div_newton/ /Q/ /A/ /B/ /ctx/ +-- -- +-- -- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- -- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\) assuming that+-- -- the leading term of \(B\) is a unit.+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_div_newton"+-- fmpz_mod_poly_div_newton :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_div_newton_n_preinv/ /Q/ /A/ /lenA/ /B/ /lenB/ /Binv/ /lenBinv/ /mod/ +-- +-- Notionally computes polynomials \(Q\) and \(R\) such that \(A = BQ + R\)+-- with \(\operatorname{len}(R)\) less than @lenB@, where @A@ is of length+-- @lenA@ and @B@ is of length @lenB@, but return only \(Q\).+-- +-- We require that \(Q\) have space for @lenA - lenB + 1@ coefficients and+-- assume that the leading coefficient of \(B\) is a unit. Furthermore, we+-- assume that \(Binv\) is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\).+-- +-- The algorithm used is to reverse the polynomials and divide the+-- resulting power series, then reverse the result.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_div_newton_n_preinv"+ _fmpz_mod_poly_div_newton_n_preinv :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_div_newton_n_preinv/ /Q/ /A/ /B/ /Binv/ /ctx/ +-- +-- Notionally computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R) < \operatorname{len}(B)\), but returns only+-- \(Q\).+-- +-- We assume that the leading coefficient of \(B\) is a unit and that+-- \(Binv\) is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\).+-- +-- It is required that the length of \(A\) is less than or equal to 2*the+-- length of \(B\) - 2.+-- +-- The algorithm used is to reverse the polynomials and divide the+-- resulting power series, then reverse the result.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_div_newton_n_preinv"+ fmpz_mod_poly_div_newton_n_preinv :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_remove/ /f/ /g/ /ctx/ +-- +-- Removes the highest possible power of @g@ from @f@ and returns the+-- exponent.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_remove"+ fmpz_mod_poly_remove :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CULong++-- | /_fmpz_mod_poly_rem_basecase/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\) but only sets+-- @(R, lenB - 1)@.+-- +-- Allows aliasing only between \(A\) and \(R\). Allows zero-padding in+-- \(A\) but not in \(B\). Assumes that the leading coefficient of \(B\) is+-- a unit modulo \(p\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_rem_basecase"+ _fmpz_mod_poly_rem_basecase :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_rem_basecase/ /R/ /A/ /B/ /ctx/ +-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\) assuming that+-- the leading term of \(B\) is a unit.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_rem_basecase"+ fmpz_mod_poly_rem_basecase :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- -- | /_fmpz_mod_poly_divrem_divconquer_recursive/ /Q/ /BQ/ /W/ /A/ /B/ /lenB/ /invB/ /p/ +-- -- +-- -- Computes @(Q, lenB)@, @(BQ, 2 lenB - 1)@ such that \(BQ = B \times Q\)+-- -- and \(A = B Q + R\) where+-- -- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- -- +-- -- Assumes that the leading coefficient of \(B\) is invertible modulo+-- -- \(p\), and that @invB@ is the inverse.+-- -- +-- -- Assumes \(\operatorname{len}(B) > 0\). Allows zero-padding in+-- -- @(A, lenA)@. Requires a temporary array @(W, 2 lenB - 1)@. No aliasing+-- -- of input and output operands is allowed.+-- -- +-- -- This function does not read the bottom \(\operatorname{len}(B) - 1\)+-- -- coefficients from \(A\), which means that they might not even need to+-- -- exist in allocated memory.+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_divrem_divconquer_recursive"+-- _fmpz_mod_poly_divrem_divconquer_recursive :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- -- | /_fmpz_mod_poly_divrem_divconquer/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- -- +-- -- Computes @(Q, lenA - lenB + 1)@, @(R, lenB - 1)@ such that+-- -- \(A = B Q + R\) and+-- -- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- -- +-- -- Assumes that the leading coefficient of \(B\) is invertible modulo+-- -- \(p\), and that @invB@ is the inverse.+-- -- +-- -- Assumes \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\). Allows+-- -- zero-padding in @(A, lenA)@. No aliasing of input and output operands is+-- -- allowed.+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_divrem_divconquer"+-- _fmpz_mod_poly_divrem_divconquer :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- -- | /_fmpz_mod_poly_div_divconquer/ /Q/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- -- +-- -- Notionally computes polynomials \(Q\) and \(R\) such that \(A = BQ + R\)+-- -- with \(\operatorname{len}(R)\) less than @lenB@, where @A@ is of length+-- -- @lenA@ and @B@ is of length @lenB@, but returns only @Q@. We require+-- -- that @Q@ have space for @lenA - lenB + 1@ coefficients.+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_div_divconquer"+-- _fmpz_mod_poly_div_divconquer :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- -- | /fmpz_mod_poly_div_divconquer/ /Q/ /A/ /B/ /ctx/ +-- -- +-- -- Notionally computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- -- \(\operatorname{len}(R) < \operatorname{len}(B)\), but returns only+-- -- \(Q\).+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_div_divconquer"+-- fmpz_mod_poly_div_divconquer :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- -- | /fmpz_mod_poly_divrem_divconquer/ /Q/ /R/ /A/ /B/ /ctx/ +-- -- +-- -- Computes \(Q\), \(R\) such that \(A = B Q + R\) and+-- -- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- -- +-- -- Assumes that \(B\) is non-zero and that the leading coefficient of \(B\)+-- -- is invertible modulo \(p\).+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_divrem_divconquer"+-- fmpz_mod_poly_divrem_divconquer :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_div/ /Q/ /A/ /lenA/ /B/ /lenB/ /p/ +-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\) but only sets+-- @(Q, lenA - lenB + 1)@.+-- +-- Assumes that the leading coefficient of \(B\) is a unit modulo \(p\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_div"+ _fmpz_mod_poly_div :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_div/ /Q/ /A/ /B/ /ctx/ +-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\) assuming that+-- the leading term of \(B\) is a unit.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_div"+ fmpz_mod_poly_div :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_divrem/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- +-- Computes @(Q, lenA - lenB + 1)@, @(R, lenB - 1)@ such that+-- \(A = B Q + R\) and+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- Assumes that \(B\) is non-zero, that the leading coefficient of \(B\) is+-- invertible modulo \(p\) and that @invB@ is the inverse.+-- +-- Assumes \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\). Allows+-- zero-padding in @(A, lenA)@. No aliasing of input and output operands is+-- allowed.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_divrem"+ _fmpz_mod_poly_divrem :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_divrem/ /Q/ /R/ /A/ /B/ /ctx/ +-- +-- Computes \(Q\), \(R\) such that \(A = B Q + R\) and+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- Assumes that \(B\) is non-zero and that the leading coefficient of \(B\)+-- is invertible modulo \(p\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_divrem"+ fmpz_mod_poly_divrem :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_divrem_f/ /f/ /Q/ /R/ /A/ /B/ /ctx/ +-- +-- Either finds a non-trivial factor~\`f\` of the modulus~\`p\`, or+-- computes \(Q\), \(R\) such that \(A = B Q + R\) and+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- If the leading coefficient of \(B\) is invertible in \(\mathbf{Z}/(p)\),+-- the division with remainder operation is carried out, \(Q\) and \(R\)+-- are computed correctly, and \(f\) is set to \(1\). Otherwise, \(f\) is+-- set to a non-trivial factor of \(p\) and \(Q\) and \(R\) are not+-- touched.+-- +-- Assumes that \(B\) is non-zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_divrem_f"+ fmpz_mod_poly_divrem_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_rem/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- +-- Notationally, computes @(Q, lenA - lenB + 1)@, @(R, lenB - 1)@ such that+-- \(A = B Q + R\) and+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\), returning only+-- the remainder part.+-- +-- Assumes that \(B\) is non-zero, that the leading coefficient of \(B\) is+-- invertible modulo \(p\) and that @invB@ is the inverse.+-- +-- Assumes \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\). Allows+-- zero-padding in @(A, lenA)@. No aliasing of input and output operands is+-- allowed.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_rem"+ _fmpz_mod_poly_rem :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- -- | /_fmpz_mod_poly_rem_f/ /f/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- -- +-- -- If \(f\) returns with the value \(1\) then the function operates as+-- -- @_fmpz_mod_poly_rem@, otherwise \(f\) will be set to a nontrivial factor+-- -- of \(p\).+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_rem_f"+-- _fmpz_mod_poly_rem_f :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- -- | /fmpz_mod_poly_rem/ /R/ /A/ /B/ /ctx/ +-- -- +-- -- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) and+-- -- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\), returning only+-- -- the remainder part.+-- -- +-- -- Assumes that \(B\) is non-zero and that the leading coefficient of \(B\)+-- -- is invertible modulo \(p\).+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_rem"+-- fmpz_mod_poly_rem :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- Divisibility testing --------------------------------------------------------++-- | /_fmpz_mod_poly_divides_classical/ /Q/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Returns \(1\) if \((B, lenB)\) divides \((A, lenA)\) and sets+-- \((Q, lenA - lenB + 1)\) to the quotient. Otherwise, returns \(0\) and+-- sets \((Q, lenA - lenB + 1)\) to zero. We require that+-- \(lenA >= lenB > 0\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_divides_classical"+ _fmpz_mod_poly_divides_classical :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_divides_classical/ /Q/ /A/ /B/ /ctx/ +-- +-- Returns \(1\) if \(B\) divides \(A\) and sets \(Q\) to the quotient.+-- Otherwise returns \(0\) and sets \(Q\) to zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_divides_classical"+ fmpz_mod_poly_divides_classical :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /_fmpz_mod_poly_divides/ /Q/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Returns \(1\) if \((B, lenB)\) divides \((A, lenA)\) and sets+-- \((Q, lenA - lenB + 1)\) to the quotient. Otherwise, returns \(0\) and+-- sets \((Q, lenA - lenB + 1)\) to zero. We require that+-- \(lenA >= lenB > 0\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_divides"+ _fmpz_mod_poly_divides :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_divides/ /Q/ /A/ /B/ /ctx/ +-- +-- Returns \(1\) if \(B\) divides \(A\) and sets \(Q\) to the quotient.+-- Otherwise returns \(0\) and sets \(Q\) to zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_divides"+ fmpz_mod_poly_divides :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- Power series inversion ------------------------------------------------------++-- -- | /_fmpz_mod_poly_inv_series_newton/ /Qinv/ /Q/ /n/ /cinv/ /p/ +-- -- +-- -- Sets @(Qinv, n)@ to the inverse of @(Q, n)@ modulo \(x^n\), where+-- -- \(n \geq 1\), assuming that the bottom coefficient of \(Q\) is+-- -- invertible modulo \(p\) and that its inverse is @cinv@.+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_inv_series_newton"+-- _fmpz_mod_poly_inv_series_newton :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- -- | /fmpz_mod_poly_inv_series_newton/ /Qinv/ /Q/ /n/ /ctx/ +-- -- +-- -- Sets @Qinv@ to the inverse of @Q@ modulo \(x^n\), where \(n \geq 1\),+-- -- assuming that the bottom coefficient of \(Q\) is a unit.+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_inv_series_newton"+-- fmpz_mod_poly_inv_series_newton :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- -- | /fmpz_mod_poly_inv_series_newton_f/ /f/ /Qinv/ /Q/ /n/ /ctx/ +-- -- +-- -- Either sets \(f\) to a nontrivial factor of \(p\) with the value of+-- -- @Qinv@ undefined, or sets @Qinv@ to the inverse of @Q@ modulo \(x^n\),+-- -- where \(n \geq 1\).+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_inv_series_newton_f"+-- fmpz_mod_poly_inv_series_newton_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_inv_series/ /Qinv/ /Q/ /n/ /cinv/ /p/ +-- +-- Sets @(Qinv, n)@ to the inverse of @(Q, n)@ modulo \(x^n\), where+-- \(n \geq 1\), assuming that the bottom coefficient of \(Q\) is+-- invertible modulo \(p\) and that its inverse is @cinv@.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_inv_series"+ _fmpz_mod_poly_inv_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_inv_series/ /Qinv/ /Q/ /n/ /ctx/ +-- +-- Sets @Qinv@ to the inverse of @Q@ modulo \(x^n\), where \(n \geq 1\),+-- assuming that the bottom coefficient of \(Q\) is a unit.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_inv_series"+ fmpz_mod_poly_inv_series :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_inv_series_f/ /f/ /Qinv/ /Q/ /n/ /ctx/ +-- +-- Either sets \(f\) to a nontrivial factor of \(p\) with the value of+-- @Qinv@ undefined, or sets @Qinv@ to the inverse of @Q@ modulo \(x^n\),+-- where \(n \geq 1\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_inv_series_f"+ fmpz_mod_poly_inv_series_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Power series division -------------------------------------------------------++-- | /_fmpz_mod_poly_div_series/ /Q/ /A/ /Alen/ /B/ /Blen/ /p/ /n/ +-- +-- Set @(Q, n)@ to the quotient of the series @(A, Alen@) and @(B, Blen)@+-- assuming @Alen, Blen \<= n@. We assume the bottom coefficient of @B@ is+-- invertible modulo \(p\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_div_series"+ _fmpz_mod_poly_div_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_mod_poly_div_series/ /Q/ /A/ /B/ /n/ /ctx/ +-- +-- Set \(Q\) to the quotient of the series \(A\) by \(B\), thinking of the+-- series as though they were of length \(n\). We assume that the bottom+-- coefficient of \(B\) is a unit.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_div_series"+ fmpz_mod_poly_div_series :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Greatest common divisor -----------------------------------------------------++-- | /fmpz_mod_poly_make_monic/ /res/ /poly/ /ctx/ +-- +-- If @poly@ is non-zero, sets @res@ to @poly@ divided by its leading+-- coefficient. This assumes that the leading coefficient of @poly@ is+-- invertible modulo \(p\).+-- +-- Otherwise, if @poly@ is zero, sets @res@ to zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_make_monic"+ fmpz_mod_poly_make_monic :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_make_monic_f/ /f/ /res/ /poly/ /ctx/ +-- +-- Either set \(f\) to \(1\) and @res@ to @poly@ divided by its leading+-- coefficient or set \(f\) to a nontrivial factor of \(p\) and leave @res@+-- undefined.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_make_monic_f"+ fmpz_mod_poly_make_monic_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- -- | /_fmpz_mod_poly_gcd_euclidean/ /G/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- -- +-- -- Sets \(G\) to the greatest common divisor of+-- -- \((A, \operatorname{len}(A))\) and \((B, \operatorname{len}(B))\) and+-- -- returns its length.+-- -- +-- -- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\)+-- -- and that the vector \(G\) has space for sufficiently many coefficients.+-- -- +-- -- Assumes that @invB@ is the inverse of the leading coefficients of \(B\)+-- -- modulo the prime number \(p\).+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_gcd_euclidean"+-- _fmpz_mod_poly_gcd_euclidean :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO CLong++-- -- | /fmpz_mod_poly_gcd_euclidean/ /G/ /A/ /B/ /ctx/ +-- -- +-- -- Sets \(G\) to the greatest common divisor of \(A\) and \(B\).+-- -- +-- -- The algorithm used to compute \(G\) is the classical Euclidean+-- -- algorithm.+-- -- +-- -- In general, the greatest common divisor is defined in the polynomial+-- -- ring \((\mathbf{Z}/(p \mathbf{Z}))[X]\) if and only if \(p\) is a prime+-- -- number. Thus, this function assumes that \(p\) is prime.+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_gcd_euclidean"+-- fmpz_mod_poly_gcd_euclidean :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_gcd/ /G/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- +-- Sets \(G\) to the greatest common divisor of+-- \((A, \operatorname{len}(A))\) and \((B, \operatorname{len}(B))\) and+-- returns its length.+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\)+-- and that the vector \(G\) has space for sufficiently many coefficients.+-- +-- Assumes that @invB@ is the inverse of the leading coefficients of \(B\)+-- modulo the prime number \(p\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_gcd"+ _fmpz_mod_poly_gcd :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO CLong++-- | /fmpz_mod_poly_gcd/ /G/ /A/ /B/ /ctx/ +-- +-- Sets \(G\) to the greatest common divisor of \(A\) and \(B\).+-- +-- In general, the greatest common divisor is defined in the polynomial+-- ring \((\mathbf{Z}/(p \mathbf{Z}))[X]\) if and only if \(p\) is a prime+-- number. Thus, this function assumes that \(p\) is prime.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_gcd"+ fmpz_mod_poly_gcd :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_gcd_euclidean_f/ /f/ /G/ /A/ /lenA/ /B/ /lenB/ /p/ +-- +-- Either sets \(f = 1\) and \(G\) to the greatest common divisor of+-- \((A, \operatorname{len}(A))\) and \((B, \operatorname{len}(B))\) and+-- returns its length, or sets \(f \in (1,p)\) to a non-trivial factor of+-- \(p\) and leaves the contents of the vector \((G, lenB)\) undefined.+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\)+-- and that the vector \(G\) has space for sufficiently many coefficients.+-- +-- Does not support aliasing of any of the input arguments with any of the+-- output argument.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_gcd_euclidean_f"+ _fmpz_mod_poly_gcd_euclidean_f :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- | /fmpz_mod_poly_gcd_euclidean_f/ /f/ /G/ /A/ /B/ /ctx/ +-- +-- Either sets \(f = 1\) and \(G\) to the greatest common divisor of \(A\)+-- and \(B\), or \( \in (1,p)\) to a non-trivial factor of \(p\).+-- +-- In general, the greatest common divisor is defined in the polynomial+-- ring \((\mathbf{Z}/(p \mathbf{Z}))[X]\) if and only if \(p\) is a prime+-- number.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_gcd_euclidean_f"+ fmpz_mod_poly_gcd_euclidean_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_gcd_f/ /f/ /G/ /A/ /lenA/ /B/ /lenB/ /p/ +-- +-- Either sets \(f = 1\) and \(G\) to the greatest common divisor of+-- \((A, \operatorname{len}(A))\) and \((B, \operatorname{len}(B))\) and+-- returns its length, or sets \(f \in (1,p)\) to a non-trivial factor of+-- \(p\) and leaves the contents of the vector \((G, lenB)\) undefined.+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\)+-- and that the vector \(G\) has space for sufficiently many coefficients.+-- +-- Does not support aliasing of any of the input arguments with any of the+-- output arguments.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_gcd_f"+ _fmpz_mod_poly_gcd_f :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- | /fmpz_mod_poly_gcd_f/ /f/ /G/ /A/ /B/ /ctx/ +-- +-- Either sets \(f = 1\) and \(G\) to the greatest common divisor of \(A\)+-- and \(B\), or \(f \in (1,p)\) to a non-trivial factor of \(p\).+-- +-- In general, the greatest common divisor is defined in the polynomial+-- ring \((\mathbf{Z}/(p \mathbf{Z}))[X]\) if and only if \(p\) is a prime+-- number.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_gcd_f"+ fmpz_mod_poly_gcd_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_hgcd/ /M/ /lenM/ /A/ /lenA/ /B/ /lenB/ /a/ /lena/ /b/ /lenb/ /mod/ +-- +-- Computes the HGCD of \(a\) and \(b\), that is, a matrix~\`M\`, a+-- sign~\`sigma\` and two polynomials \(A\) and \(B\) such that+-- +-- \[`\]+-- \[(A,B)^t = \sigma M^{-1} (a,b)^t.\]+-- +-- Assumes that \(\operatorname{len}(a) > \operatorname{len}(b) > 0\).+-- +-- Assumes that \(A\) and \(B\) have space of size at least+-- \(\operatorname{len}(a)\) and \(\operatorname{len}(b)\), respectively.+-- On exit, @*lenA@ and @*lenB@ will contain the correct lengths of \(A\)+-- and \(B\).+-- +-- Assumes that @M[0]@, @M[1]@, @M[2]@, and @M[3]@ each point to a vector+-- of size at least \(\operatorname{len}(a)\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_hgcd"+ _fmpz_mod_poly_hgcd :: Ptr (Ptr CFmpz) -> Ptr CLong -> Ptr CFmpz -> Ptr CLong -> Ptr CFmpz -> Ptr CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- -- | /_fmpz_mod_poly_gcd_hgcd/ /G/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- -- +-- -- Computes the monic GCD of \(A\) and \(B\), assuming that+-- -- \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\).+-- -- +-- -- Assumes that \(G\) has space for \(\operatorname{len}(B)\) coefficients+-- -- and returns the length of \(G\) on output.+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_gcd_hgcd"+-- _fmpz_mod_poly_gcd_hgcd :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- -- | /fmpz_mod_poly_gcd_hgcd/ /G/ /A/ /B/ /ctx/ +-- -- +-- -- Computes the monic GCD of \(A\) and \(B\) using the HGCD algorithm.+-- -- +-- -- As a special case, the GCD of two zero polynomials is defined to be the+-- -- zero polynomial.+-- -- +-- -- The time complexity of the algorithm is \(\mathcal{O}(n \log^2 n)\) ring+-- -- operations. For further details, see < [ThullYap1990]>.+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_gcd_hgcd"+-- fmpz_mod_poly_gcd_hgcd :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- -- | /_fmpz_mod_poly_xgcd_euclidean/ /G/ /S/ /T/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- -- +-- -- Computes the GCD of \(A\) and \(B\) together with cofactors \(S\) and+-- -- \(T\) such that \(S A + T B = G\). Returns the length of \(G\).+-- -- +-- -- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1\)+-- -- and \((\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)\).+-- -- +-- -- No attempt is made to make the GCD monic.+-- -- +-- -- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- -- coefficients. Writes \(\operatorname{len}(B)-1\) and+-- -- \(\operatorname{len}(A)-1\) coefficients to \(S\) and \(T\),+-- -- respectively. Note that, in fact,+-- -- \(\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)\)+-- -- and+-- -- \(\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)\).+-- -- +-- -- No aliasing of input and output operands is permitted.+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_xgcd_euclidean"+-- _fmpz_mod_poly_xgcd_euclidean :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO CLong++-- | /_fmpz_mod_poly_xgcd_euclidean_f/ /f/ /G/ /S/ /T/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- +-- If \(f\) returns with the value \(1\) then the function operates as per+-- @_fmpz_mod_poly_xgcd_euclidean@, otherwise \(f\) is set to a nontrivial+-- factor of \(p\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_xgcd_euclidean_f"+ _fmpz_mod_poly_xgcd_euclidean_f :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO CLong++-- -- | /fmpz_mod_poly_xgcd_euclidean/ /G/ /S/ /T/ /A/ /B/ /ctx/ +-- -- +-- -- Computes the GCD of \(A\) and \(B\). The GCD of zero polynomials is+-- -- defined to be zero, whereas the GCD of the zero polynomial and some+-- -- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- -- the GCD is zero, the GCD \(G\) is made monic.+-- -- +-- -- Polynomials @S@ and @T@ are computed such that @S*A + T*B = G@. The+-- -- length of @S@ will be at most @lenB@ and the length of @T@ will be at+-- -- most @lenA@.+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_xgcd_euclidean"+-- fmpz_mod_poly_xgcd_euclidean :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_xgcd_euclidean_f/ /f/ /G/ /S/ /T/ /A/ /B/ /ctx/ +-- +-- If \(f\) returns with the value \(1\) then the function operates as per+-- @fmpz_mod_poly_xgcd_euclidean@, otherwise \(f\) is set to a nontrivial+-- factor of \(p\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_xgcd_euclidean_f"+ fmpz_mod_poly_xgcd_euclidean_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- -- | /_fmpz_mod_poly_xgcd_hgcd/ /G/ /S/ /T/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- -- +-- -- Computes the GCD of \(A\) and \(B\), where+-- -- \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\), together with+-- -- cofactors \(S\) and \(T\) such that \(S A + T B = G\). Returns the+-- -- length of \(G\).+-- -- +-- -- No attempt is made to make the GCD monic.+-- -- +-- -- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- -- coefficients. Writes \(\operatorname{len}(B) - 1\) and+-- -- \(\operatorname{len}(A) - 1\) coefficients to \(S\) and \(T\),+-- -- respectively. Note that, in fact,+-- -- \(\operatorname{len}(S) \leq \operatorname{len}(B) - \operatorname{len}(G)\)+-- -- and+-- -- \(\operatorname{len}(T) \leq \operatorname{len}(A) - \operatorname{len}(G)\).+-- -- +-- -- Both \(S\) and \(T\) must have space for at least \(2\) coefficients.+-- -- +-- -- No aliasing of input and output operands is permitted.+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_xgcd_hgcd"+-- _fmpz_mod_poly_xgcd_hgcd :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- -- | /fmpz_mod_poly_xgcd_hgcd/ /G/ /S/ /T/ /A/ /B/ /ctx/ +-- -- +-- -- Computes the GCD of \(A\) and \(B\). The GCD of zero polynomials is+-- -- defined to be zero, whereas the GCD of the zero polynomial and some+-- -- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- -- the GCD is zero, the GCD \(G\) is made monic.+-- -- +-- -- Polynomials @S@ and @T@ are computed such that @S*A + T*B = G@. The+-- -- length of @S@ will be at most @lenB@ and the length of @T@ will be at+-- -- most @lenA@.+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_xgcd_hgcd"+-- fmpz_mod_poly_xgcd_hgcd :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_xgcd/ /G/ /S/ /T/ /A/ /lenA/ /B/ /lenB/ /invB/ /p/ +-- +-- Computes the GCD of \(A\) and \(B\) together with cofactors \(S\) and+-- \(T\) such that \(S A + T B = G\). Returns the length of \(G\).+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1\)+-- and \((\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)\).+-- +-- No attempt is made to make the GCD monic.+-- +-- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- coefficients. Writes \(\operatorname{len}(B)-1\) and+-- \(\operatorname{len}(A)-1\) coefficients to \(S\) and \(T\),+-- respectively. Note that, in fact,+-- \(\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)\)+-- and+-- \(\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)\).+-- +-- No aliasing of input and output operands is permitted.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_xgcd"+ _fmpz_mod_poly_xgcd :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO CLong++-- | /fmpz_mod_poly_xgcd/ /G/ /S/ /T/ /A/ /B/ /ctx/ +-- +-- Computes the GCD of \(A\) and \(B\). The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+-- +-- Polynomials @S@ and @T@ are computed such that @S*A + T*B = G@. The+-- length of @S@ will be at most @lenB@ and the length of @T@ will be at+-- most @lenA@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_xgcd"+ fmpz_mod_poly_xgcd :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_xgcd_f/ /f/ /G/ /S/ /T/ /A/ /B/ /ctx/ +-- +-- If \(f\) returns with the value \(1\) then the function operates as per+-- @fmpz_mod_poly_xgcd@, otherwise \(f\) is set to a nontrivial factor of+-- \(p\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_xgcd_f"+ fmpz_mod_poly_xgcd_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_gcdinv_euclidean/ /G/ /S/ /A/ /lenA/ /B/ /lenB/ /p/ +-- +-- Computes @(G, lenA)@, @(S, lenB-1)@ such that \(G \cong S A \pmod{B}\),+-- returning the actual length of \(G\).+-- +-- Assumes that \(0 < \operatorname{len}(A) < \operatorname{len}(B)\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_gcdinv_euclidean"+ _fmpz_mod_poly_gcdinv_euclidean :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- | /fmpz_mod_poly_gcdinv_euclidean/ /G/ /S/ /A/ /B/ /ctx/ +-- +-- Computes polynomials \(G\) and \(S\), both reduced modulo~\`B\`, such+-- that \(G \cong S A \pmod{B}\), where \(B\) is assumed to have+-- \(\operatorname{len}(B) \geq 2\).+-- +-- In the case that \(A = 0 \pmod{B}\), returns \(G = S = 0\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_gcdinv_euclidean"+ fmpz_mod_poly_gcdinv_euclidean :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_gcdinv_euclidean_f/ /f/ /G/ /S/ /A/ /lenA/ /B/ /lenB/ /p/ +-- +-- If \(f\) returns with value \(1\) then the function operates as per+-- @_fmpz_mod_poly_gcdinv_euclidean@, otherwise \(f\) is set to a+-- nontrivial factor of \(p\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_gcdinv_euclidean_f"+ _fmpz_mod_poly_gcdinv_euclidean_f :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- | /fmpz_mod_poly_gcdinv_euclidean_f/ /f/ /G/ /S/ /A/ /B/ /ctx/ +-- +-- If \(f\) returns with value \(1\) then the function operates as per+-- @fmpz_mod_poly_gcdinv_euclidean@, otherwise \(f\) is set to a nontrivial+-- factor of the modulus of \(A\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_gcdinv_euclidean_f"+ fmpz_mod_poly_gcdinv_euclidean_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_gcdinv/ /G/ /S/ /A/ /lenA/ /B/ /lenB/ /p/ +-- +-- Computes @(G, lenA)@, @(S, lenB-1)@ such that \(G \cong S A \pmod{B}\),+-- returning the actual length of \(G\).+-- +-- Assumes that \(0 < \operatorname{len}(A) < \operatorname{len}(B)\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_gcdinv"+ _fmpz_mod_poly_gcdinv :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- | /_fmpz_mod_poly_gcdinv_f/ /f/ /G/ /S/ /A/ /lenA/ /B/ /lenB/ /p/ +-- +-- If \(f\) returns with value \(1\) then the function operates as per+-- @_fmpz_mod_poly_gcdinv@, otherwise \(f\) will be set to a nontrivial+-- factor of \(p\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_gcdinv_f"+ _fmpz_mod_poly_gcdinv_f :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- | /fmpz_mod_poly_gcdinv/ /G/ /S/ /A/ /B/ /ctx/ +-- +-- Computes polynomials \(G\) and \(S\), both reduced modulo~\`B\`, such+-- that \(G \cong S A \pmod{B}\), where \(B\) is assumed to have+-- \(\operatorname{len}(B) \geq 2\).+-- +-- In the case that \(A = 0 \pmod{B}\), returns \(G = S = 0\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_gcdinv"+ fmpz_mod_poly_gcdinv :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_gcdinv_f/ /f/ /G/ /S/ /A/ /B/ /ctx/ +-- +-- If \(f\) returns with value \(1\) then the function operates as per+-- @fmpz_mod_poly_gcdinv@, otherwise \(f\) will be set to a nontrivial+-- factor of \(p\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_gcdinv_f"+ fmpz_mod_poly_gcdinv_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_invmod/ /A/ /B/ /lenB/ /P/ /lenP/ /p/ +-- +-- Attempts to set @(A, lenP-1)@ to the inverse of @(B, lenB)@ modulo the+-- polynomial @(P, lenP)@. Returns \(1\) if @(B, lenB)@ is invertible and+-- \(0\) otherwise.+-- +-- Assumes that \(0 < \operatorname{len}(B) < \operatorname{len}(P)\), and+-- hence also \(\operatorname{len}(P) \geq 2\), but supports zero-padding+-- in @(B, lenB)@.+-- +-- Does not support aliasing.+-- +-- Assumes that \(p\) is a prime number.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_invmod"+ _fmpz_mod_poly_invmod :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CInt++-- | /_fmpz_mod_poly_invmod_f/ /f/ /A/ /B/ /lenB/ /P/ /lenP/ /p/ +-- +-- If \(f\) returns with the value \(1\), then the function operates as per+-- @_fmpz_mod_poly_invmod@. Otherwise \(f\) is set to a nontrivial factor+-- of \(p\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_invmod_f"+ _fmpz_mod_poly_invmod_f :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CInt++-- | /fmpz_mod_poly_invmod/ /A/ /B/ /P/ /ctx/ +-- +-- Attempts to set \(A\) to the inverse of \(B\) modulo \(P\) in the+-- polynomial ring \((\mathbf{Z}/p\mathbf{Z})[X]\), where we assume that+-- \(p\) is a prime number.+-- +-- If \(\deg(P) < 2\), raises an exception.+-- +-- If the greatest common divisor of \(B\) and \(P\) is~\`1\`,+-- returns~\`1\` and sets \(A\) to the inverse of \(B\). Otherwise,+-- returns~\`0\` and the value of \(A\) on exit is undefined.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_invmod"+ fmpz_mod_poly_invmod :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_invmod_f/ /f/ /A/ /B/ /P/ /ctx/ +-- +-- If \(f\) returns with the value \(1\), then the function operates as per+-- @fmpz_mod_poly_invmod@. Otherwise \(f\) is set to a nontrivial factor of+-- \(p\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_invmod_f"+ fmpz_mod_poly_invmod_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- Minpoly ---------------------------------------------------------------------++-- | /_fmpz_mod_poly_minpoly_bm/ /poly/ /seq/ /len/ /p/ +-- +-- Sets @poly@ to the coefficients of a minimal generating polynomial for+-- sequence @(seq, len)@ modulo \(p\).+-- +-- The return value equals the length of @poly@.+-- +-- It is assumed that \(p\) is prime and @poly@ has space for at least+-- \(len+1\) coefficients. No aliasing between inputs and outputs is+-- allowed.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_minpoly_bm"+ _fmpz_mod_poly_minpoly_bm :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- | /fmpz_mod_poly_minpoly_bm/ /poly/ /seq/ /len/ /ctx/ +-- +-- Sets @poly@ to a minimal generating polynomial for sequence @seq@ of+-- length @len@.+-- +-- Assumes that the modulus is prime.+-- +-- This version uses the Berlekamp-Massey algorithm, whose running time is+-- proportional to @len@ times the size of the minimal generator.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_minpoly_bm"+ fmpz_mod_poly_minpoly_bm :: Ptr CFmpzModPoly -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_minpoly_hgcd/ /poly/ /seq/ /len/ /p/ +-- +-- Sets @poly@ to the coefficients of a minimal generating polynomial for+-- sequence @(seq, len)@ modulo \(p\).+-- +-- The return value equals the length of @poly@.+-- +-- It is assumed that \(p\) is prime and @poly@ has space for at least+-- \(len+1\) coefficients. No aliasing between inputs and outputs is+-- allowed.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_minpoly_hgcd"+ _fmpz_mod_poly_minpoly_hgcd :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- | /fmpz_mod_poly_minpoly_hgcd/ /poly/ /seq/ /len/ /ctx/ +-- +-- Sets @poly@ to a minimal generating polynomial for sequence @seq@ of+-- length @len@.+-- +-- Assumes that the modulus is prime.+-- +-- This version uses the HGCD algorithm, whose running time is+-- \(O(n \log^2 n)\) field operations, regardless of the actual size of the+-- minimal generator.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_minpoly_hgcd"+ fmpz_mod_poly_minpoly_hgcd :: Ptr CFmpzModPoly -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_minpoly/ /poly/ /seq/ /len/ /p/ +-- +-- Sets @poly@ to the coefficients of a minimal generating polynomial for+-- sequence @(seq, len)@ modulo \(p\).+-- +-- The return value equals the length of @poly@.+-- +-- It is assumed that \(p\) is prime and @poly@ has space for at least+-- \(len+1\) coefficients. No aliasing between inputs and outputs is+-- allowed.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_minpoly"+ _fmpz_mod_poly_minpoly :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CLong++-- | /fmpz_mod_poly_minpoly/ /poly/ /seq/ /len/ /ctx/ +-- +-- Sets @poly@ to a minimal generating polynomial for sequence @seq@ of+-- length @len@.+-- +-- A minimal generating polynomial is a monic polynomial+-- \(f = x^d + c_{d-1}x^{d-1} + \cdots + c_1 x + c_0\), of minimal degree+-- \(d\), that annihilates any consecutive \(d+1\) terms in @seq@. That is,+-- for any \(i < len - d\),+-- +-- \(seq_i = -\sum_{j=0}^{d-1} seq_{i+j}*f_j.\)+-- +-- Assumes that the modulus is prime.+-- +-- This version automatically chooses the fastest underlying implementation+-- based on @len@ and the size of the modulus.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_minpoly"+ fmpz_mod_poly_minpoly :: Ptr CFmpzModPoly -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Resultant -------------------------------------------------------------------++-- | /_fmpz_mod_poly_resultant_euclidean/ /res/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- +-- Sets \(r\) to the resultant of @(poly1, len1)@ and @(poly2, len2)@ using+-- the Euclidean algorithm.+-- +-- Assumes that @len1 >= len2 > 0@.+-- +-- Assumes that the modulus is prime.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_resultant_euclidean"+ _fmpz_mod_poly_resultant_euclidean :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_resultant_euclidean/ /r/ /f/ /g/ /ctx/ +-- +-- Computes the resultant of \(f\) and \(g\) using the Euclidean algorithm.+-- +-- For two non-zero polynomials \(f(x) = a_m x^m + \dotsb + a_0\) and+-- \(g(x) = b_n x^n + \dotsb + b_0\) of degrees \(m\) and \(n\), the+-- resultant is defined to be+-- +-- \[`\]+-- \[a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y).\]+-- +-- For convenience, we define the resultant to be equal to zero if either+-- of the two polynomials is zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_resultant_euclidean"+ fmpz_mod_poly_resultant_euclidean :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_resultant_hgcd/ /res/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Sets @res@ to the resultant of @(A, lenA)@ and @(B, lenB)@ using the+-- half-gcd algorithm.+-- +-- This algorithm computes the half-gcd as per @_fmpz_mod_poly_gcd_hgcd@+-- but additionally updates the resultant every time a division occurs. The+-- half-gcd algorithm computes the GCD recursively. Given inputs \(a\) and+-- \(b\) it lets @m = len(a)\/2@ and (recursively) performs all quotients+-- in the Euclidean algorithm which do not require the low \(m\)+-- coefficients of \(a\) and \(b\).+-- +-- This performs quotients in exactly the same order as the ordinary+-- Euclidean algorithm except that the low \(m\) coefficients of the+-- polynomials in the remainder sequence are not computed. A correction+-- step after hgcd has been called computes these low \(m\) coefficients+-- (by matrix multiplication by a transformation matrix also computed by+-- hgcd).+-- +-- This means that from the point of view of the resultant, all but the+-- last quotient performed by a recursive call to hgcd is an ordinary+-- quotient as per the usual Euclidean algorithm. However, the final+-- quotient may give a remainder of less than \(m + 1\) coefficients, which+-- won\'t be corrected until the hgcd correction step is performed+-- afterwards.+-- +-- To compute the adjustments to the resultant coming from this corrected+-- quotient, we save the relevant information in an @nmod_poly_res_t@+-- struct at the time the quotient is performed so that when the correction+-- step is performed later, the adjustments to the resultant can be+-- computed at that time also.+-- +-- The only time an adjustment to the resultant is not required after a+-- call to hgcd is if hgcd does nothing (the remainder may already have had+-- less than \(m + 1\) coefficients when hgcd was called).+-- +-- Assumes that @lenA >= lenB > 0@.+-- +-- Assumes that the modulus is prime.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_resultant_hgcd"+ _fmpz_mod_poly_resultant_hgcd :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_resultant_hgcd/ /res/ /f/ /g/ /ctx/ +-- +-- Computes the resultant of \(f\) and \(g\) using the half-gcd algorithm.+-- +-- For two non-zero polynomials \(f(x) = a_m x^m + \dotsb + a_0\) and+-- \(g(x) = b_n x^n + \dotsb + b_0\) of degrees \(m\) and \(n\), the+-- resultant is defined to be+-- +-- \[`\]+-- \[a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y).\]+-- +-- For convenience, we define the resultant to be equal to zero if either+-- of the two polynomials is zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_resultant_hgcd"+ fmpz_mod_poly_resultant_hgcd :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_resultant/ /res/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- +-- Returns the resultant of @(poly1, len1)@ and @(poly2, len2)@.+-- +-- Assumes that @len1 >= len2 > 0@.+-- +-- Assumes that the modulus is prime.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_resultant"+ _fmpz_mod_poly_resultant :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_resultant/ /res/ /f/ /g/ /ctx/ +-- +-- Computes the resultant of $f$ and $g$.+-- +-- For two non-zero polynomials \(f(x) = a_m x^m + \dotsb + a_0\) and+-- \(g(x) = b_n x^n + \dotsb + b_0\) of degrees \(m\) and \(n\), the+-- resultant is defined to be+-- +-- \[`\]+-- \[a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y).\]+-- +-- For convenience, we define the resultant to be equal to zero if either+-- of the two polynomials is zero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_resultant"+ fmpz_mod_poly_resultant :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- Discriminant ----------------------------------------------------------------++-- | /_fmpz_mod_poly_discriminant/ /d/ /poly/ /len/ /mod/ +-- +-- Set \(d\) to the discriminant of @(poly, len)@. Assumes @len > 1@.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_discriminant"+ _fmpz_mod_poly_discriminant :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_discriminant/ /d/ /f/ /ctx/ +-- +-- Set \(d\) to the discriminant of \(f\). We normalise the discriminant so+-- that+-- \(\operatorname{disc}(f) = (-1)^(n(n-1)/2) \operatorname{res}(f, f') /+-- \operatorname{lc}(f)^(n - m - 2)\), where @n = len(f)@ and+-- @m = len(f\')@. Thus \(\operatorname{disc}(f) =+-- \operatorname{lc}(f)^(2n - 2) \prod_{i < j} (r_i - r_j)^2\), where+-- \(\operatorname{lc}(f)\) is the leading coefficient of \(f\) and \(r_i\)+-- are the roots of \(f\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_discriminant"+ fmpz_mod_poly_discriminant :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- Derivative ------------------------------------------------------------------++-- | /_fmpz_mod_poly_derivative/ /res/ /poly/ /len/ /p/ +-- +-- Sets @(res, len - 1)@ to the derivative of @(poly, len)@. Also handles+-- the cases where @len@ is \(0\) or \(1\) correctly. Supports aliasing of+-- @res@ and @poly@.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_derivative"+ _fmpz_mod_poly_derivative :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_derivative/ /res/ /poly/ /ctx/ +-- +-- Sets @res@ to the derivative of @poly@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_derivative"+ fmpz_mod_poly_derivative :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- Evaluation ------------------------------------------------------------------++-- | /_fmpz_mod_poly_evaluate_fmpz/ /res/ /poly/ /len/ /a/ /p/ +-- +-- Evaluates the polynomial @(poly, len)@ at the integer \(a\) and sets+-- @res@ to the result. Aliasing between @res@ and \(a\) or any of the+-- coefficients of @poly@ is not supported.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_evaluate_fmpz"+ _fmpz_mod_poly_evaluate_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_evaluate_fmpz/ /res/ /poly/ /a/ /ctx/ +-- +-- Evaluates the polynomial @poly@ at the integer \(a\) and sets @res@ to+-- the result.+-- +-- As expected, aliasing between @res@ and \(a\) is supported. However,+-- @res@ may not be aliased with a coefficient of @poly@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_evaluate_fmpz"+ fmpz_mod_poly_evaluate_fmpz :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- Multipoint evaluation -------------------------------------------------------++-- | /_fmpz_mod_poly_evaluate_fmpz_vec_iter/ /ys/ /coeffs/ /len/ /xs/ /n/ /mod/ +-- +-- Evaluates (@coeffs@, @len@) at the @n@ values given in the vector @xs@,+-- writing the output values to @ys@. The values in @xs@ should be reduced+-- modulo the modulus.+-- +-- Uses Horner\'s method iteratively.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_evaluate_fmpz_vec_iter"+ _fmpz_mod_poly_evaluate_fmpz_vec_iter :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_evaluate_fmpz_vec_iter/ /ys/ /poly/ /xs/ /n/ /ctx/ +-- +-- Evaluates @poly@ at the @n@ values given in the vector @xs@, writing the+-- output values to @ys@. The values in @xs@ should be reduced modulo the+-- modulus.+-- +-- Uses Horner\'s method iteratively.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_evaluate_fmpz_vec_iter"+ fmpz_mod_poly_evaluate_fmpz_vec_iter :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_evaluate_fmpz_vec_fast_precomp/ /vs/ /poly/ /plen/ /tree/ /len/ /mod/ +-- +-- Evaluates (@poly@, @plen@) at the @len@ values given by the precomputed+-- subproduct tree @tree@.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_evaluate_fmpz_vec_fast_precomp"+ _fmpz_mod_poly_evaluate_fmpz_vec_fast_precomp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr (Ptr CFmpzPoly) -> CLong -> Ptr CFmpz -> IO ()++-- | /_fmpz_mod_poly_evaluate_fmpz_vec_fast/ /ys/ /poly/ /plen/ /xs/ /n/ /mod/ +-- +-- Evaluates (@coeffs@, @len@) at the @n@ values given in the vector @xs@,+-- writing the output values to @ys@. The values in @xs@ should be reduced+-- modulo the modulus.+-- +-- Uses fast multipoint evaluation, building a temporary subproduct tree.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_evaluate_fmpz_vec_fast"+ _fmpz_mod_poly_evaluate_fmpz_vec_fast :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_evaluate_fmpz_vec_fast/ /ys/ /poly/ /xs/ /n/ /ctx/ +-- +-- Evaluates @poly@ at the @n@ values given in the vector @xs@, writing the+-- output values to @ys@. The values in @xs@ should be reduced modulo the+-- modulus.+-- +-- Uses fast multipoint evaluation, building a temporary subproduct tree.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_evaluate_fmpz_vec_fast"+ fmpz_mod_poly_evaluate_fmpz_vec_fast :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_evaluate_fmpz_vec/ /ys/ /coeffs/ /len/ /xs/ /n/ /mod/ +-- +-- Evaluates (@coeffs@, @len@) at the @n@ values given in the vector @xs@,+-- writing the output values to @ys@. The values in @xs@ should be reduced+-- modulo the modulus.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_evaluate_fmpz_vec"+ _fmpz_mod_poly_evaluate_fmpz_vec :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_evaluate_fmpz_vec/ /ys/ /poly/ /xs/ /n/ /ctx/ +-- +-- Evaluates @poly@ at the @n@ values given in the vector @xs@, writing the+-- output values to @ys@. The values in @xs@ should be reduced modulo the+-- modulus.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_evaluate_fmpz_vec"+ fmpz_mod_poly_evaluate_fmpz_vec :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Composition -----------------------------------------------------------------++-- -- | /_fmpz_mod_poly_compose_horner/ /res/ /poly1/ /len1/ /poly2/ /len2/ /p/ +-- -- +-- -- Sets @res@ to the composition of @(poly1, len1)@ and @(poly2, len2)@+-- -- using Horner\'s algorithm.+-- -- +-- -- Assumes that @res@ has space for @(len1-1)*(len2-1) + 1@ coefficients,+-- -- although in \(\mathbf{Z}_p[X]\) this might not actually be the length of+-- -- the resulting polynomial when \(p\) is not a prime.+-- -- +-- -- Assumes that @poly1@ and @poly2@ are non-zero polynomials. Does not+-- -- support aliasing between any of the inputs and the output.+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_compose_horner"+-- _fmpz_mod_poly_compose_horner :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- -- | /fmpz_mod_poly_compose_horner/ /res/ /poly1/ /poly2/ /ctx/ +-- -- +-- -- Sets @res@ to the composition of @poly1@ and @poly2@ using Horner\'s+-- -- algorithm.+-- -- +-- -- To be precise about the order of composition, denoting @res@, @poly1@,+-- -- and @poly2@ by \(f\), \(g\), and \(h\), respectively, sets+-- -- \(f(t) = g(h(t))\).+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_compose_horner"+-- fmpz_mod_poly_compose_horner :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- -- | /_fmpz_mod_poly_compose_divconquer/ /res/ /poly1/ /len1/ /poly2/ /len2/ /p/ +-- -- +-- -- Sets @res@ to the composition of @(poly1, len1)@ and @(poly2, len2)@+-- -- using a divide and conquer algorithm which takes out factors of @poly2@+-- -- raised to \(2^i\) where possible.+-- -- +-- -- Assumes that @res@ has space for @(len1-1)*(len2-1) + 1@ coefficients,+-- -- although in \(\mathbf{Z}_p[X]\) this might not actually be the length of+-- -- the resulting polynomial when \(p\) is not a prime.+-- -- +-- -- Assumes that @poly1@ and @poly2@ are non-zero polynomials. Does not+-- -- support aliasing between any of the inputs and the output.+-- foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_compose_divconquer"+-- _fmpz_mod_poly_compose_divconquer :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- -- | /fmpz_mod_poly_compose_divconquer/ /res/ /poly1/ /poly2/ /ctx/ +-- -- +-- -- Sets @res@ to the composition of @poly1@ and @poly2@ using a divide and+-- -- conquer algorithm which takes out factors of @poly2@ raised to \(2^i\)+-- -- where possible.+-- -- +-- -- To be precise about the order of composition, denoting @res@, @poly1@,+-- -- and @poly2@ by \(f\), \(g\), and \(h\), respectively, sets+-- -- \(f(t) = g(h(t))\).+-- foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_compose_divconquer"+-- fmpz_mod_poly_compose_divconquer :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_compose/ /res/ /poly1/ /len1/ /poly2/ /len2/ /p/ +-- +-- Sets @res@ to the composition of @(poly1, len1)@ and @(poly2, len2)@.+-- +-- Assumes that @res@ has space for @(len1-1)*(len2-1) + 1@ coefficients,+-- although in \(\mathbf{Z}_p[X]\) this might not actually be the length of+-- the resulting polynomial when \(p\) is not a prime.+-- +-- Assumes that @poly1@ and @poly2@ are non-zero polynomials. Does not+-- support aliasing between any of the inputs and the output.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_compose"+ _fmpz_mod_poly_compose :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_compose/ /res/ /poly1/ /poly2/ /ctx/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@.+-- +-- To be precise about the order of composition, denoting @res@, @poly1@,+-- and @poly2@ by \(f\), \(g\), and \(h\), respectively, sets+-- \(f(t) = g(h(t))\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_compose"+ fmpz_mod_poly_compose :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- Square roots ----------------------------------------------------------------++-- The series expansions for \(\sqrt{h}\) and \(1/\sqrt{h}\) are defined by+-- means of the generalised binomial theorem+-- @h^r = (1+y)^r = \\sum_{k=0}^{\\infty} {r \\choose k} y^k.@ It is+-- assumed that \(h\) has constant term \(1\) and that the coefficients+-- 2^{-k} exist in the coefficient ring (i.e. \(2\) must be invertible).+--+-- | /_fmpz_mod_poly_invsqrt_series/ /g/ /h/ /n/ /mod/ +-- +-- Set the first \(n\) terms of \(g\) to the series expansion of+-- \(1/\sqrt{h}\). It is assumed that \(n > 0\), that \(h\) has constant+-- term 1 and that \(h\) is zero-padded as necessary to length \(n\).+-- Aliasing is not permitted.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_invsqrt_series"+ _fmpz_mod_poly_invsqrt_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_invsqrt_series/ /g/ /h/ /n/ /ctx/ +-- +-- Set \(g\) to the series expansion of \(1/\sqrt{h}\) to order \(O(x^n)\).+-- It is assumed that \(h\) has constant term 1.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_invsqrt_series"+ fmpz_mod_poly_invsqrt_series :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_sqrt_series/ /g/ /h/ /n/ /ctx/ +-- +-- Set the first \(n\) terms of \(g\) to the series expansion of+-- \(\sqrt{h}\). It is assumed that \(n > 0\), that \(h\) has constant term+-- 1 and that \(h\) is zero-padded as necessary to length \(n\). Aliasing+-- is not permitted.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_sqrt_series"+ _fmpz_mod_poly_sqrt_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_sqrt_series/ /g/ /h/ /n/ /ctx/ +-- +-- Set \(g\) to the series expansion of \(\sqrt{h}\) to order \(O(x^n)\).+-- It is assumed that \(h\) has constant term 1.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_sqrt_series"+ fmpz_mod_poly_sqrt_series :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_sqrt/ /s/ /p/ /n/ /mod/ +-- +-- If @(p, n)@ is a perfect square, sets @(s, n \/ 2 + 1)@ to a square root+-- of \(p\) and returns 1. Otherwise returns 0.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_sqrt"+ _fmpz_mod_poly_sqrt :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_sqrt/ /s/ /p/ /mod/ +-- +-- If \(p\) is a perfect square, sets \(s\) to a square root of \(p\) and+-- returns 1. Otherwise returns 0.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_sqrt"+ fmpz_mod_poly_sqrt :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- Modular composition ---------------------------------------------------------++-- | /_fmpz_mod_poly_compose_mod/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /p/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). The output is not allowed+-- to be aliased with any of the inputs.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_compose_mod"+ _fmpz_mod_poly_compose_mod :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_compose_mod/ /res/ /f/ /g/ /h/ /ctx/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_compose_mod"+ fmpz_mod_poly_compose_mod :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_compose_mod_horner/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /p/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). The output is not allowed+-- to be aliased with any of the inputs.+-- +-- The algorithm used is Horner\'s rule.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_compose_mod_horner"+ _fmpz_mod_poly_compose_mod_horner :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_compose_mod_horner/ /res/ /f/ /g/ /h/ /ctx/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero. The algorithm used is Horner\'s rule.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_compose_mod_horner"+ fmpz_mod_poly_compose_mod_horner :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_compose_mod_brent_kung/ /res/ /f/ /len1/ /g/ /h/ /len3/ /p/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). The output is not+-- allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_compose_mod_brent_kung"+ _fmpz_mod_poly_compose_mod_brent_kung :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_compose_mod_brent_kung/ /res/ /f/ /g/ /h/ /ctx/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\). The+-- algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_compose_mod_brent_kung"+ fmpz_mod_poly_compose_mod_brent_kung :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_reduce_matrix_mod_poly/ /A/ /B/ /f/ /ctx/ +-- +-- Sets the ith row of @A@ to the reduction of the ith row of \(B\) modulo+-- \(f\) for \(i=1,\ldots,\sqrt{\deg(f)}\). We require \(B\) to be at least+-- a \(\sqrt{\deg(f)}\times \deg(f)\) matrix and \(f\) to be nonzero.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_reduce_matrix_mod_poly"+ _fmpz_mod_poly_reduce_matrix_mod_poly :: Ptr CFmpzMat -> Ptr CFmpzMat -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_precompute_matrix_worker/ /arg_ptr/ +-- +-- Worker function version of @_fmpz_mod_poly_precompute_matrix@.+-- Input\/output is stored in @fmpz_mod_poly_matrix_precompute_arg_t@.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_precompute_matrix_worker"+ _fmpz_mod_poly_precompute_matrix_worker :: Ptr () -> IO ()++-- | /_fmpz_mod_poly_precompute_matrix/ /A/ /f/ /g/ /leng/ /ginv/ /lenginv/ /p/ +-- +-- Sets the ith row of @A@ to \(f^i\) modulo \(g\) for+-- \(i=1,\ldots,\sqrt{\deg(g)}\). We require \(A\) to be a+-- \(\sqrt{\deg(g)}\times \deg(g)\) matrix. We require @ginv@ to be the+-- inverse of the reverse of @g@ and \(g\) to be nonzero. @f@ has to be+-- reduced modulo @g@ and of length one less than @leng@ (possibly with+-- zero padding).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_precompute_matrix"+ _fmpz_mod_poly_precompute_matrix :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_precompute_matrix/ /A/ /f/ /g/ /ginv/ /ctx/ +-- +-- Sets the ith row of @A@ to \(f^i\) modulo \(g\) for+-- \(i=1,\ldots,\sqrt{\deg(g)}\). We require \(A\) to be a+-- \(\sqrt{\deg(g)}\times \deg(g)\) matrix. We require @ginv@ to be the+-- inverse of the reverse of @g@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_precompute_matrix"+ fmpz_mod_poly_precompute_matrix :: Ptr CFmpzMat -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker/ /arg_ptr/ +-- +-- Worker function version of+-- @_fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv@. Input\/output is+-- stored in @fmpz_mod_poly_compose_mod_precomp_preinv_arg_t@.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker"+ _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv_worker :: Ptr () -> IO ()++-- | /_fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv/ /res/ /f/ /lenf/ /A/ /h/ /lenh/ /hinv/ /lenhinv/ /p/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero. We require that the ith row of \(A\) contains \(g^i\)+-- for \(i=1,\ldots,\sqrt{\deg(h)}\), i.e. \(A\) is a+-- \(\sqrt{\deg(h)}\times \deg(h)\) matrix. We also require that the length+-- of \(f\) is less than the length of \(h\). Furthermore, we require+-- @hinv@ to be the inverse of the reverse of @h@. The output is not+-- allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv"+ _fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzMat -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv/ /res/ /f/ /A/ /h/ /hinv/ /ctx/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that the+-- ith row of \(A\) contains \(g^i\) for \(i=1,\ldots,\sqrt{\deg(h)}\),+-- i.e. \(A\) is a \(\sqrt{\deg(h)}\times \deg(h)\) matrix. We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+-- This version of Brent-Kung modular composition is particularly useful if+-- one has to perform several modular composition of the form \(f(g)\)+-- modulo \(h\) for fixed \(g\) and \(h\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv"+ fmpz_mod_poly_compose_mod_brent_kung_precomp_preinv :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzMat -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_compose_mod_brent_kung_preinv/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /hinv/ /lenhinv/ /p/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_compose_mod_brent_kung_preinv"+ _fmpz_mod_poly_compose_mod_brent_kung_preinv :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_compose_mod_brent_kung_preinv/ /res/ /f/ /g/ /h/ /hinv/ /ctx/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_compose_mod_brent_kung_preinv"+ fmpz_mod_poly_compose_mod_brent_kung_preinv :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_compose_mod_brent_kung_vec_preinv/ /res/ /polys/ /len1/ /l/ /g/ /glen/ /h/ /lenh/ /hinv/ /lenhinv/ /p/ +-- +-- Sets @res@ to the composition \(f_i(g)\) modulo \(h\) for+-- \(1\leq i \leq l\), where \(f_i\) are the @l@ elements of @polys@. We+-- require that \(h\) is nonzero and that the length of \(g\) is less than+-- the length of \(h\). We also require that the length of \(f_i\) is less+-- than the length of \(h\). We require @res@ to have enough memory+-- allocated to hold @l@ @fmpz_mod_poly_struct@\'s. The entries of @res@+-- need to be initialised and @l@ needs to be less than @len1@ Furthermore,+-- we require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv"+ _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_compose_mod_brent_kung_vec_preinv/ /res/ /polys/ /len1/ /n/ /g/ /h/ /hinv/ /ctx/ +-- +-- Sets @res@ to the composition \(f_i(g)\) modulo \(h\) for+-- \(1\leq i \leq n\) where \(f_i\) are the @n@ elements of @polys@. We+-- require @res@ to have enough memory allocated to hold @n@+-- @fmpz_mod_poly_struct@\'s. The entries of @res@ need to be initialised+-- and @n@ needs to be less than @len1@. We require that \(h\) is nonzero+-- and that \(f_i\) and \(g\) have smaller degree than \(h\). Furthermore,+-- we require @hinv@ to be the inverse of the reverse of @h@. No aliasing+-- of @res@ and @polys@ is allowed. The algorithm used is the Brent-Kung+-- matrix algorithm.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_compose_mod_brent_kung_vec_preinv"+ fmpz_mod_poly_compose_mod_brent_kung_vec_preinv :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> CLong -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool/ /res/ /polys/ /lenpolys/ /l/ /g/ /glen/ /poly/ /len/ /polyinv/ /leninv/ /p/ /threads/ /num_threads/ +-- +-- Multithreaded version of+-- @_fmpz_mod_poly_compose_mod_brent_kung_vec_preinv@. Distributing the+-- Horner evaluations across @flint_get_num_threads@ threads.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool"+ _fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CThreadPoolHandle -> CLong -> IO ()++-- | /fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool/ /res/ /polys/ /len1/ /n/ /g/ /poly/ /polyinv/ /ctx/ /threads/ /num_threads/ +-- +-- Multithreaded version of+-- @fmpz_mod_poly_compose_mod_brent_kung_vec_preinv@. Distributing the+-- Horner evaluations across @flint_get_num_threads@ threads.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool"+ fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> CLong -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> Ptr CThreadPoolHandle -> CLong -> IO ()++-- | /fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded/ /res/ /polys/ /len1/ /n/ /g/ /poly/ /polyinv/ /ctx/ +-- +-- Multithreaded version of+-- @fmpz_mod_poly_compose_mod_brent_kung_vec_preinv@. Distributing the+-- Horner evaluations across @flint_get_num_threads@ threads.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded"+ fmpz_mod_poly_compose_mod_brent_kung_vec_preinv_threaded :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> CLong -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- Subproduct trees ------------------------------------------------------------++-- | /_fmpz_mod_poly_tree_alloc/ /len/ +-- +-- Allocates space for a subproduct tree of the given length, having linear+-- factors at the lowest level.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_tree_alloc"+ _fmpz_mod_poly_tree_alloc :: CLong -> IO (Ptr (Ptr CFmpzPoly))++-- | /_fmpz_mod_poly_tree_free/ /tree/ /len/ +-- +-- Free the allocated space for the subproduct.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_tree_free"+ _fmpz_mod_poly_tree_free :: Ptr (Ptr CFmpzPoly) -> CLong -> IO ()++-- | /_fmpz_mod_poly_tree_build/ /tree/ /roots/ /len/ /mod/ +-- +-- Builds a subproduct tree in the preallocated space from the @len@ monic+-- linear factors \((x-r_i)\) where \(r_i\) are given by @roots@. The top+-- level product is not computed.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_tree_build"+ _fmpz_mod_poly_tree_build :: Ptr (Ptr CFmpzPoly) -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- Radix conversion ------------------------------------------------------------++-- The following functions provide the functionality to solve the radix+-- conversion problems for polynomials, which is to express a polynomial+-- \(f(X)\) with respect to a given radix \(r(X)\) as+--++++-- where \(N = \lfloor\deg(f) / \deg(r)\rfloor\). The algorithm implemented+-- here is a recursive one, which performs Euclidean divisions by powers of+-- \(r\) of the form \(r^{2^i}\), and it has time complexity+-- \(\Theta(\deg(f) \log \deg(f))\). It facilitates the repeated use of+-- precomputed data, namely the powers of \(r\) and their power series+-- inverses. This data is stored in objects of type @fmpz_mod_poly_radix_t@+-- and it is computed using the function @fmpz_mod_poly_radix_init@, which+-- only depends on~\`r\` and an upper bound on the degree of~\`f\`.+--+-- | /_fmpz_mod_poly_radix_init/ /Rpow/ /Rinv/ /R/ /lenR/ /k/ /invL/ /p/ +-- +-- Computes powers of \(R\) of the form \(R^{2^i}\) and their Newton+-- inverses modulo \(x^{2^{i} \deg(R)}\) for \(i = 0, \dotsc, k-1\).+-- +-- Assumes that the vectors @Rpow[i]@ and @Rinv[i]@ have space for+-- \(2^i \deg(R) + 1\) and \(2^i \deg(R)\) coefficients, respectively.+-- +-- Assumes that the polynomial \(R\) is non-constant, i.e.+-- \(\deg(R) \geq 1\).+-- +-- Assumes that the leading coefficient of \(R\) is a unit and that the+-- argument @invL@ is the inverse of the coefficient modulo~\`p\`.+-- +-- The argument~\`p\` is the modulus, which in \(p\)-adic applications is+-- typically a prime power, although this is not necessary. Here, we only+-- assume that \(p \geq 2\).+-- +-- Note that this precomputed data can be used for any \(F\) such that+-- \(\operatorname{len}(F) \leq 2^k \deg(R)\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_radix_init"+ _fmpz_mod_poly_radix_init :: Ptr (Ptr CFmpz) -> Ptr (Ptr CFmpz) -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_radix_init/ /D/ /R/ /degF/ /ctx/ +-- +-- Carries out the precomputation necessary to perform radix conversion to+-- radix~\`R\` for polynomials~\`F\` of degree at most @degF@.+-- +-- Assumes that \(R\) is non-constant, i.e. \(\deg(R) \geq 1\), and that+-- the leading coefficient is a unit.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_radix_init"+ fmpz_mod_poly_radix_init :: Ptr CFmpzModPolyRadix -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_poly_radix/ /B/ /F/ /Rpow/ /Rinv/ /degR/ /k/ /i/ /W/ /p/ +-- +-- This is the main recursive function used by the function+-- @fmpz_mod_poly_radix@.+-- +-- Assumes that, for all \(i = 0, \dotsc, N\), the vector @B[i]@ has space+-- for \(\deg(R)\) coefficients.+-- +-- The variable \(k\) denotes the factors of \(r\) that have previously+-- been counted for the polynomial \(F\), which is assumed to have length+-- \(2^{i+1} \deg(R)\), possibly including zero-padding.+-- +-- Assumes that \(W\) is a vector providing temporary space of length+-- \(\operatorname{len}(F) = 2^{i+1} \deg(R)\).+-- +-- The entire computation takes place over \(\mathbf{Z} / p \mathbf{Z}\),+-- where \(p \geq 2\) is a natural number.+-- +-- Thus, the top level call will have \(F\) as in the original problem, and+-- \(k = 0\).+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_radix"+ _fmpz_mod_poly_radix :: Ptr (Ptr CFmpz) -> Ptr CFmpz -> Ptr (Ptr CFmpz) -> Ptr (Ptr CFmpz) -> CLong -> CLong -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_mod_poly_radix/ /B/ /F/ /D/ /ctx/ +-- +-- Given a polynomial \(F\) and the precomputed data \(D\) for the radix+-- \(R\), computes polynomials \(B_0, \dotsc, B_N\) of degree less than+-- \(\deg(R)\) such that+-- +-- \[`\]+-- \[F = B_0 + B_1 R + \dotsb + B_N R^N,\]+-- +-- where necessarily \(N = \lfloor\deg(F) / \deg(R)\rfloor\).+-- +-- Assumes that \(R\) is non-constant, i.e.\(\deg(R) \geq 1\), and that the+-- leading coefficient is a unit.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_radix"+ fmpz_mod_poly_radix :: Ptr (Ptr CFmpzModPoly) -> Ptr CFmpzModPoly -> Ptr CFmpzModPolyRadix -> Ptr CFmpzModCtx -> IO ()++-- Input and output ------------------------------------------------------------++foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_get_str"+ fmpz_mod_poly_get_str :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CString++foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_get_str_pretty"+ fmpz_mod_poly_get_str_pretty :: Ptr CFmpzModPoly -> CString -> Ptr CFmpzModCtx -> IO CString++-- The printing options supported by this module are very similar to what+-- can be found in the two related modules @fmpz_poly@ and @nmod_poly@.+-- Consider, for example, the polynomial \(f(x) = 5x^3 + 2x + 1\) in+-- (mathbf{Z}\/6mathbf{Z})[x]. Its simple string representation is+-- @\"4 6 1 2 0 5\"@, where the first two numbers denote the length of the+-- polynomial and the modulus. The pretty string representation is+-- @\"5*x^3+2*x+1\"@.+--+-- | /_fmpz_mod_poly_fprint/ /file/ /poly/ /len/ /p/ +-- +-- Prints the polynomial @(poly, len)@ to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_mod_poly.h _fmpz_mod_poly_fprint"+ _fmpz_mod_poly_fprint :: Ptr CFile -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CInt++-- | /fmpz_mod_poly_fprint/ /file/ /poly/ /ctx/ +-- +-- Prints the polynomial to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_fprint"+ fmpz_mod_poly_fprint :: Ptr CFile -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_fprint_pretty/ /file/ /poly/ /x/ /ctx/ +-- +-- Prints the pretty representation of @(poly, len)@ to the stream @file@,+-- using the string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_fprint_pretty"+ fmpz_mod_poly_fprint_pretty :: Ptr CFile -> Ptr CFmpzModPoly -> CString -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_print/ /poly/ /ctx/ +-- +-- Prints the polynomial to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+fmpz_mod_poly_print :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt+fmpz_mod_poly_print poly ctx = printCStr (flip fmpz_mod_poly_get_str ctx) poly++-- | /fmpz_mod_poly_print_pretty/ /poly/ /x/ /ctx/ +-- +-- Prints the pretty representation of @poly@ to @stdout@, using the string+-- @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+fmpz_mod_poly_print_pretty :: Ptr CFmpzModPoly -> CString -> Ptr CFmpzModCtx -> IO CInt+fmpz_mod_poly_print_pretty poly x ctx = + printCStr (\poly -> fmpz_mod_poly_get_str_pretty poly x ctx) poly++-- Inflation and deflation -----------------------------------------------------++-- | /fmpz_mod_poly_inflate/ /result/ /input/ /inflation/ /ctx/ +-- +-- Sets @result@ to the inflated polynomial \(p(x^n)\) where \(p\) is given+-- by @input@ and \(n\) is given by @inflation@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_inflate"+ fmpz_mod_poly_inflate :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CULong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_deflate/ /result/ /input/ /deflation/ /ctx/ +-- +-- Sets @result@ to the deflated polynomial \(p(x^{1/n})\) where \(p\) is+-- given by @input@ and \(n\) is given by @deflation@. Requires \(n > 0\).+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_deflate"+ fmpz_mod_poly_deflate :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CULong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_deflation/ /input/ /ctx/ +-- +-- Returns the largest integer by which @input@ can be deflated. As special+-- cases, returns 0 if @input@ is the zero polynomial and 1 of @input@ is a+-- constant polynomial.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_poly_deflation"+ fmpz_mod_poly_deflation :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CULong++-- Berlekamp-Massey Algorithm --------------------------------------------------+++++-- | /fmpz_mod_berlekamp_massey_init/ /B/ /ctx/ +-- +-- Initialize @B@ with an empty stream.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_berlekamp_massey_init"+ fmpz_mod_berlekamp_massey_init :: Ptr CFmpzModBerlekampMassey -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_berlekamp_massey_clear/ /B/ /ctx/ +-- +-- Free any space used by @B@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_berlekamp_massey_clear"+ fmpz_mod_berlekamp_massey_clear :: Ptr CFmpzModBerlekampMassey -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_berlekamp_massey_start_over/ /B/ /ctx/ +-- +-- Empty the stream of points in @B@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_berlekamp_massey_start_over"+ fmpz_mod_berlekamp_massey_start_over :: Ptr CFmpzModBerlekampMassey -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_berlekamp_massey_add_points/ /B/ /a/ /count/ /ctx/ +-- +-- Add point(s) to the stream processed by @B@. The addition of any number+-- of points will not update the \(V\) and \(R\) polynomial.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_berlekamp_massey_add_points"+ fmpz_mod_berlekamp_massey_add_points :: Ptr CFmpzModBerlekampMassey -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_berlekamp_massey_reduce/ /B/ /ctx/ +-- +-- Ensure that the polynomials \(V\) and \(R\) are up to date. The return+-- value is @1@ if this function changed \(V\) and @0@ otherwise. For+-- example, if this function is called twice in a row without adding any+-- points in between, the return of the second call should be @0@. As+-- another example, suppose the object is emptied, the points+-- \(1, 1, 2, 3\) are added, then reduce is called. This reduce should+-- return @1@ with \(\deg(R) < \deg(V) = 2\) because the Fibonacci sequence+-- has been recognized. The further addition of the two points \(5, 8\) and+-- a reduce will result in a return value of @0@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_berlekamp_massey_reduce"+ fmpz_mod_berlekamp_massey_reduce :: Ptr CFmpzModBerlekampMassey -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_berlekamp_massey_point_count/ /B/ +-- +-- Return the number of points stored in @B@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_berlekamp_massey_point_count"+ fmpz_mod_berlekamp_massey_point_count :: Ptr CFmpzModBerlekampMassey -> IO CLong++-- | /fmpz_mod_berlekamp_massey_points/ /B/ +-- +-- Return a pointer the array of points stored in @B@. This may be @NULL@+-- if func::fmpz_mod_berlekamp_massey_point_count returns @0@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_berlekamp_massey_points"+ fmpz_mod_berlekamp_massey_points :: Ptr CFmpzModBerlekampMassey -> IO (Ptr CFmpz)++-- | /fmpz_mod_berlekamp_massey_V_poly/ /B/ +-- +-- Return the polynomial @V@ in @B@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_berlekamp_massey_V_poly"+ fmpz_mod_berlekamp_massey_V_poly :: Ptr CFmpzModBerlekampMassey -> IO (Ptr CFmpzModPoly)++-- | /fmpz_mod_berlekamp_massey_R_poly/ /B/ +-- +-- Return the polynomial @R@ in @B@.+foreign import ccall "fmpz_mod_poly.h fmpz_mod_berlekamp_massey_R_poly"+ fmpz_mod_berlekamp_massey_R_poly :: Ptr CFmpzModBerlekampMassey -> IO (Ptr CFmpzModPoly)++-- Characteristic polynomial ---------------------------------------------------++-- | /fmpz_mod_mat_charpoly/ /p/ /M/ /ctx/ +-- +-- Compute the characteristic polynomial \(p\) of the matrix \(M\). The+-- matrix is required to be square, otherwise an exception is raised.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_charpoly"+ fmpz_mod_mat_charpoly :: Ptr CFmpzModPoly -> Ptr CFmpzModMat -> Ptr CFmpzModCtx -> IO ()++-- Minimal polynomial ----------------------------------------------------------++-- | /fmpz_mod_mat_minpoly/ /p/ /M/ /ctx/ +-- +-- Compute the minimal polynomial \(p\) of the matrix \(M\). The matrix is+-- required to be square, otherwise an exception is raised.+-- +-- The modulus is assumed to be prime.+foreign import ccall "fmpz_mod_mat.h fmpz_mod_mat_minpoly"+ fmpz_mod_mat_minpoly :: Ptr CFmpzModPoly -> Ptr CFmpzModMat -> Ptr CFmpzModCtx -> IO ()
+ src/Data/Number/Flint/Fmpz/Mod/Poly/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Mod.Poly.Factor (+ module Data.Number.Flint.Fmpz.Mod.Poly.Factor.FFI,+) where++import Data.Number.Flint.Fmpz.Mod.Poly.Factor.FFI
+ src/Data/Number/Flint/Fmpz/Mod/Poly/Factor/FFI.hsc view
@@ -0,0 +1,365 @@+{-|+module : Data.Number.Flint.Fmpz.Mod.Poly.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Mod.Poly.Factor.FFI (+ -- * Factorisation of polynomials over integers mod n+ FmpzModPolyFactor (..)+ , CFmpzModPolyFactor (..)+ , newFmpzModPolyFactor+ , withFmpzModPolyFactor+ -- * Factorisation+ , fmpz_mod_poly_factor_init+ , fmpz_mod_poly_factor_clear+ , fmpz_mod_poly_factor_realloc+ , fmpz_mod_poly_factor_fit_length+ , fmpz_mod_poly_factor_set+ , fmpz_mod_poly_factor_print+ , fmpz_mod_poly_factor_print_pretty+ , fmpz_mod_poly_factor_insert+ , fmpz_mod_poly_factor_concat+ , fmpz_mod_poly_factor_pow+ , fmpz_mod_poly_is_irreducible+ , fmpz_mod_poly_is_irreducible_ddf+ , fmpz_mod_poly_is_irreducible_rabin+ , fmpz_mod_poly_is_irreducible_rabin_f+ , _fmpz_mod_poly_is_squarefree+ , _fmpz_mod_poly_is_squarefree_f+ , fmpz_mod_poly_is_squarefree+ , fmpz_mod_poly_is_squarefree_f+ , fmpz_mod_poly_factor_equal_deg_prob+ , fmpz_mod_poly_factor_equal_deg+ , fmpz_mod_poly_factor_distinct_deg+ , fmpz_mod_poly_factor_distinct_deg_threaded+ , fmpz_mod_poly_factor_squarefree+ , fmpz_mod_poly_factor+ , fmpz_mod_poly_factor_cantor_zassenhaus+ , fmpz_mod_poly_factor_kaltofen_shoup+ , fmpz_mod_poly_factor_berlekamp+ --, _fmpz_mod_poly_interval_poly_worker+ -- * Root Finding+ , fmpz_mod_poly_roots+ , fmpz_mod_poly_roots_factored+) where++-- Factorisation of polynomials over integers mod n ----------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.ThreadPool+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpz.Mod+import Data.Number.Flint.Fmpz.Mod.Poly++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_mod_poly.h>+#include <flint/fmpz_mod_poly_factor.h>++-- fmpz_mod_poly_factor_t ------------------------------------------------------++data FmpzModPolyFactor =+ FmpzModPolyFactor {-# UNPACK #-} !(ForeignPtr CFmpzModPolyFactor)+data CFmpzModPolyFactor = CFmpzModPolyFactor (Ptr CFmpzModPoly) (Ptr CLong) CLong CLong ++instance Storable CFmpzModPolyFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_mod_poly_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_mod_poly_factor_t}+ peek ptr = return CFmpzModPolyFactor + `ap` #{peek fmpz_mod_poly_factor_struct, poly } ptr+ `ap` #{peek fmpz_mod_poly_factor_struct, exp } ptr+ `ap` #{peek fmpz_mod_poly_factor_struct, num } ptr+ `ap` #{peek fmpz_mod_poly_factor_struct, alloc} ptr+ poke = undefined++newFmpzModPolyFactor ctx@(FmpzModCtx mtx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpzModCtx ctx $ \ctx -> do+ fmpz_mod_poly_factor_init x ctx+ addForeignPtrFinalizerEnv p_fmpz_mod_poly_factor_clear x mtx+ return $ FmpzModPolyFactor x++{-# INLINE withFmpzModPolyFactor #-}+withFmpzModPolyFactor (FmpzModPolyFactor x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FmpzModPolyFactor x,)+ +-- Factorisation ---------------------------------------------------------------++-- | /fmpz_mod_poly_factor_init/ /fac/ /ctx/ +--+-- Initialises @fac@ for use.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_init"+ fmpz_mod_poly_factor_init :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor_clear/ /fac/ /ctx/ +--+-- Frees all memory associated with @fac@.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_clear"+ fmpz_mod_poly_factor_clear :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModCtx -> IO ()++foreign import ccall "fmpz_mod_poly_factor.h &fmpz_mod_poly_factor_clear"+ p_fmpz_mod_poly_factor_clear :: FunPtr (Ptr CFmpzModPolyFactor -> Ptr CFmpzModCtx -> IO ())++-- | /fmpz_mod_poly_factor_realloc/ /fac/ /alloc/ /ctx/ +--+-- Reallocates the factor structure to provide space for precisely @alloc@+-- factors.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_realloc"+ fmpz_mod_poly_factor_realloc :: Ptr CFmpzModPolyFactor -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor_fit_length/ /fac/ /len/ /ctx/ +--+-- Ensures that the factor structure has space for at least @len@ factors.+-- This function takes care of the case of repeated calls by always at+-- least doubling the number of factors the structure can hold.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_fit_length"+ fmpz_mod_poly_factor_fit_length :: Ptr CFmpzModPolyFactor -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor_set/ /res/ /fac/ /ctx/ +--+-- Sets @res@ to the same factorisation as @fac@.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_set"+ fmpz_mod_poly_factor_set :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPolyFactor -> Ptr CFmpzModCtx -> IO ()++foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_get_str"+ fmpz_mod_poly_factor_get_str :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModCtx -> IO CString++foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_get_str_pretty"+ fmpz_mod_poly_factor_get_str_pretty :: Ptr CFmpzModPolyFactor -> CString -> Ptr CFmpzModCtx -> IO CString++-- | /fmpz_mod_poly_factor_print/ /fac/ /ctx/ +--+-- Prints the entries of @fac@ to standard output.+fmpz_mod_poly_factor_print :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModCtx -> IO ()+fmpz_mod_poly_factor_print fac ctx = do+ printCStr (flip fmpz_mod_poly_factor_get_str ctx) fac+ return ()++-- | /fmpz_mod_poly_factor_print_pretty/ /fac/ /var/ /ctx/ +--+-- Prints the entries of @fac@ to standard output.+fmpz_mod_poly_factor_print_pretty :: Ptr CFmpzModPolyFactor -> CString -> Ptr CFmpzModCtx -> IO ()+fmpz_mod_poly_factor_print_pretty fac var ctx = do+ printCStr (\fac -> fmpz_mod_poly_factor_get_str_pretty fac var ctx) fac+ return ()++-- | /fmpz_mod_poly_factor_insert/ /fac/ /poly/ /exp/ /ctx/ +--+-- Inserts the factor @poly@ with multiplicity @exp@ into the factorisation+-- @fac@.+-- +-- If @fac@ already contains @poly@, then @exp@ simply gets added to the+-- exponent of the existing entry.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_insert"+ fmpz_mod_poly_factor_insert :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor_concat/ /res/ /fac/ /ctx/ +--+-- Concatenates two factorisations.+-- +-- This is equivalent to calling @fmpz_mod_poly_factor_insert@ repeatedly+-- with the individual factors of @fac@.+-- +-- Does not support aliasing between @res@ and @fac@.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_concat"+ fmpz_mod_poly_factor_concat :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPolyFactor -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor_pow/ /fac/ /exp/ /ctx/ +--+-- Raises @fac@ to the power @exp@.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_pow"+ fmpz_mod_poly_factor_pow :: Ptr CFmpzModPolyFactor -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_is_irreducible/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_is_irreducible"+ fmpz_mod_poly_is_irreducible :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_is_irreducible_ddf/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+-- Uses fast distinct-degree factorisation.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_is_irreducible_ddf"+ fmpz_mod_poly_is_irreducible_ddf :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_is_irreducible_rabin/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+-- Uses Rabin irreducibility test.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_is_irreducible_rabin"+ fmpz_mod_poly_is_irreducible_rabin :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_is_irreducible_rabin_f/ /r/ /f/ /ctx/ +--+-- Either sets \(r\) to \(1\) and returns 1 if the polynomial @f@ is+-- irreducible or \(0\) otherwise, or sets \(r\) to a nontrivial factor of+-- \(p\).+-- +-- This algorithm correctly determines whether \(f\) is irreducible over+-- \(\mathbb{Z}/p\mathbb{Z}\), even for composite \(f\), or it finds a+-- factor of \(p\).+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_is_irreducible_rabin_f"+ fmpz_mod_poly_is_irreducible_rabin_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /_fmpz_mod_poly_is_squarefree/ /f/ /len/ /ctx/ +--+-- Returns 1 if @(f, len)@ is squarefree, and 0 otherwise. As a special+-- case, the zero polynomial is not considered squarefree. There are no+-- restrictions on the length.+foreign import ccall "fmpz_mod_poly_factor.h _fmpz_mod_poly_is_squarefree"+ _fmpz_mod_poly_is_squarefree :: Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO CInt++-- | /_fmpz_mod_poly_is_squarefree_f/ /fac/ /f/ /len/ /ctx/ +--+-- If \(fac\) returns with the value \(1\) then the function operates as+-- per @_fmpz_mod_poly_is_squarefree@, otherwise \(f\) is set to a+-- nontrivial factor of \(p\).+foreign import ccall "fmpz_mod_poly_factor.h _fmpz_mod_poly_is_squarefree_f"+ _fmpz_mod_poly_is_squarefree_f :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_is_squarefree/ /f/ /ctx/ +--+-- Returns 1 if @f@ is squarefree, and 0 otherwise. As a special case, the+-- zero polynomial is not considered squarefree.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_is_squarefree"+ fmpz_mod_poly_is_squarefree :: Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_is_squarefree_f/ /fac/ /f/ /ctx/ +--+-- If \(fac\) returns with the value \(1\) then the function operates as+-- per @fmpz_mod_poly_is_squarefree@, otherwise \(f\) is set to a+-- nontrivial factor of \(p\).+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_is_squarefree_f"+ fmpz_mod_poly_is_squarefree_f :: Ptr CFmpz -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_factor_equal_deg_prob/ /factor/ /state/ /pol/ /d/ /ctx/ +--+-- Probabilistic equal degree factorisation of @pol@ into irreducible+-- factors of degree @d@. If it passes, a factor is placed in @factor@ and+-- 1 is returned, otherwise 0 is returned and the value of factor is+-- undetermined.+-- +-- Requires that @pol@ be monic, non-constant and squarefree.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_equal_deg_prob"+ fmpz_mod_poly_factor_equal_deg_prob :: Ptr CFmpzModPoly -> Ptr CFRandState -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO CInt++-- | /fmpz_mod_poly_factor_equal_deg/ /factors/ /pol/ /d/ /ctx/ +--+-- Assuming @pol@ is a product of irreducible factors all of degree @d@,+-- finds all those factors and places them in factors. Requires that @pol@+-- be monic, non-constant and squarefree.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_equal_deg"+ fmpz_mod_poly_factor_equal_deg :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPoly -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor_distinct_deg/ /res/ /poly/ /degs/ /ctx/ +--+-- Factorises a monic non-constant squarefree polynomial @poly@ of degree+-- \(n\) into factors \(f[d]\) such that for \(1 \leq d \leq n\) \(f[d]\)+-- is the product of the monic irreducible factors of @poly@ of degree+-- \(d\). Factors \(f[d]\) are stored in @res@, and the degree \(d\) of the+-- irreducible factors is stored in @degs@ in the same order as the+-- factors.+-- +-- Requires that @degs@ has enough space for \((n/2)+1 * sizeof(slong)\).+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_distinct_deg"+ fmpz_mod_poly_factor_distinct_deg :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPoly -> Ptr (Ptr CLong) -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor_distinct_deg_threaded/ /res/ /poly/ /degs/ /ctx/ +--+-- Multithreaded version of @fmpz_mod_poly_factor_distinct_deg@.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_distinct_deg_threaded"+ fmpz_mod_poly_factor_distinct_deg_threaded :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPoly -> Ptr (Ptr CLong) -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor_squarefree/ /res/ /f/ /ctx/ +--+-- Sets @res@ to a squarefree factorization of @f@.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_squarefree"+ fmpz_mod_poly_factor_squarefree :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor/ /res/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- choosing the best algorithm for given modulo and degree. Choice is based+-- on heuristic measurements.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor"+ fmpz_mod_poly_factor :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor_cantor_zassenhaus/ /res/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the Cantor-Zassenhaus algorithm.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_cantor_zassenhaus"+ fmpz_mod_poly_factor_cantor_zassenhaus :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor_kaltofen_shoup/ /res/ /poly/ /ctx/ +--+-- Factorises a non-constant polynomial @poly@ into monic irreducible+-- factors using the fast version of Cantor-Zassenhaus algorithm proposed+-- by Kaltofen and Shoup (1998). More precisely this algorithm uses a baby+-- step\/giant step strategy for the distinct-degree factorization step. If+-- @flint_get_num_threads@ is greater than one+-- @fmpz_mod_poly_factor_distinct_deg_threaded@ is used.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_kaltofen_shoup"+ fmpz_mod_poly_factor_kaltofen_shoup :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_factor_berlekamp/ /factors/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the Berlekamp algorithm.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_factor_berlekamp"+ fmpz_mod_poly_factor_berlekamp :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> IO ()++-- -- | /_fmpz_mod_poly_interval_poly_worker/ /arg_ptr/ +-- --+-- -- Worker function to compute interval polynomials in distinct degree+-- -- factorisation. Input\/output is stored in+-- -- @fmpz_mod_poly_interval_poly_arg_t@.+-- foreign import ccall "fmpz_mod_poly_factor.h _fmpz_mod_poly_interval_poly_worker"+-- _fmpz_mod_poly_interval_poly_worker :: Ptr -> IO ()++-- Root Finding ----------------------------------------------------------------++-- | /fmpz_mod_poly_roots/ /r/ /f/ /with_multiplicity/ /ctx/ +--+-- Fill \(r\) with factors of the form \(x - r_i\) where the \(r_i\) are+-- the distinct roots of a nonzero \(f\) in \(Z/pZ\). It is expected and+-- not checked that the modulus of \(ctx\) is prime. If+-- \(with\_multiplicity\) is zero, the exponent \(e_i\) of the factor+-- \(x - r_i\) is \(1\). Otherwise, it is the largest \(e_i\) such that+-- \((x-r_i)^e_i\) divides \(f\). This function throws if \(f\) is zero,+-- but is otherwise always successful.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_roots"+ fmpz_mod_poly_roots :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPoly -> CInt -> Ptr CFmpzModCtx -> IO ()++-- | /fmpz_mod_poly_roots_factored/ /r/ /f/ /with_multiplicity/ /n/ /ctx/ +--+-- Fill \(r\) with factors of the form \(x - r_i\) where the \(r_i\) are+-- the distinct roots of a nonzero \(f\) in \(Z/nZ\). It is expected and+-- not checked that \(n\) is a prime factorization of the modulus of+-- \(ctx\). If \(with\_multiplicity\) is zero, the exponent \(e_i\) of the+-- factor \(x - r_i\) is \(1\). Otherwise, it is the largest \(e_i\) such+-- that \((x-r_i)^e_i\) divides \(f\). The roots are first found modulo the+-- primes in \(n\), then lifted to the corresponding prime powers, then+-- combined into roots of the original polynomial \(f\). A return of \(1\)+-- indicates the function was successful. A return of \(0\) indicates the+-- function was not able to find the roots, possibly because there are too+-- many of them. This function throws if \(f\) is zero.+foreign import ccall "fmpz_mod_poly_factor.h fmpz_mod_poly_roots_factored"+ fmpz_mod_poly_roots_factored :: Ptr CFmpzModPolyFactor -> Ptr CFmpzModPoly -> CInt -> Ptr CFmpzFactor -> Ptr CFmpzModCtx -> IO CInt+
+ src/Data/Number/Flint/Fmpz/Mod/Vec.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Mod.Vec (+ module Data.Number.Flint.Fmpz.Mod.Vec.FFI+ ) where++import Data.Number.Flint.Fmpz.Mod.Vec.FFI
+ src/Data/Number/Flint/Fmpz/Mod/Vec/FFI.hsc view
@@ -0,0 +1,106 @@+{-|+module : Data.Number.Flint.Fmpz.Mod.Vec.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Mod.Vec.FFI (+ -- * Vectors over integers mod n+ -- * Conversions+ _fmpz_mod_vec_set_fmpz_vec+ -- * Arithmetic+ , _fmpz_mod_vec_neg+ , _fmpz_mod_vec_add+ , _fmpz_mod_vec_sub+ -- * Scalar Multiplication+ , _fmpz_mod_vec_scalar_mul_fmpz_mod+ , _fmpz_mod_vec_scalar_addmul_fmpz_mod+ , _fmpz_mod_vec_scalar_div_fmpz_mod+ -- * Dot Product+ , _fmpz_mod_vec_dot+ , _fmpz_mod_vec_dot_rev+ -- * Multiplication+ , _fmpz_mod_vec_mul+) where++-- Vectors over integers mod n -------------------------------------------------++import Foreign.Ptr+import Foreign.C.Types++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mod++-- Conversions -----------------------------------------------------------------++-- | /_fmpz_mod_vec_set_fmpz_vec/ /A/ /B/ /len/ /ctx/ +--+-- Set the \(fmpz_mod_vec\) \((A, len)\) to the \(fmpz_vec\) \((B, len)\)+-- after reduction of each entry modulo the modulus..+foreign import ccall "fmpz_mod_vec.h _fmpz_mod_vec_set_fmpz_vec"+ _fmpz_mod_vec_set_fmpz_vec :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- | /_fmpz_mod_vec_neg/ /A/ /B/ /len/ /ctx/ +--+-- Set \((A, len)\) to \(-(B, len)\).+foreign import ccall "fmpz_mod_vec.h _fmpz_mod_vec_neg"+ _fmpz_mod_vec_neg :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_vec_add/ /a/ /b/ /c/ /n/ /ctx/ +--+-- Set (A, len) to :math:(B, len) + (C, len)\`.+foreign import ccall "fmpz_mod_vec.h _fmpz_mod_vec_add"+ _fmpz_mod_vec_add :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_vec_sub/ /a/ /b/ /c/ /n/ /ctx/ +--+-- Set (A, len) to :math:(B, len) - (C, len)\`.+foreign import ccall "fmpz_mod_vec.h _fmpz_mod_vec_sub"+ _fmpz_mod_vec_sub :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Scalar Multiplication -------------------------------------------------------++-- | /_fmpz_mod_vec_scalar_mul_fmpz_mod/ /A/ /B/ /len/ /c/ /ctx/ +--+-- Set \((A, len)\) to \((B, len)*c\).+foreign import ccall "fmpz_mod_vec.h _fmpz_mod_vec_scalar_mul_fmpz_mod"+ _fmpz_mod_vec_scalar_mul_fmpz_mod :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_vec_scalar_addmul_fmpz_mod/ /A/ /B/ /len/ /c/ /ctx/ +--+-- Set \((A, len)\) to \((A, len) + (B, len)*c\).+foreign import ccall "fmpz_mod_vec.h _fmpz_mod_vec_scalar_addmul_fmpz_mod"+ _fmpz_mod_vec_scalar_addmul_fmpz_mod :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_vec_scalar_div_fmpz_mod/ /A/ /B/ /len/ /c/ /ctx/ +--+-- Set \((A, len)\) to \((B, len)/c\) assuming \(c\) is nonzero.+foreign import ccall "fmpz_mod_vec.h _fmpz_mod_vec_scalar_div_fmpz_mod"+ _fmpz_mod_vec_scalar_div_fmpz_mod :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpzModCtx -> IO ()++-- Dot Product -----------------------------------------------------------------++-- | /_fmpz_mod_vec_dot/ /d/ /A/ /B/ /len/ /ctx/ +--+-- Set \(d\) to the dot product of \((A, len)\) with \((B, len)\).+foreign import ccall "fmpz_mod_vec.h _fmpz_mod_vec_dot"+ _fmpz_mod_vec_dot :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- | /_fmpz_mod_vec_dot_rev/ /d/ /A/ /B/ /len/ /ctx/ +--+-- Set \(d\) to the dot product of \((A, len)\) with the reverse of the+-- vector \((B, len)\).+foreign import ccall "fmpz_mod_vec.h _fmpz_mod_vec_dot_rev"+ _fmpz_mod_vec_dot_rev :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /_fmpz_mod_vec_mul/ /A/ /B/ /C/ /len/ /ctx/ +--+-- Set \((A, len)\) the pointwise multiplication of \((B, len)\) and+-- \((C, len)\).+foreign import ccall "fmpz_mod_vec.h _fmpz_mod_vec_mul"+ _fmpz_mod_vec_mul :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzModCtx -> IO ()+
+ src/Data/Number/Flint/Fmpz/Poly.hs view
@@ -0,0 +1,37 @@+{-|+module : Data.Number.Flint.Fmpz.Poly+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+++An `FmpzPoly` represents an element of \(\mathbb{Z}[x]\).+This module implements operations on univariate polynomials over the integers.++== Example++__Warning__: Instances like `Show`, `Num` and `IsList` are only+avaible for some types.++@+import Data.Number.Flint++main = do + let poly = fromList [35,24,16,4,1] :: FmpzPoly+ print poly+ mapM_ print $ factor poly+@++Running main yields:++>>> main +x^4+4*x^3+16*x^2+24*x+35+(x^2+2*x+7,1)+(x^2+2*x+5,1)+-}+module Data.Number.Flint.Fmpz.Poly (+ module Data.Number.Flint.Fmpz.Poly.FFI+ ) where+ +import GHC.Exts+import Data.Number.Flint.Fmpz.Poly.FFI
+ src/Data/Number/Flint/Fmpz/Poly/FFI.hsc view
@@ -0,0 +1,4517 @@+{-|+module : Data.Number.Flint.Fmpz.Poly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Poly.FFI (+ -- * Univariate polynomials over the integers+ FmpzPoly (..)+ , CFmpzPoly (..)+ -- * Constructor+ , newFmpzPoly+ , withFmpzPoly+ , withNewFmpzPoly+ -- * Memory management+ , fmpz_poly_init+ , fmpz_poly_init2+ , fmpz_poly_realloc+ , fmpz_poly_fit_length+ , fmpz_poly_clear+ , _fmpz_poly_normalise+ , _fmpz_poly_set_length+ , fmpz_poly_attach_truncate+ , fmpz_poly_attach_shift+ -- * Polynomial parameters+ , fmpz_poly_length+ , fmpz_poly_degree+ -- * Assignment and basic manipulation+ , fmpz_poly_set+ , fmpz_poly_set_si+ , fmpz_poly_set_ui+ , fmpz_poly_set_fmpz+ -- , fmpz_poly_set_mpz+ , _fmpz_poly_set_str+ , fmpz_poly_set_str+ , _fmpz_poly_get_str+ , fmpz_poly_get_str+ , _fmpz_poly_get_str_pretty+ , fmpz_poly_get_str_pretty+ , fmpz_poly_zero+ , fmpz_poly_one+ , fmpz_poly_zero_coeffs+ , fmpz_poly_swap+ , _fmpz_poly_reverse+ , fmpz_poly_reverse+ , fmpz_poly_truncate+ , fmpz_poly_set_trunc+ -- * Randomisation+ , fmpz_poly_randtest+ , fmpz_poly_randtest_unsigned+ , fmpz_poly_randtest_not_zero+ , fmpz_poly_randtest_no_real_root+ -- * Getting and setting coefficients+ , fmpz_poly_get_coeff_fmpz+ , fmpz_poly_get_coeff_si+ , fmpz_poly_get_coeff_ui+ , fmpz_poly_get_coeff_ptr+ , fmpz_poly_lead+ , fmpz_poly_set_coeff_fmpz+ , fmpz_poly_set_coeff_si+ , fmpz_poly_set_coeff_ui+ -- * Comparison+ , fmpz_poly_equal+ , fmpz_poly_equal_trunc+ , fmpz_poly_is_zero+ , fmpz_poly_is_one+ , fmpz_poly_is_unit+ , fmpz_poly_is_gen+ -- * Addition and subtraction+ , _fmpz_poly_add+ , fmpz_poly_add+ , fmpz_poly_add_series+ , _fmpz_poly_sub+ , fmpz_poly_sub+ , fmpz_poly_sub_series+ , fmpz_poly_neg+ -- * Scalar absolute value, multiplication and division+ , fmpz_poly_scalar_abs+ , fmpz_poly_scalar_mul_fmpz+ --, fmpz_poly_scalar_mul_mpz+ , fmpz_poly_scalar_mul_si+ , fmpz_poly_scalar_mul_ui+ , fmpz_poly_scalar_mul_2exp+ , fmpz_poly_scalar_addmul_si+ , fmpz_poly_scalar_addmul_ui+ , fmpz_poly_scalar_addmul_fmpz+ , fmpz_poly_scalar_submul_fmpz+ , fmpz_poly_scalar_fdiv_fmpz+ --, fmpz_poly_scalar_fdiv_mpz+ , fmpz_poly_scalar_fdiv_si+ , fmpz_poly_scalar_fdiv_ui+ , fmpz_poly_scalar_fdiv_2exp+ , fmpz_poly_scalar_tdiv_fmpz+ , fmpz_poly_scalar_tdiv_si+ , fmpz_poly_scalar_tdiv_ui+ , fmpz_poly_scalar_tdiv_2exp+ , fmpz_poly_scalar_divexact_fmpz+ --, fmpz_poly_scalar_divexact_mpz+ , fmpz_poly_scalar_divexact_si+ , fmpz_poly_scalar_divexact_ui+ , fmpz_poly_scalar_mod_fmpz+ , fmpz_poly_scalar_smod_fmpz+ , _fmpz_poly_remove_content_2exp+ , _fmpz_poly_scale_2exp+ -- * Bit packing+ , _fmpz_poly_bit_pack+ , _fmpz_poly_bit_unpack+ , _fmpz_poly_bit_unpack_unsigned+ , fmpz_poly_bit_pack+ , fmpz_poly_bit_unpack+ , fmpz_poly_bit_unpack_unsigned+ -- * Multiplication+ , _fmpz_poly_mul_classical+ , fmpz_poly_mul_classical+ , _fmpz_poly_mullow_classical+ , fmpz_poly_mullow_classical+ , _fmpz_poly_mulhigh_classical+ , fmpz_poly_mulhigh_classical+ , _fmpz_poly_mulmid_classical+ , fmpz_poly_mulmid_classical+ , _fmpz_poly_mul_karatsuba+ , fmpz_poly_mul_karatsuba+ , _fmpz_poly_mullow_karatsuba_n+ , fmpz_poly_mullow_karatsuba_n+ , _fmpz_poly_mulhigh_karatsuba_n+ , fmpz_poly_mulhigh_karatsuba_n+ , _fmpz_poly_mul_KS+ , fmpz_poly_mul_KS+ , _fmpz_poly_mullow_KS+ , fmpz_poly_mullow_KS+ , _fmpz_poly_mul_SS+ , fmpz_poly_mul_SS+ , _fmpz_poly_mullow_SS+ , fmpz_poly_mullow_SS+ , _fmpz_poly_mul+ , fmpz_poly_mul+ , _fmpz_poly_mullow+ , fmpz_poly_mullow+ , fmpz_poly_mulhigh_n+ , _fmpz_poly_mulhigh+ -- * FFT precached multiplication+ , fmpz_poly_mul_SS_precache_init+ , fmpz_poly_mul_precache_clear+ , _fmpz_poly_mullow_SS_precache+ , fmpz_poly_mullow_SS_precache+ , fmpz_poly_mul_SS_precache+ -- * Squaring+ , _fmpz_poly_sqr_KS+ , fmpz_poly_sqr_KS+ , _fmpz_poly_sqr_karatsuba+ , fmpz_poly_sqr_karatsuba+ , _fmpz_poly_sqr_classical+ , fmpz_poly_sqr_classical+ , _fmpz_poly_sqr+ , fmpz_poly_sqr+ , _fmpz_poly_sqrlow_KS+ , fmpz_poly_sqrlow_KS+ , _fmpz_poly_sqrlow_karatsuba_n+ , fmpz_poly_sqrlow_karatsuba_n+ , _fmpz_poly_sqrlow_classical+ , fmpz_poly_sqrlow_classical+ , _fmpz_poly_sqrlow+ , fmpz_poly_sqrlow+ -- * Powering+ , _fmpz_poly_pow_multinomial+ , fmpz_poly_pow_multinomial+ , _fmpz_poly_pow_binomial+ , fmpz_poly_pow_binomial+ , _fmpz_poly_pow_addchains+ , fmpz_poly_pow_addchains+ , _fmpz_poly_pow_binexp+ , fmpz_poly_pow_binexp+ , _fmpz_poly_pow_small+ , _fmpz_poly_pow+ , fmpz_poly_pow+ , _fmpz_poly_pow_trunc+ , fmpz_poly_pow_trunc+ -- * Shifting+ , _fmpz_poly_shift_left+ , fmpz_poly_shift_left+ , _fmpz_poly_shift_right+ , fmpz_poly_shift_right+ -- * Bit sizes and norms+ , fmpz_poly_max_limbs+ , fmpz_poly_max_bits+ , fmpz_poly_height+ , _fmpz_poly_2norm+ , fmpz_poly_2norm+ , _fmpz_poly_2norm_normalised_bits+ -- * Greatest common divisor+ , _fmpz_poly_gcd_subresultant+ , fmpz_poly_gcd_subresultant+ , _fmpz_poly_gcd_heuristic+ , fmpz_poly_gcd_heuristic+ , _fmpz_poly_gcd_modular+ , fmpz_poly_gcd_modular+ , _fmpz_poly_gcd+ , fmpz_poly_gcd+ , _fmpz_poly_xgcd_modular+ , fmpz_poly_xgcd_modular+ , _fmpz_poly_xgcd+ , fmpz_poly_xgcd+ , _fmpz_poly_lcm+ , fmpz_poly_lcm+ , _fmpz_poly_resultant_modular+ , fmpz_poly_resultant_modular+ , fmpz_poly_resultant_modular_div+ , _fmpz_poly_resultant_euclidean+ , fmpz_poly_resultant_euclidean+ , _fmpz_poly_resultant+ , fmpz_poly_resultant+ -- * Discriminant+ , _fmpz_poly_discriminant+ , fmpz_poly_discriminant+ -- * Gaussian content+ , _fmpz_poly_content+ , fmpz_poly_content+ , _fmpz_poly_primitive_part+ , fmpz_poly_primitive_part+ -- * Square-free+ , _fmpz_poly_is_squarefree+ , fmpz_poly_is_squarefree+ -- * Euclidean division+ , _fmpz_poly_divrem_basecase+ , fmpz_poly_divrem_basecase+ , _fmpz_poly_divrem_divconquer_recursive+ , _fmpz_poly_divrem_divconquer+ , fmpz_poly_divrem_divconquer+ , _fmpz_poly_divrem+ , fmpz_poly_divrem+ , _fmpz_poly_div_basecase+ , fmpz_poly_div_basecase+ , _fmpz_poly_divremlow_divconquer_recursive+ , _fmpz_poly_div_divconquer_recursive+ , _fmpz_poly_div_divconquer+ , fmpz_poly_div_divconquer+ , _fmpz_poly_div+ , fmpz_poly_div+ , _fmpz_poly_rem_basecase+ , fmpz_poly_rem_basecase+ , _fmpz_poly_rem+ , fmpz_poly_rem+ , _fmpz_poly_div_root+ , fmpz_poly_div_root+ -- * Division with precomputed inverse+ , _fmpz_poly_preinvert+ , fmpz_poly_preinvert+ , _fmpz_poly_div_preinv+ , fmpz_poly_div_preinv+ , _fmpz_poly_divrem_preinv+ , fmpz_poly_divrem_preinv+ , _fmpz_poly_powers_precompute+ , fmpz_poly_powers_precompute+ , _fmpz_poly_powers_clear+ , fmpz_poly_powers_clear+ , _fmpz_poly_rem_powers_precomp+ , fmpz_poly_rem_powers_precomp+ -- * Divisibility testing+ , _fmpz_poly_divides+ , fmpz_poly_divides+ , fmpz_poly_remove+ -- * Division mod p+ , fmpz_poly_divlow_smodp+ , fmpz_poly_divhigh_smodp+ -- * Power series division+ , _fmpz_poly_inv_series_basecase+ , fmpz_poly_inv_series_basecase+ , _fmpz_poly_inv_series_newton+ , fmpz_poly_inv_series_newton+ , _fmpz_poly_inv_series+ , fmpz_poly_inv_series+ , _fmpz_poly_div_series_basecase+ , _fmpz_poly_div_series_divconquer+ , _fmpz_poly_div_series+ , fmpz_poly_div_series_basecase+ , fmpz_poly_div_series_divconquer+ , fmpz_poly_div_series+ -- * Pseudo division+ , _fmpz_poly_pseudo_divrem_basecase+ , fmpz_poly_pseudo_divrem_basecase+ , _fmpz_poly_pseudo_divrem_divconquer+ , fmpz_poly_pseudo_divrem_divconquer+ , _fmpz_poly_pseudo_divrem_cohen+ , fmpz_poly_pseudo_divrem_cohen+ , _fmpz_poly_pseudo_rem_cohen+ , fmpz_poly_pseudo_rem_cohen+ --, _fmpz_poly_pseudo_divrem+ --, fmpz_poly_pseudo_divrem+ , _fmpz_poly_pseudo_div+ , fmpz_poly_pseudo_div+ , _fmpz_poly_pseudo_rem+ , fmpz_poly_pseudo_rem+ -- * Derivative+ , _fmpz_poly_derivative+ , fmpz_poly_derivative+ , _fmpz_poly_nth_derivative+ , fmpz_poly_nth_derivative+ -- * Evaluation+ , _fmpz_poly_evaluate_divconquer_fmpz+ , fmpz_poly_evaluate_divconquer_fmpz+ , _fmpz_poly_evaluate_horner_fmpz+ , fmpz_poly_evaluate_horner_fmpz+ , _fmpz_poly_evaluate_fmpz+ , fmpz_poly_evaluate_fmpz+ , _fmpz_poly_evaluate_divconquer_fmpq+ , fmpz_poly_evaluate_divconquer_fmpq+ , _fmpz_poly_evaluate_horner_fmpq+ , fmpz_poly_evaluate_horner_fmpq+ , _fmpz_poly_evaluate_fmpq+ , fmpz_poly_evaluate_fmpq+ -- , fmpz_poly_evaluate_mpq+ , _fmpz_poly_evaluate_mod+ , fmpz_poly_evaluate_mod+ , fmpz_poly_evaluate_fmpz_vec+ , _fmpz_poly_evaluate_horner_d+ , fmpz_poly_evaluate_horner_d+ , _fmpz_poly_evaluate_horner_d_2exp+ , fmpz_poly_evaluate_horner_d_2exp+ , _fmpz_poly_evaluate_horner_d_2exp2+ -- * Newton basis+ , _fmpz_poly_monomial_to_newton+ , _fmpz_poly_newton_to_monomial+ -- * Interpolation+ , fmpz_poly_interpolate_fmpz_vec+ -- * Composition+ , _fmpz_poly_compose_horner+ , fmpz_poly_compose_horner+ , _fmpz_poly_compose_divconquer+ , fmpz_poly_compose_divconquer+ , _fmpz_poly_compose+ , fmpz_poly_compose+ -- * Inflation and deflation+ , fmpz_poly_inflate+ , fmpz_poly_deflate+ , fmpz_poly_deflation+ -- * Taylor shift+ , _fmpz_poly_taylor_shift_horner+ , fmpz_poly_taylor_shift_horner+ , _fmpz_poly_taylor_shift_divconquer+ , fmpz_poly_taylor_shift_divconquer+ , _fmpz_poly_taylor_shift_multi_mod+ , fmpz_poly_taylor_shift_multi_mod+ , _fmpz_poly_taylor_shift+ , fmpz_poly_taylor_shift+ -- * Power series composition+ , _fmpz_poly_compose_series_horner+ , fmpz_poly_compose_series_horner+ , _fmpz_poly_compose_series_brent_kung+ , fmpz_poly_compose_series_brent_kung+ , _fmpz_poly_compose_series+ , fmpz_poly_compose_series+ -- * Power series reversion+ , _fmpz_poly_revert_series_lagrange+ , fmpz_poly_revert_series_lagrange+ , _fmpz_poly_revert_series_lagrange_fast+ , fmpz_poly_revert_series_lagrange_fast+ , _fmpz_poly_revert_series_newton+ , fmpz_poly_revert_series_newton+ , _fmpz_poly_revert_series+ , fmpz_poly_revert_series+ -- * Square root+ , _fmpz_poly_sqrtrem_classical+ , fmpz_poly_sqrtrem_classical+ , _fmpz_poly_sqrtrem_divconquer+ , fmpz_poly_sqrtrem_divconquer+ , _fmpz_poly_sqrt_classical+ , fmpz_poly_sqrt_classical+ , _fmpz_poly_sqrt_KS+ , fmpz_poly_sqrt_KS+ , _fmpz_poly_sqrt_divconquer+ , fmpz_poly_sqrt_divconquer+ , _fmpz_poly_sqrt+ , fmpz_poly_sqrt+ , _fmpz_poly_sqrt_series+ , fmpz_poly_sqrt_series+ -- * Power sums+ , _fmpz_poly_power_sums_naive+ , fmpz_poly_power_sums_naive+ , fmpz_poly_power_sums+ , _fmpz_poly_power_sums_to_poly+ , fmpz_poly_power_sums_to_poly+ -- * Signature+ , _fmpz_poly_signature+ , fmpz_poly_signature+ -- * Hensel lifting+ , fmpz_poly_hensel_build_tree+ , fmpz_poly_hensel_lift+ , fmpz_poly_hensel_lift_without_inverse+ , fmpz_poly_hensel_lift_only_inverse+ , fmpz_poly_hensel_lift_tree_recursive+ , fmpz_poly_hensel_lift_tree+ , _fmpz_poly_hensel_start_lift+ , _fmpz_poly_hensel_continue_lift+ , fmpz_poly_hensel_lift_once+ -- * Input and output+ , _fmpz_poly_print+ , fmpz_poly_print+ , _fmpz_poly_print_pretty+ , fmpz_poly_print_pretty+ , _fmpz_poly_fprint+ , fmpz_poly_fprint+ , _fmpz_poly_fprint_pretty+ , fmpz_poly_fprint_pretty+ , fmpz_poly_read+ , fmpz_poly_read_pretty+ , fmpz_poly_fread+ , fmpz_poly_fread_pretty+ -- * Modular reduction and reconstruction+ , fmpz_poly_get_nmod_poly+ , fmpz_poly_set_nmod_poly+ , fmpz_poly_set_nmod_poly_unsigned+ , _fmpz_poly_CRT_ui_precomp+ , _fmpz_poly_CRT_ui+ , fmpz_poly_CRT_ui+ -- * Products+ , _fmpz_poly_product_roots_fmpz_vec+ , fmpz_poly_product_roots_fmpz_vec+ , _fmpz_poly_product_roots_fmpq_vec+ , fmpz_poly_product_roots_fmpq_vec+ -- * Roots+ , _fmpz_poly_bound_roots+ , _fmpz_poly_num_real_roots_sturm+ , fmpz_poly_num_real_roots_sturm+ , _fmpz_poly_num_real_roots+ , fmpz_poly_num_real_roots+ -- * Minimal polynomials+ , _fmpz_poly_cyclotomic+ , fmpz_poly_cyclotomic+ , _fmpz_poly_is_cyclotomic+ , _fmpz_poly_cos_minpoly+ , _fmpz_poly_swinnerton_dyer+ -- * Orthogonal polynomials+ , _fmpz_poly_chebyshev_t+ , _fmpz_poly_chebyshev_u+ , _fmpz_poly_legendre_pt+ , fmpz_poly_legendre_pt+ , _fmpz_poly_hermite_h+ , fmpz_poly_hermite_h+ , _fmpz_poly_hermite_he+ , fmpz_poly_hermite_he+ -- * Fibonacci polynomials+ , _fmpz_poly_fibonacci+ , fmpz_poly_fibonacci+ -- THIS DOES NOT SEEM TO EXIST IN THE ACTUAL IMPLEMENTATION+ -- -- * Eulerian numbers and polynomials+ -- , arith_eulerian_polynomial+ -- * Modular forms and q-series+ , _fmpz_poly_eta_qexp+ , _fmpz_poly_theta_qexp+ -- * CLD bounds+ , fmpz_poly_CLD_bound+) where ++-- univariate polynomials over the integers ------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq+import Data.Number.Flint.NMod.Types++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpq.h>+#include <flint/fmpz_poly.h>++-- fmpz_poly_t -----------------------------------------------------------------++data FmpzPoly = FmpzPoly {-# UNPACK #-} !(ForeignPtr CFmpzPoly)+data CFmpzPoly = CFmpzPoly (Ptr CFmpz) CLong CLong++instance Storable CFmpzPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_poly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_poly_t}+ peek ptr = do+ coeffs <- #{peek fmpz_poly_struct, coeffs} ptr+ alloc <- #{peek fmpz_poly_struct, alloc } ptr+ length <- #{peek fmpz_poly_struct, length} ptr+ return $ CFmpzPoly coeffs alloc length+ poke = error "CFmpzPoly.poke: Not defined"++-- | /newFmpzPoly/+--+-- Construct a new `FmpzPoly`+newFmpzPoly = do+ p <- mallocForeignPtr+ withForeignPtr p fmpz_poly_init+ addForeignPtrFinalizer p_fmpz_poly_clear p+ return $ FmpzPoly p++-- | /withFmpzPoly/ /poly/ /f/+-- +-- Execute /f/ on /poly/+{-# INLINE withFmpzPoly #-}+withFmpzPoly (FmpzPoly p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpzPoly p,)++-- | /withNewFmpzPoly/ /poly/ /f/+-- +-- Execute /f/ on a new `FmpzPoly`+withNewFmpzPoly f = do+ x <- newFmpzPoly+ withFmpzPoly x $ \x -> f x++-- fmpz_poly_powers_precomp_t --------------------------------------------------++-- | Data structure containing the /CFmpzPolyPowersPrecomp/ pointer+data FmpzPolyPowersPrecomp = FmpzPolyPowersPrecomp+ {-# UNPACK #-} !(ForeignPtr CFmpzPolyPowersPrecomp) +type CFmpzPolyPowersPrecomp = CFlint FmpzPolyPowersPrecomp++-- fmpz_poly_factor_t ----------------------------------------------------------++-- | Data structure containing the /CFmpzPolyFactor/ pointer+data FmpzPolyFactor = FmpzPolyFactor+ {-# UNPACK #-} !(ForeignPtr CFmpzPolyFactor) +type CFmpzPolyFactor = CFlint FmpzPolyFactor++-- fmpz_poly_mul_precache_t ----------------------------------------------------++-- | Data structure containing the /CFmpzPolyMulPrecache/ pointer+data FmpzPolyMulPrecache = FmpzPolyMulPrecache+ {-# UNPACK #-} !(ForeignPtr CFmpzPolyMulPrecache) +type CFmpzPolyMulPrecache = CFlint FmpzPolyMulPrecache++-- Memory management -----------------------------------------------------------++-- | /fmpz_poly_init/ /poly/ +-- +-- Initialises @poly@ for use, setting its length to zero. A corresponding+-- call to @fmpz_poly_clear@ must be made after finishing with the+-- @fmpz_poly_t@ to free the memory used by the polynomial.+foreign import ccall "fmpz_poly.h fmpz_poly_init"+ fmpz_poly_init :: Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_init2/ /poly/ /alloc/ +-- +-- Initialises @poly@ with space for at least @alloc@ coefficients and sets+-- the length to zero. The allocated coefficients are all set to zero.+foreign import ccall "fmpz_poly.h fmpz_poly_init2"+ fmpz_poly_init2 :: Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_realloc/ /poly/ /alloc/ +-- +-- Reallocates the given polynomial to have space for @alloc@ coefficients.+-- If @alloc@ is zero the polynomial is cleared and then reinitialised. If+-- the current length is greater than @alloc@ the polynomial is first+-- truncated to length @alloc@.+foreign import ccall "fmpz_poly.h fmpz_poly_realloc"+ fmpz_poly_realloc :: Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_fit_length/ /poly/ /len/ +-- +-- If @len@ is greater than the number of coefficients currently allocated,+-- then the polynomial is reallocated to have space for at least @len@+-- coefficients. No data is lost when calling this function.+-- +-- The function efficiently deals with the case where @fit_length@ is+-- called many times in small increments by at least doubling the number of+-- allocated coefficients when length is larger than the number of+-- coefficients currently allocated.+foreign import ccall "fmpz_poly.h fmpz_poly_fit_length"+ fmpz_poly_fit_length :: Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_clear/ /poly/ +-- +-- Clears the given polynomial, releasing any memory used. It must be+-- reinitialised in order to be used again.+foreign import ccall "fmpz_poly.h fmpz_poly_clear"+ fmpz_poly_clear :: Ptr CFmpzPoly -> IO ()++foreign import ccall "fmpz_poly.h &fmpz_poly_clear"+ p_fmpz_poly_clear :: FunPtr (Ptr CFmpzPoly -> IO ())++-- | /_fmpz_poly_normalise/ /poly/ +-- +-- Sets the length of @poly@ so that the top coefficient is non-zero. If+-- all coefficients are zero, the length is set to zero. This function is+-- mainly used internally, as all functions guarantee normalisation.+foreign import ccall "fmpz_poly.h _fmpz_poly_normalise"+ _fmpz_poly_normalise :: Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_set_length/ /poly/ /newlen/ +-- +-- Demotes the coefficients of @poly@ beyond @newlen@ and sets the length+-- of @poly@ to @newlen@.+foreign import ccall "fmpz_poly.h _fmpz_poly_set_length"+ _fmpz_poly_set_length :: Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_attach_truncate/ /trunc/ /poly/ /n/ +-- +-- This function sets the uninitialised polynomial @trunc@ to the low \(n\)+-- coefficients of @poly@, or to @poly@ if the latter doesn\'t have \(n\)+-- coefficients. The polynomial @trunc@ not be cleared or used as the+-- output of any Flint functions.+foreign import ccall "fmpz_poly.h fmpz_poly_attach_truncate"+ fmpz_poly_attach_truncate :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_attach_shift/ /trunc/ /poly/ /n/ +-- +-- This function sets the uninitialised polynomial @trunc@ to the high+-- coefficients of @poly@, i.e. the coefficients not among the low \(n\)+-- coefficients of @poly@. If the latter doesn\'t have \(n\) coefficients+-- @trunc@ is set to the zero polynomial. The polynomial @trunc@ not be+-- cleared or used as the output of any Flint functions.+foreign import ccall "fmpz_poly.h fmpz_poly_attach_shift"+ fmpz_poly_attach_shift :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- Polynomial parameters -------------------------------------------------------++-- | /fmpz_poly_length/ /poly/ +-- +-- Returns the length of @poly@. The zero polynomial has length zero.+foreign import ccall "fmpz_poly.h fmpz_poly_length"+ fmpz_poly_length :: Ptr CFmpzPoly -> IO CLong++-- | /fmpz_poly_degree/ /poly/ +-- +-- Returns the degree of @poly@, which is one less than its length.+foreign import ccall "fmpz_poly.h fmpz_poly_degree"+ fmpz_poly_degree :: Ptr CFmpzPoly -> IO CLong++-- Assignment and basic manipulation -------------------------------------------++-- | /fmpz_poly_set/ /poly1/ /poly2/ +-- +-- Sets @poly1@ to equal @poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_set"+ fmpz_poly_set :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_set_si/ /poly/ /c/ +-- +-- Sets @poly@ to the signed integer @c@.+foreign import ccall "fmpz_poly.h fmpz_poly_set_si"+ fmpz_poly_set_si :: Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_set_ui/ /poly/ /c/ +-- +-- Sets @poly@ to the unsigned integer @c@.+foreign import ccall "fmpz_poly.h fmpz_poly_set_ui"+ fmpz_poly_set_ui :: Ptr CFmpzPoly -> CULong -> IO ()++-- | /fmpz_poly_set_fmpz/ /poly/ /c/ +-- +-- Sets @poly@ to the integer @c@.+foreign import ccall "fmpz_poly.h fmpz_poly_set_fmpz"+ fmpz_poly_set_fmpz :: Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- -- | /fmpz_poly_set_mpz/ /poly/ /c/ +-- -- +-- -- Sets @poly@ to the integer @c@.+-- foreign import ccall "fmpz_poly.h fmpz_poly_set_mpz"+-- fmpz_poly_set_mpz :: Ptr CFmpzPoly -> Ptr CMpz -> IO ()++-- | /_fmpz_poly_set_str/ /poly/ /str/ +-- +-- Sets @poly@ to the polynomial encoded in the null-terminated string+-- @str@. Assumes that @poly@ is allocated as a sufficiently large array+-- suitable for the number of coefficients present in @str@.+-- +-- Returns \(0\) if no error occurred. Otherwise, returns a non-zero value,+-- in which case the resulting value of @poly@ is undefined. If @str@ is+-- not null-terminated, calling this method might result in a segmentation+-- fault.+foreign import ccall "fmpz_poly.h _fmpz_poly_set_str"+ _fmpz_poly_set_str :: Ptr CFmpz -> CString -> IO CInt++-- | /fmpz_poly_set_str/ /poly/ /str/ +-- +-- Imports a polynomial from a null-terminated string. If the string @str@+-- represents a valid polynomial returns \(0\), otherwise returns \(1\).+-- +-- Returns \(0\) if no error occurred. Otherwise, returns a non-zero value,+-- in which case the resulting value of @poly@ is undefined. If @str@ is+-- not null-terminated, calling this method might result in a segmentation+-- fault.+foreign import ccall "fmpz_poly.h fmpz_poly_set_str"+ fmpz_poly_set_str :: Ptr CFmpzPoly -> CString -> IO CInt++-- | /_fmpz_poly_get_str/ /poly/ /len/ +-- +-- Returns the plain FLINT string representation of the polynomial+-- @(poly, len)@.+foreign import ccall "fmpz_poly.h _fmpz_poly_get_str"+ _fmpz_poly_get_str :: Ptr CFmpz -> CLong -> IO CString++-- | /fmpz_poly_get_str/ /poly/ +-- +-- Returns the plain FLINT string representation of the polynomial @poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_get_str"+ fmpz_poly_get_str :: Ptr CFmpzPoly -> IO CString++-- | /_fmpz_poly_get_str_pretty/ /poly/ /len/ /x/ +-- +-- Returns a pretty representation of the polynomial @(poly, len)@ using+-- the null-terminated string @x@ as the variable name.+foreign import ccall "fmpz_poly.h _fmpz_poly_get_str_pretty"+ _fmpz_poly_get_str_pretty :: Ptr CFmpz -> CLong -> CString -> IO CString++-- | /fmpz_poly_get_str_pretty/ /poly/ /x/ +-- +-- Returns a pretty representation of the polynomial @poly@ using the+-- null-terminated string @x@ as the variable name.+foreign import ccall "fmpz_poly.h fmpz_poly_get_str_pretty"+ fmpz_poly_get_str_pretty :: Ptr CFmpzPoly -> CString -> IO CString++-- | /fmpz_poly_zero/ /poly/ +-- +-- Sets @poly@ to the zero polynomial.+foreign import ccall "fmpz_poly.h fmpz_poly_zero"+ fmpz_poly_zero :: Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_one/ /poly/ +-- +-- Sets @poly@ to the constant polynomial one.+foreign import ccall "fmpz_poly.h fmpz_poly_one"+ fmpz_poly_one :: Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_zero_coeffs/ /poly/ /i/ /j/ +-- +-- Sets the coefficients of \(x^i, \dotsc, x^{j-1}\) to zero.+foreign import ccall "fmpz_poly.h fmpz_poly_zero_coeffs"+ fmpz_poly_zero_coeffs :: Ptr CFmpzPoly -> CLong -> CLong -> IO ()++-- | /fmpz_poly_swap/ /poly1/ /poly2/ +-- +-- Swaps @poly1@ and @poly2@. This is done efficiently without copying data+-- by swapping pointers, etc.+foreign import ccall "fmpz_poly.h fmpz_poly_swap"+ fmpz_poly_swap :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_reverse/ /res/ /poly/ /len/ /n/ +-- +-- Sets @(res, n)@ to the reverse of @(poly, n)@, where @poly@ is in fact+-- an array of length @len@. Assumes that @0 \< len \<= n@. Supports+-- aliasing of @res@ and @poly@, but the behaviour is undefined in case of+-- partial overlap.+foreign import ccall "fmpz_poly.h _fmpz_poly_reverse"+ _fmpz_poly_reverse :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_reverse/ /res/ /poly/ /n/ +-- +-- This function considers the polynomial @poly@ to be of length \(n\),+-- notionally truncating and zero padding if required, and reverses the+-- result. Since the function normalises its result @res@ may be of length+-- less than \(n\).+foreign import ccall "fmpz_poly.h fmpz_poly_reverse"+ fmpz_poly_reverse :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_truncate/ /poly/ /newlen/ +-- +-- If the current length of @poly@ is greater than @newlen@, it is+-- truncated to have the given length. Discarded coefficients are not+-- necessarily set to zero.+foreign import ccall "fmpz_poly.h fmpz_poly_truncate"+ fmpz_poly_truncate :: Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_set_trunc/ /res/ /poly/ /n/ +-- +-- Sets @res@ to a copy of @poly@, truncated to length @n@.+foreign import ccall "fmpz_poly.h fmpz_poly_set_trunc"+ fmpz_poly_set_trunc :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- Randomisation ---------------------------------------------------------------++-- | /fmpz_poly_randtest/ /f/ /state/ /len/ /bits/ +-- +-- Sets \(f\) to a random polynomial with up to the given length and where+-- each coefficient has up to the given number of bits. The coefficients+-- are signed randomly. One must call @flint_randinit@ before calling this+-- function.+foreign import ccall "fmpz_poly.h fmpz_poly_randtest"+ fmpz_poly_randtest :: Ptr CFmpzPoly -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- | /fmpz_poly_randtest_unsigned/ /f/ /state/ /len/ /bits/ +-- +-- Sets \(f\) to a random polynomial with up to the given length and where+-- each coefficient has up to the given number of bits. One must call+-- @flint_randinit@ before calling this function.+foreign import ccall "fmpz_poly.h fmpz_poly_randtest_unsigned"+ fmpz_poly_randtest_unsigned :: Ptr CFmpzPoly -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- | /fmpz_poly_randtest_not_zero/ /f/ /state/ /len/ /bits/ +-- +-- As for @fmpz_poly_randtest@ except that @len@ and bits may not be zero+-- and the polynomial generated is guaranteed not to be the zero+-- polynomial. One must call @flint_randinit@ before calling this function.+foreign import ccall "fmpz_poly.h fmpz_poly_randtest_not_zero"+ fmpz_poly_randtest_not_zero :: Ptr CFmpzPoly -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- | /fmpz_poly_randtest_no_real_root/ /p/ /state/ /len/ /bits/ +-- +-- Sets @p@ to a random polynomial without any real root, whose length is+-- up to @len@ and where each coefficient has up to the given number of+-- bits. One must call @flint_randinit@ before calling this function.+foreign import ccall "fmpz_poly.h fmpz_poly_randtest_no_real_root"+ fmpz_poly_randtest_no_real_root :: Ptr CFmpzPoly -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- Getting and setting coefficients --------------------------------------------++-- | /fmpz_poly_get_coeff_fmpz/ /x/ /poly/ /n/ +-- +-- Sets \(x\) to the \(n\)-th coefficient of @poly@. Coefficient numbering+-- is from zero and if \(n\) is set to a value beyond the end of the+-- polynomial, zero is returned.+foreign import ccall "fmpz_poly.h fmpz_poly_get_coeff_fmpz"+ fmpz_poly_get_coeff_fmpz :: Ptr CFmpz -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_get_coeff_si/ /poly/ /n/ +-- +-- Returns coefficient \(n\) of @poly@ as a @slong@. The result is+-- undefined if the value does not fit into a @slong@. Coefficient+-- numbering is from zero and if \(n\) is set to a value beyond the end of+-- the polynomial, zero is returned.+foreign import ccall "fmpz_poly.h fmpz_poly_get_coeff_si"+ fmpz_poly_get_coeff_si :: Ptr CFmpzPoly -> CLong -> IO CLong++-- | /fmpz_poly_get_coeff_ui/ /poly/ /n/ +-- +-- Returns coefficient \(n\) of @poly@ as a @ulong@. The result is+-- undefined if the value does not fit into a @ulong@. Coefficient+-- numbering is from zero and if \(n\) is set to a value beyond the end of+-- the polynomial, zero is returned.+foreign import ccall "fmpz_poly.h fmpz_poly_get_coeff_ui"+ fmpz_poly_get_coeff_ui :: Ptr CFmpzPoly -> CLong -> IO CULong++-- | /fmpz_poly_get_coeff_ptr/ /poly/ /n/ +-- +-- Returns a reference to the coefficient of \(x^n\) in the polynomial, as+-- an @fmpz *@. This function is provided so that individual coefficients+-- can be accessed and operated on by functions in the @fmpz@ module. This+-- function does not make a copy of the data, but returns a reference to+-- the actual coefficient.+-- +-- Returns @NULL@ when \(n\) exceeds the degree of the polynomial.+-- +-- This function is implemented as a macro.+fmpz_poly_get_coeff_ptr :: Ptr CFmpzPoly -> CLong -> IO (Ptr CFmpz)+fmpz_poly_get_coeff_ptr poly j = do+ CFmpzPoly coeffs _ n <- peek poly+ return $ if 0 <= j && j < n then+ (coeffs `advancePtr` (fromIntegral j))+ else+ nullPtr+-- | /fmpz_poly_lead/ /poly/ +-- +-- Returns a reference to the leading coefficient of the polynomial, as an+-- @fmpz *@. This function is provided so that the leading coefficient can+-- be easily accessed and operated on by functions in the @fmpz@ module.+-- This function does not make a copy of the data, but returns a reference+-- to the actual coefficient.+-- +-- Returns @NULL@ when the polynomial is zero.+-- +-- This function is implemented as a macro.+fmpz_poly_lead :: Ptr CFmpzPoly -> IO (Ptr CFmpz)+fmpz_poly_lead poly = do+ CFmpzPoly coeffs _ n <- peek poly+ return $ coeffs `advancePtr` (fromIntegral $ pred $ n)++-- | /fmpz_poly_set_coeff_fmpz/ /poly/ /n/ /x/ +-- +-- Sets coefficient \(n\) of @poly@ to the @fmpz@ value @x@. Coefficient+-- numbering starts from zero and if \(n\) is beyond the current length of+-- @poly@ then the polynomial is extended and zero coefficients inserted if+-- necessary.+foreign import ccall "fmpz_poly.h fmpz_poly_set_coeff_fmpz"+ fmpz_poly_set_coeff_fmpz :: Ptr CFmpzPoly -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_set_coeff_si/ /poly/ /n/ /x/ +-- +-- Sets coefficient \(n\) of @poly@ to the @slong@ value @x@. Coefficient+-- numbering starts from zero and if \(n\) is beyond the current length of+-- @poly@ then the polynomial is extended and zero coefficients inserted if+-- necessary.+foreign import ccall "fmpz_poly.h fmpz_poly_set_coeff_si"+ fmpz_poly_set_coeff_si :: Ptr CFmpzPoly -> CLong -> CLong -> IO ()++-- | /fmpz_poly_set_coeff_ui/ /poly/ /n/ /x/ +-- +-- Sets coefficient \(n\) of @poly@ to the @ulong@ value @x@. Coefficient+-- numbering starts from zero and if \(n\) is beyond the current length of+-- @poly@ then the polynomial is extended and zero coefficients inserted if+-- necessary.+foreign import ccall "fmpz_poly.h fmpz_poly_set_coeff_ui"+ fmpz_poly_set_coeff_ui :: Ptr CFmpzPoly -> CLong -> CULong -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fmpz_poly_equal/ /poly1/ /poly2/ +-- +-- Returns \(1\) if @poly1@ is equal to @poly2@, otherwise returns \(0\).+-- The polynomials are assumed to be normalised.+foreign import ccall "fmpz_poly.h fmpz_poly_equal"+ fmpz_poly_equal :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO CInt++-- | /fmpz_poly_equal_trunc/ /poly1/ /poly2/ /n/ +-- +-- Return \(1\) if @poly1@ and @poly2@, notionally truncated to length+-- \(n\) are equal, otherwise return \(0\).+foreign import ccall "fmpz_poly.h fmpz_poly_equal_trunc"+ fmpz_poly_equal_trunc :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO CInt++-- | /fmpz_poly_is_zero/ /poly/ +-- +-- Returns \(1\) if the polynomial is zero and \(0\) otherwise.+-- +-- This function is implemented as a macro.+fmpz_poly_is_zero :: Ptr CFmpzPoly -> IO CInt+fmpz_poly_is_zero poly = do+ CFmpzPoly _ _ n <- peek poly+ return $ if n == 0 then 1 else 0+ +-- | /fmpz_poly_is_one/ /poly/ +-- +-- Returns \(1\) if the polynomial is one and \(0\) otherwise.+foreign import ccall "fmpz_poly.h fmpz_poly_is_one"+ fmpz_poly_is_one :: Ptr CFmpzPoly -> IO CInt++-- | /fmpz_poly_is_unit/ /poly/ +-- +-- Returns \(1\) is the polynomial is the constant polynomial \(\pm 1\),+-- and \(0\) otherwise.+foreign import ccall "fmpz_poly.h fmpz_poly_is_unit"+ fmpz_poly_is_unit :: Ptr CFmpzPoly -> IO CInt++-- | /fmpz_poly_is_gen/ /poly/ +-- +-- Returns \(1\) if the polynomial is the degree \(1\) polynomial \(x\),+-- and \(0\) otherwise.+foreign import ccall "fmpz_poly.h fmpz_poly_is_gen"+ fmpz_poly_is_gen :: Ptr CFmpzPoly -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /_fmpz_poly_add/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @res@ to the sum of @(poly1, len1)@ and @(poly2, len2)@. It is+-- assumed that @res@ has sufficient space for the longer of the two+-- polynomials.+foreign import ccall "fmpz_poly.h _fmpz_poly_add"+ _fmpz_poly_add :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_add/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the sum of @poly1@ and @poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_add"+ fmpz_poly_add :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_add_series/ /res/ /poly1/ /poly2/ /n/ +-- +-- Notionally truncate @poly1@ and @poly2@ to length \(n\) and then set+-- @res@ to the sum.+foreign import ccall "fmpz_poly.h fmpz_poly_add_series"+ fmpz_poly_add_series :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /_fmpz_poly_sub/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @res@ to @(poly1, len1)@ minus @(poly2, len2)@. It is assumed that+-- @res@ has sufficient space for the longer of the two polynomials.+foreign import ccall "fmpz_poly.h _fmpz_poly_sub"+ _fmpz_poly_sub :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_sub/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to @poly1@ minus @poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_sub"+ fmpz_poly_sub :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_sub_series/ /res/ /poly1/ /poly2/ /n/ +-- +-- Notionally truncate @poly1@ and @poly2@ to length \(n\) and then set+-- @res@ to the sum.+foreign import ccall "fmpz_poly.h fmpz_poly_sub_series"+ fmpz_poly_sub_series :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /fmpz_poly_neg/ /res/ /poly/ +-- +-- Sets @res@ to @-poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_neg"+ fmpz_poly_neg :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- Scalar absolute value, multiplication and division --------------------------++-- | /fmpz_poly_scalar_abs/ /res/ /poly/ +-- +-- Sets @poly1@ to the polynomial whose coefficients are the absolute value+-- of those of @poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_abs"+ fmpz_poly_scalar_abs :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_scalar_mul_fmpz/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ times \(x\).+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_mul_fmpz"+ fmpz_poly_scalar_mul_fmpz :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- -- | /fmpz_poly_scalar_mul_mpz/ /poly1/ /poly2/ /x/ +-- -- +-- -- Sets @poly1@ to @poly2@ times the @mpz_t@ \(x\).+-- foreign import ccall "fmpz_poly.h fmpz_poly_scalar_mul_mpz"+-- fmpz_poly_scalar_mul_mpz :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CMpz -> IO ()++-- | /fmpz_poly_scalar_mul_si/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ times the signed @slong x@.+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_mul_si"+ fmpz_poly_scalar_mul_si :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_scalar_mul_ui/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ times the @ulong x@.+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_mul_ui"+ fmpz_poly_scalar_mul_ui :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /fmpz_poly_scalar_mul_2exp/ /poly1/ /poly2/ /exp/ +-- +-- Sets @poly1@ to @poly2@ times @2^exp@.+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_mul_2exp"+ fmpz_poly_scalar_mul_2exp :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++foreign import ccall "fmpz_poly.h fmpz_poly_scalar_addmul_si"+ fmpz_poly_scalar_addmul_si :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++foreign import ccall "fmpz_poly.h fmpz_poly_scalar_addmul_ui"+ fmpz_poly_scalar_addmul_ui :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /fmpz_poly_scalar_addmul_fmpz/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly1 + x * poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_addmul_fmpz"+ fmpz_poly_scalar_addmul_fmpz :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_scalar_submul_fmpz/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly1 - x * poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_submul_fmpz"+ fmpz_poly_scalar_submul_fmpz :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_scalar_fdiv_fmpz/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ divided by the @fmpz_t x@, rounding coefficients+-- down toward \(- \infty\).+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_fdiv_fmpz"+ fmpz_poly_scalar_fdiv_fmpz :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- -- | /fmpz_poly_scalar_fdiv_mpz/ /poly1/ /poly2/ /x/ +-- -- +-- -- Sets @poly1@ to @poly2@ divided by the @mpz_t x@, rounding coefficients+-- -- down toward \(- \infty\).+-- foreign import ccall "fmpz_poly.h fmpz_poly_scalar_fdiv_mpz"+-- fmpz_poly_scalar_fdiv_mpz :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CMpz -> IO ()++-- | /fmpz_poly_scalar_fdiv_si/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ divided by the @slong x@, rounding coefficients+-- down toward \(- \infty\).+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_fdiv_si"+ fmpz_poly_scalar_fdiv_si :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_scalar_fdiv_ui/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ divided by the @ulong x@, rounding coefficients+-- down toward \(- \infty\).+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_fdiv_ui"+ fmpz_poly_scalar_fdiv_ui :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /fmpz_poly_scalar_fdiv_2exp/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ divided by @2^x@, rounding coefficients down+-- toward \(- \infty\).+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_fdiv_2exp"+ fmpz_poly_scalar_fdiv_2exp :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /fmpz_poly_scalar_tdiv_fmpz/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ divided by the @fmpz_t x@, rounding coefficients+-- toward \(0\).+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_tdiv_fmpz"+ fmpz_poly_scalar_tdiv_fmpz :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_scalar_tdiv_si/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ divided by the @slong x@, rounding coefficients+-- toward \(0\).+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_tdiv_si"+ fmpz_poly_scalar_tdiv_si :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_scalar_tdiv_ui/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ divided by the @ulong x@, rounding coefficients+-- toward \(0\).+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_tdiv_ui"+ fmpz_poly_scalar_tdiv_ui :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /fmpz_poly_scalar_tdiv_2exp/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ divided by @2^x@, rounding coefficients toward+-- \(0\).+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_tdiv_2exp"+ fmpz_poly_scalar_tdiv_2exp :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /fmpz_poly_scalar_divexact_fmpz/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ divided by the @fmpz_t x@, assuming the division+-- is exact for every coefficient.+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_divexact_fmpz"+ fmpz_poly_scalar_divexact_fmpz :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- -- | /fmpz_poly_scalar_divexact_mpz/ /poly1/ /poly2/ /x/ +-- -- +-- -- Sets @poly1@ to @poly2@ divided by the @mpz_t x@, assuming the+-- -- coefficient is exact for every coefficient.+-- foreign import ccall "fmpz_poly.h fmpz_poly_scalar_divexact_mpz"+-- fmpz_poly_scalar_divexact_mpz :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CMpz -> IO ()++-- | /fmpz_poly_scalar_divexact_si/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ divided by the @slong x@, assuming the+-- coefficient is exact for every coefficient.+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_divexact_si"+ fmpz_poly_scalar_divexact_si :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_scalar_divexact_ui/ /poly1/ /poly2/ /x/ +-- +-- Sets @poly1@ to @poly2@ divided by the @ulong x@, assuming the+-- coefficient is exact for every coefficient.+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_divexact_ui"+ fmpz_poly_scalar_divexact_ui :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /fmpz_poly_scalar_mod_fmpz/ /poly1/ /poly2/ /p/ +-- +-- Sets @poly1@ to @poly2@, reducing each coefficient modulo \(p > 0\).+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_mod_fmpz"+ fmpz_poly_scalar_mod_fmpz :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_scalar_smod_fmpz/ /poly1/ /poly2/ /p/ +-- +-- Sets @poly1@ to @poly2@, symmetrically reducing each coefficient modulo+-- \(p > 0\), that is, choosing the unique representative in the interval+-- \((-p/2, p/2]\).+foreign import ccall "fmpz_poly.h fmpz_poly_scalar_smod_fmpz"+ fmpz_poly_scalar_smod_fmpz :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /_fmpz_poly_remove_content_2exp/ /pol/ /len/ +-- +-- Remove the 2-content of @pol@ and return the number \(k\) that is the+-- maximal non-negative integer so that \(2^k\) divides all coefficients of+-- the polynomial. For the zero polynomial, \(0\) is returned.+foreign import ccall "fmpz_poly.h _fmpz_poly_remove_content_2exp"+ _fmpz_poly_remove_content_2exp :: Ptr CFmpz -> CLong -> IO CLong++-- | /_fmpz_poly_scale_2exp/ /pol/ /len/ /k/ +-- +-- Scale @(pol, len)@ to \(p(2^k X)\) in-place and divide by the 2-content+-- (so that the gcd of coefficients is odd). If @k@ is negative the+-- polynomial is multiplied by \(2^{kd}\).+foreign import ccall "fmpz_poly.h _fmpz_poly_scale_2exp"+ _fmpz_poly_scale_2exp :: Ptr CFmpz -> CLong -> CLong -> IO ()++-- Bit packing -----------------------------------------------------------------++-- | /_fmpz_poly_bit_pack/ /arr/ /poly/ /len/ /bit_size/ /negate/ +-- +-- Packs the coefficients of @poly@ into bitfields of the given @bit_size@,+-- negating the coefficients before packing if @negate@ is set to \(-1\).+foreign import ccall "fmpz_poly.h _fmpz_poly_bit_pack"+ _fmpz_poly_bit_pack :: Ptr CMp -> Ptr CFmpz -> CLong -> CFBitCnt -> CInt -> IO ()++-- | /_fmpz_poly_bit_unpack/ /poly/ /len/ /arr/ /bit_size/ /negate/ +-- +-- Unpacks the polynomial of given length from the array as packed into+-- fields of the given @bit_size@, finally negating the coefficients if+-- @negate@ is set to \(-1\). Returns borrow, which is nonzero if a leading+-- term with coefficient \(\pm1\) should be added at position @len@ of+-- @poly@.+foreign import ccall "fmpz_poly.h _fmpz_poly_bit_unpack"+ _fmpz_poly_bit_unpack :: Ptr CFmpz -> CLong -> Ptr CMp -> CFBitCnt -> CInt -> IO CInt++-- | /_fmpz_poly_bit_unpack_unsigned/ /poly/ /len/ /arr/ /bit_size/ +-- +-- Unpacks the polynomial of given length from the array as packed into+-- fields of the given @bit_size@. The coefficients are assumed to be+-- unsigned.+foreign import ccall "fmpz_poly.h _fmpz_poly_bit_unpack_unsigned"+ _fmpz_poly_bit_unpack_unsigned :: Ptr CFmpz -> CLong -> Ptr CMp -> CFBitCnt -> IO ()++-- | /fmpz_poly_bit_pack/ /f/ /poly/ /bit_size/ +-- +-- Packs @poly@ into bitfields of size @bit_size@, writing the result to+-- @f@. The sign of @f@ will be the same as that of the leading coefficient+-- of @poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_bit_pack"+ fmpz_poly_bit_pack :: Ptr CFmpz -> Ptr CFmpzPoly -> CFBitCnt -> IO ()++-- | /fmpz_poly_bit_unpack/ /poly/ /f/ /bit_size/ +-- +-- Unpacks the polynomial with signed coefficients packed into fields of+-- size @bit_size@ as represented by the integer @f@.+foreign import ccall "fmpz_poly.h fmpz_poly_bit_unpack"+ fmpz_poly_bit_unpack :: Ptr CFmpzPoly -> Ptr CFmpz -> CFBitCnt -> IO ()++-- | /fmpz_poly_bit_unpack_unsigned/ /poly/ /f/ /bit_size/ +-- +-- Unpacks the polynomial with unsigned coefficients packed into fields of+-- size @bit_size@ as represented by the integer @f@. It is required that+-- @f@ is nonnegative.+foreign import ccall "fmpz_poly.h fmpz_poly_bit_unpack_unsigned"+ fmpz_poly_bit_unpack_unsigned :: Ptr CFmpzPoly -> Ptr CFmpz -> CFBitCnt -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /_fmpz_poly_mul_classical/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @(res, len1 + len2 - 1)@ to the product of @(poly1, len1)@ and+-- @(poly2, len2)@.+-- +-- Assumes @len1@ and @len2@ are positive. Allows zero-padding of the two+-- input polynomials. No aliasing of inputs with outputs is allowed.+foreign import ccall "fmpz_poly.h _fmpz_poly_mul_classical"+ _fmpz_poly_mul_classical :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_mul_classical/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@, computed using the+-- classical or schoolbook method.+foreign import ccall "fmpz_poly.h fmpz_poly_mul_classical"+ fmpz_poly_mul_classical :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_mullow_classical/ /res/ /poly1/ /len1/ /poly2/ /len2/ /n/ +-- +-- Sets @(res, n)@ to the first \(n\) coefficients of @(poly1, len1)@+-- multiplied by @(poly2, len2)@.+-- +-- Assumes @0 \< n \<= len1 + len2 - 1@. Assumes neither @len1@ nor @len2@+-- is zero.+foreign import ccall "fmpz_poly.h _fmpz_poly_mullow_classical"+ _fmpz_poly_mullow_classical :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_mullow_classical/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the first \(n\) coefficients of @poly1 * poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_mullow_classical"+ fmpz_poly_mullow_classical :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_mulhigh_classical/ /res/ /poly1/ /len1/ /poly2/ /len2/ /start/ +-- +-- Sets the first @start@ coefficients of @res@ to zero and the remainder+-- to the corresponding coefficients of @(poly1, len1) * (poly2, len2)@.+-- +-- Assumes @start \<= len1 + len2 - 1@. Assumes neither @len1@ nor @len2@+-- is zero.+foreign import ccall "fmpz_poly.h _fmpz_poly_mulhigh_classical"+ _fmpz_poly_mulhigh_classical :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_mulhigh_classical/ /res/ /poly1/ /poly2/ /start/ +-- +-- Sets the first @start@ coefficients of @res@ to zero and the remainder+-- to the corresponding coefficients of the product of @poly1@ and @poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_mulhigh_classical"+ fmpz_poly_mulhigh_classical :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_mulmid_classical/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @res@ to the middle @len1 - len2 + 1@ coefficients of the product+-- of @(poly1, len1)@ and @(poly2, len2)@, i.e.the coefficients from degree+-- @len2 - 1@ to @len1 - 1@ inclusive. Assumes that @len1 >= len2 > 0@.+foreign import ccall "fmpz_poly.h _fmpz_poly_mulmid_classical"+ _fmpz_poly_mulmid_classical :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_mulmid_classical/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the middle @len(poly1) - len(poly2) + 1@ coefficients of+-- @poly1 * poly2@, i.e.the coefficient from degree @len2 - 1@ to+-- @len1 - 1@ inclusive. Assumes that @len1 >= len2@.+foreign import ccall "fmpz_poly.h fmpz_poly_mulmid_classical"+ fmpz_poly_mulmid_classical :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_mul_karatsuba/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @(res, len1 + len2 - 1)@ to the product of @(poly1, len1)@ and+-- @(poly2, len2)@. Assumes @len1 >= len2 > 0@. Allows zero-padding of the+-- two input polynomials. No aliasing of inputs with outputs is allowed.+foreign import ccall "fmpz_poly.h _fmpz_poly_mul_karatsuba"+ _fmpz_poly_mul_karatsuba :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_mul_karatsuba/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_mul_karatsuba"+ fmpz_poly_mul_karatsuba :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_mullow_karatsuba_n/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@ and truncates to the+-- given length. It is assumed that @poly1@ and @poly2@ are precisely the+-- given length, possibly zero padded. Assumes \(n\) is not zero.+foreign import ccall "fmpz_poly.h _fmpz_poly_mullow_karatsuba_n"+ _fmpz_poly_mullow_karatsuba_n :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_mullow_karatsuba_n/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@ and truncates to the+-- given length.+foreign import ccall "fmpz_poly.h fmpz_poly_mullow_karatsuba_n"+ fmpz_poly_mullow_karatsuba_n :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_mulhigh_karatsuba_n/ /res/ /poly1/ /poly2/ /len/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@ and truncates at the+-- top to the given length. The first @len - 1@ coefficients are set to+-- zero. It is assumed that @poly1@ and @poly2@ are precisely the given+-- length, possibly zero padded. Assumes @len@ is not zero.+foreign import ccall "fmpz_poly.h _fmpz_poly_mulhigh_karatsuba_n"+ _fmpz_poly_mulhigh_karatsuba_n :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_mulhigh_karatsuba_n/ /res/ /poly1/ /poly2/ /len/ +-- +-- Sets the first @len - 1@ coefficients of the result to zero and the+-- remaining coefficients to the corresponding coefficients of the product+-- of @poly1@ and @poly2@. Assumes @poly1@ and @poly2@ are at most of the+-- given length.+foreign import ccall "fmpz_poly.h fmpz_poly_mulhigh_karatsuba_n"+ fmpz_poly_mulhigh_karatsuba_n :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_mul_KS/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @(res, len1 + len2 - 1)@ to the product of @(poly1, len1)@ and+-- @(poly2, len2)@.+-- +-- Places no assumptions on @len1@ and @len2@. Allows zero-padding of the+-- two input polynomials. Supports aliasing of inputs and outputs.+foreign import ccall "fmpz_poly.h _fmpz_poly_mul_KS"+ _fmpz_poly_mul_KS :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_mul_KS/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_mul_KS"+ fmpz_poly_mul_KS :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_mullow_KS/ /res/ /poly1/ /len1/ /poly2/ /len2/ /n/ +-- +-- Sets @(res, n)@ to the lowest \(n\) coefficients of the product of+-- @(poly1, len1)@ and @(poly2, len2)@.+-- +-- Assumes that @len1@ and @len2@ are positive, but does allow for the+-- polynomials to be zero-padded. The polynomials may be zero, too. Assumes+-- \(n\) is positive. Supports aliasing between @res@, @poly1@ and @poly2@.+foreign import ccall "fmpz_poly.h _fmpz_poly_mullow_KS"+ _fmpz_poly_mullow_KS :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_mullow_KS/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the lowest \(n\) coefficients of the product of @poly1@+-- and @poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_mullow_KS"+ fmpz_poly_mullow_KS :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_mul_SS/ /output/ /input1/ /length1/ /input2/ /length2/ +-- +-- Sets @(output, length1 + length2 - 1)@ to the product of+-- @(input1, length1)@ and @(input2, length2)@.+-- +-- We must have @len1 > 1@ and @len2 > 1@. Allows zero-padding of the two+-- input polynomials. Supports aliasing of inputs and outputs.+foreign import ccall "fmpz_poly.h _fmpz_poly_mul_SS"+ _fmpz_poly_mul_SS :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_mul_SS/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@. Uses the+-- Sch\"{o}nhage-Strassen algorithm.+foreign import ccall "fmpz_poly.h fmpz_poly_mul_SS"+ fmpz_poly_mul_SS :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_mullow_SS/ /output/ /input1/ /length1/ /input2/ /length2/ /n/ +-- +-- Sets @(res, n)@ to the lowest \(n\) coefficients of the product of+-- @(poly1, len1)@ and @(poly2, len2)@.+-- +-- Assumes that @len1@ and @len2@ are positive, but does allow for the+-- polynomials to be zero-padded. We must have @len1 > 1@ and @len2 > 1@.+-- Assumes \(n\) is positive. Supports aliasing between @res@, @poly1@ and+-- @poly2@.+foreign import ccall "fmpz_poly.h _fmpz_poly_mullow_SS"+ _fmpz_poly_mullow_SS :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_mullow_SS/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the lowest \(n\) coefficients of the product of @poly1@+-- and @poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_mullow_SS"+ fmpz_poly_mullow_SS :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_mul/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @(res, len1 + len2 - 1)@ to the product of @(poly1, len1)@ and+-- @(poly2, len2)@. Assumes @len1 >= len2 > 0@. Allows zero-padding of the+-- two input polynomials. Does not support aliasing between the inputs and+-- the output.+foreign import ccall "fmpz_poly.h _fmpz_poly_mul"+ _fmpz_poly_mul :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_mul/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@. Chooses an optimal+-- algorithm from the choices above.+foreign import ccall "fmpz_poly.h fmpz_poly_mul"+ fmpz_poly_mul :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_mullow/ /res/ /poly1/ /len1/ /poly2/ /len2/ /n/ +-- +-- Sets @(res, n)@ to the lowest \(n\) coefficients of the product of+-- @(poly1, len1)@ and @(poly2, len2)@.+-- +-- Assumes @len1 >= len2 > 0@ and @0 \< n \<= len1 + len2 - 1@. Allows for+-- zero-padding in the inputs. Does not support aliasing between the inputs+-- and the output.+foreign import ccall "fmpz_poly.h _fmpz_poly_mullow"+ _fmpz_poly_mullow :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_mullow/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the lowest \(n\) coefficients of the product of @poly1@+-- and @poly2@.+foreign import ccall "fmpz_poly.h fmpz_poly_mullow"+ fmpz_poly_mullow :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_mulhigh_n/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets the high \(n\) coefficients of @res@ to the high \(n\) coefficients+-- of the product of @poly1@ and @poly2@, assuming the latter are precisely+-- \(n\) coefficients in length, zero padded if necessary. The remaining+-- \(n - 1\) coefficients may be arbitrary.+foreign import ccall "fmpz_poly.h fmpz_poly_mulhigh_n"+ fmpz_poly_mulhigh_n :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_mulhigh/ /res/ /poly1/ /len1/ /poly2/ /len2/ /start/ +-- +-- Sets all but the low \(n\) coefficients of \(res\) to the corresponding+-- coefficients of the product of \(poly1\) of length \(len1\) and+-- \(poly2\) of length \(len2\), the remaining coefficients being+-- arbitrary. It is assumed that \(len1 >= len2 > 0\) and that+-- \(0 < n < len1 + len2 - 1\). Aliasing of inputs is not permitted.+foreign import ccall "fmpz_poly.h _fmpz_poly_mulhigh"+ _fmpz_poly_mulhigh :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- FFT precached multiplication ------------------------------------------------++-- | /fmpz_poly_mul_SS_precache_init/ /pre/ /len1/ /bits1/ /poly2/ +-- +-- Precompute the FFT of @poly2@ to enable repeated multiplication of+-- @poly2@ by polynomials whose length does not exceed @len1@ and whose+-- number of bits per coefficient does not exceed @bits1@.+-- +-- The value @bits1@ may be negative, i.e. it may be the result of calling+-- @fmpz_poly_max_bits@. The function only considers the absolute value of+-- @bits1@.+-- +-- Suppose @len2@ is the length of @poly2@ and @len = len1 + len2 - 1@ is+-- the maximum output length of a polynomial multiplication using @pre@.+-- Then internally @len@ is rounded up to a power of two, \(2^n\) say. The+-- truncated FFT algorithm is used to smooth performance but note that it+-- can only do this in the range \((2^{n-1}, 2^n]\). Therefore, it may be+-- more efficient to recompute \(pre\) for cases where the output length+-- will fall below \(2^{n-1} + 1\). Otherwise the implementation will zero+-- pad them up to that length.+-- +-- Note that the Schoenhage-Strassen algorithm is only efficient for+-- polynomials with relatively large coefficients relative to the length of+-- the polynomials.+-- +-- Also note that there are no restrictions on the polynomials. In+-- particular the polynomial whose FFT is being precached does not have to+-- be either longer or shorter than the polynomials it is to be multiplied+-- by.+foreign import ccall "fmpz_poly.h fmpz_poly_mul_SS_precache_init"+ fmpz_poly_mul_SS_precache_init :: Ptr CFmpzPolyMulPrecache -> CLong -> CLong -> Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_mul_precache_clear/ /pre/ +-- +-- Clear the space allocated by @fmpz_poly_mul_SS_precache_init@.+foreign import ccall "fmpz_poly.h fmpz_poly_mul_precache_clear"+ fmpz_poly_mul_precache_clear :: Ptr CFmpzPolyMulPrecache -> IO ()++-- | /_fmpz_poly_mullow_SS_precache/ /output/ /input1/ /len1/ /pre/ /trunc/ +-- +-- Write into @output@ the first @trunc@ coefficients of the polynomial+-- @(input1, len1)@ by the polynomial whose FFT was precached by+-- @fmpz_poly_mul_SS_precache_init@ and stored in @pre@.+-- +-- For performance reasons it is recommended that all polynomials be+-- truncated to at most @trunc@ coefficients if possible.+foreign import ccall "fmpz_poly.h _fmpz_poly_mullow_SS_precache"+ _fmpz_poly_mullow_SS_precache :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpzPolyMulPrecache -> CLong -> IO ()++-- | /fmpz_poly_mullow_SS_precache/ /res/ /poly1/ /pre/ /n/ +-- +-- Set @res@ to the product of @poly1@ by the polynomial whose FFT was+-- precached by @fmpz_poly_mul_SS_precache_init@ (and stored in pre). The+-- result is truncated to \(n\) coefficients (and normalised).+-- +-- There are no restrictions on the length of @poly1@ other than those+-- given in the call to @fmpz_poly_mul_SS_precache_init@.+foreign import ccall "fmpz_poly.h fmpz_poly_mullow_SS_precache"+ fmpz_poly_mullow_SS_precache :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPolyMulPrecache -> CLong -> IO ()++-- | /fmpz_poly_mul_SS_precache/ /res/ /poly1/ /pre/ +-- +-- Set @res@ to the product of @poly1@ by the polynomial whose FFT was+-- precached by @fmpz_poly_mul_SS_precache_init@ (and stored in pre).+-- +-- There are no restrictions on the length of @poly1@ other than those+-- given in the call to @fmpz_poly_mul_SS_precache_init@.+foreign import ccall "fmpz_poly.h fmpz_poly_mul_SS_precache"+ fmpz_poly_mul_SS_precache :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPolyMulPrecache -> IO ()++-- Squaring --------------------------------------------------------------------++-- | /_fmpz_poly_sqr_KS/ /rop/ /op/ /len/ +-- +-- Sets @(rop, 2*len - 1)@ to the square of @(op, len)@, assuming that+-- @len > 0@.+-- +-- Supports zero-padding in @(op, len)@. Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqr_KS"+ _fmpz_poly_sqr_KS :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_sqr_KS/ /rop/ /op/ +-- +-- Sets @rop@ to the square of the polynomial @op@ using Kronecker+-- segmentation.+foreign import ccall "fmpz_poly.h fmpz_poly_sqr_KS"+ fmpz_poly_sqr_KS :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_sqr_karatsuba/ /rop/ /op/ /len/ +-- +-- Sets @(rop, 2*len - 1)@ to the square of @(op, len)@, assuming that+-- @len > 0@.+-- +-- Supports zero-padding in @(op, len)@. Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqr_karatsuba"+ _fmpz_poly_sqr_karatsuba :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_sqr_karatsuba/ /rop/ /op/ +-- +-- Sets @rop@ to the square of the polynomial @op@ using the Karatsuba+-- multiplication algorithm.+foreign import ccall "fmpz_poly.h fmpz_poly_sqr_karatsuba"+ fmpz_poly_sqr_karatsuba :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_sqr_classical/ /rop/ /op/ /len/ +-- +-- Sets @(rop, 2*len - 1)@ to the square of @(op, len)@, assuming that+-- @len > 0@.+-- +-- Supports zero-padding in @(op, len)@. Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqr_classical"+ _fmpz_poly_sqr_classical :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_sqr_classical/ /rop/ /op/ +-- +-- Sets @rop@ to the square of the polynomial @op@ using the classical or+-- schoolbook method.+foreign import ccall "fmpz_poly.h fmpz_poly_sqr_classical"+ fmpz_poly_sqr_classical :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_sqr/ /rop/ /op/ /len/ +-- +-- Sets @(rop, 2*len - 1)@ to the square of @(op, len)@, assuming that+-- @len > 0@.+-- +-- Supports zero-padding in @(op, len)@. Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqr"+ _fmpz_poly_sqr :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_sqr/ /rop/ /op/ +-- +-- Sets @rop@ to the square of the polynomial @op@.+foreign import ccall "fmpz_poly.h fmpz_poly_sqr"+ fmpz_poly_sqr :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_sqrlow_KS/ /res/ /poly/ /len/ /n/ +-- +-- Sets @(res, n)@ to the lowest \(n\) coefficients of the square of+-- @(poly, len)@.+-- +-- Assumes that @len@ is positive, but does allow for the polynomial to be+-- zero-padded. The polynomial may be zero, too. Assumes \(n\) is positive.+-- Supports aliasing between @res@ and @poly@.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqrlow_KS"+ _fmpz_poly_sqrlow_KS :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_sqrlow_KS/ /res/ /poly/ /n/ +-- +-- Sets @res@ to the lowest \(n\) coefficients of the square of @poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_sqrlow_KS"+ fmpz_poly_sqrlow_KS :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_sqrlow_karatsuba_n/ /res/ /poly/ /n/ +-- +-- Sets @(res, n)@ to the square of @(poly, n)@ truncated to length \(n\),+-- which is assumed to be positive. Allows for @poly@ to be zero-oadded.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqrlow_karatsuba_n"+ _fmpz_poly_sqrlow_karatsuba_n :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_sqrlow_karatsuba_n/ /res/ /poly/ /n/ +-- +-- Sets @res@ to the square of @poly@ and truncates to the given length.+foreign import ccall "fmpz_poly.h fmpz_poly_sqrlow_karatsuba_n"+ fmpz_poly_sqrlow_karatsuba_n :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_sqrlow_classical/ /res/ /poly/ /len/ /n/ +-- +-- Sets @(res, n)@ to the first \(n\) coefficients of the square of+-- @(poly, len)@.+-- +-- Assumes that @0 \< n \<= 2 * len - 1@.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqrlow_classical"+ _fmpz_poly_sqrlow_classical :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_sqrlow_classical/ /res/ /poly/ /n/ +-- +-- Sets @res@ to the first \(n\) coefficients of the square of @poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_sqrlow_classical"+ fmpz_poly_sqrlow_classical :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_sqrlow/ /res/ /poly/ /len/ /n/ +-- +-- Sets @(res, n)@ to the lowest \(n\) coefficients of the square of+-- @(poly, len)@.+-- +-- Assumes @len1 >= len2 > 0@ and @0 \< n \<= 2 * len - 1@. Allows for+-- zero-padding in the input. Does not support aliasing between the input+-- and the output.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqrlow"+ _fmpz_poly_sqrlow :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_sqrlow/ /res/ /poly/ /n/ +-- +-- Sets @res@ to the lowest \(n\) coefficients of the square of @poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_sqrlow"+ fmpz_poly_sqrlow :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- Powering --------------------------------------------------------------------++-- | /_fmpz_poly_pow_multinomial/ /res/ /poly/ /len/ /e/ +-- +-- Computes @res = poly^e@. This uses the J.C.P. Miller pure recurrence as+-- follows:+-- +-- If \(\ell\) is the index of the lowest non-zero coefficient in @poly@,+-- as a first step this method zeros out the lowest \(e \ell\) coefficients+-- of @res@. The recurrence above is then used to compute the remaining+-- coefficients.+-- +-- Assumes @len > 0@, @e > 0@. Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_pow_multinomial"+ _fmpz_poly_pow_multinomial :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /fmpz_poly_pow_multinomial/ /res/ /poly/ /e/ +-- +-- Computes @res = poly^e@ using a generalisation of binomial expansion+-- called the J.C.P. Miller pure recurrence [1], [2]. If \(e\) is zero,+-- returns one, so that in particular @0^0 = 1@.+-- +-- The formal statement of the recurrence is as follows. Write the input+-- polynomial as \(P(x) = p_0 + p_1 x + \dotsb + p_m x^m\) with+-- \(p_0 \neq 0\) and let+-- +-- \[`\]+-- \[P(x)^n = a(n, 0) + a(n, 1) x + \dotsb + a(n, mn) x^{mn}.\]+-- +-- Then \(a(n, 0) = p_0^n\) and, for all \(1 \leq k \leq mn\),+-- +-- \[`\]+-- \[a(n, k) = +-- (k p_0)^{-1} \sum_{i = 1}^m p_i \bigl( (n + 1) i - k \bigr) a(n, k-i).\]+-- +-- [1] D. Knuth, The Art of Computer Programming Vol. 2, Seminumerical+-- Algorithms, Third Edition (Reading, Massachusetts: Addison-Wesley, 1997)+-- +-- [2] D. Zeilberger, The J.C.P. Miller Recurrence for Exponentiating a+-- Polynomial, and its q-Analog, Journal of Difference Equations and+-- Applications, 1995, Vol. 1, pp. 57--60+foreign import ccall "fmpz_poly.h fmpz_poly_pow_multinomial"+ fmpz_poly_pow_multinomial :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /_fmpz_poly_pow_binomial/ /res/ /poly/ /e/ +-- +-- Computes @res = poly^e@ when poly is of length 2, using binomial+-- expansion.+-- +-- Assumes \(e > 0\). Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_pow_binomial"+ _fmpz_poly_pow_binomial :: Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_poly_pow_binomial/ /res/ /poly/ /e/ +-- +-- Computes @res = poly^e@ when @poly@ is of length \(2\), using binomial+-- expansion.+-- +-- If the length of @poly@ is not \(2\), raises an exception and aborts.+foreign import ccall "fmpz_poly.h fmpz_poly_pow_binomial"+ fmpz_poly_pow_binomial :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /_fmpz_poly_pow_addchains/ /res/ /poly/ /len/ /a/ /n/ +-- +-- Given a star chain \(1 = a_0 < a_1 < \dotsb < a_n = e\) computes+-- @res = poly^e@.+-- +-- A star chain is an addition chain \(1 = a_0 < a_1 < \dotsb < a_n\) such+-- that, for all \(i > 0\), \(a_i = a_{i-1} + a_j\) for some \(j < i\).+-- +-- Assumes that \(e > 2\), or equivalently \(n > 1\), and @len > 0@. Does+-- not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_pow_addchains"+ _fmpz_poly_pow_addchains :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CInt -> CInt -> IO ()++-- | /fmpz_poly_pow_addchains/ /res/ /poly/ /e/ +-- +-- Computes @res = poly^e@ using addition chains whenever+-- \(0 \leq e \leq 148\).+-- +-- If \(e > 148\), raises an exception and aborts.+foreign import ccall "fmpz_poly.h fmpz_poly_pow_addchains"+ fmpz_poly_pow_addchains :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /_fmpz_poly_pow_binexp/ /res/ /poly/ /len/ /e/ +-- +-- Sets @res = poly^e@ using left-to-right binary exponentiation as+-- described in [p. 461]< [Knu1997]>.+-- +-- Assumes that @len > 0@, @e > 1@. Assumes that @res@ is an array of+-- length at least @e*(len - 1) + 1@. Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_pow_binexp"+ _fmpz_poly_pow_binexp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /fmpz_poly_pow_binexp/ /res/ /poly/ /e/ +-- +-- Computes @res = poly^e@ using the binary exponentiation algorithm. If+-- \(e\) is zero, returns one, so that in particular @0^0 = 1@.+foreign import ccall "fmpz_poly.h fmpz_poly_pow_binexp"+ fmpz_poly_pow_binexp :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /_fmpz_poly_pow_small/ /res/ /poly/ /len/ /e/ +-- +-- Sets @res = poly^e@ whenever \(0 \leq e \leq 4\).+-- +-- Assumes that @len > 0@ and that @res@ is an array of length at least+-- @e*(len - 1) + 1@. Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_pow_small"+ _fmpz_poly_pow_small :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /_fmpz_poly_pow/ /res/ /poly/ /len/ /e/ +-- +-- Sets @res = poly^e@, assuming that @e, len > 0@ and that @res@ has space+-- for @e*(len - 1) + 1@ coefficients. Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_pow"+ _fmpz_poly_pow :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /fmpz_poly_pow/ /res/ /poly/ /e/ +-- +-- Computes @res = poly^e@. If \(e\) is zero, returns one, so that in+-- particular @0^0 = 1@.+foreign import ccall "fmpz_poly.h fmpz_poly_pow"+ fmpz_poly_pow :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /_fmpz_poly_pow_trunc/ /res/ /poly/ /e/ /n/ +-- +-- Sets @(res, n)@ to @(poly, n)@ raised to the power \(e\) and truncated+-- to length \(n\).+-- +-- Assumes that \(e, n > 0\). Allows zero-padding of @(poly, n)@. Does not+-- support aliasing of any inputs and outputs.+foreign import ccall "fmpz_poly.h _fmpz_poly_pow_trunc"+ _fmpz_poly_pow_trunc :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CLong -> IO ()++-- | /fmpz_poly_pow_trunc/ /res/ /poly/ /e/ /n/ +-- +-- Notationally raises @poly@ to the power \(e\), truncates the result to+-- length \(n\) and writes the result in @res@. This is computed much more+-- efficiently than simply powering the polynomial and truncating.+-- +-- Thus, if \(n = 0\) the result is zero. Otherwise, whenever \(e = 0\) the+-- result will be the constant polynomial equal to \(1\).+-- +-- This function can be used to raise power series to a power in an+-- efficient way.+foreign import ccall "fmpz_poly.h fmpz_poly_pow_trunc"+ fmpz_poly_pow_trunc :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> CLong -> IO ()++-- Shifting --------------------------------------------------------------------++-- | /_fmpz_poly_shift_left/ /res/ /poly/ /len/ /n/ +-- +-- Sets @(res, len + n)@ to @(poly, len)@ shifted left by \(n\)+-- coefficients.+-- +-- Inserts zero coefficients at the lower end. Assumes that @len@ and \(n\)+-- are positive, and that @res@ fits @len + n@ elements. Supports aliasing+-- between @res@ and @poly@.+foreign import ccall "fmpz_poly.h _fmpz_poly_shift_left"+ _fmpz_poly_shift_left :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_shift_left/ /res/ /poly/ /n/ +-- +-- Sets @res@ to @poly@ shifted left by \(n\) coeffs. Zero coefficients are+-- inserted.+foreign import ccall "fmpz_poly.h fmpz_poly_shift_left"+ fmpz_poly_shift_left :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_shift_right/ /res/ /poly/ /len/ /n/ +-- +-- Sets @(res, len - n)@ to @(poly, len)@ shifted right by \(n\)+-- coefficients.+-- +-- Assumes that @len@ and \(n\) are positive, that @len > n@, and that+-- @res@ fits @len - n@ elements. Supports aliasing between @res@ and+-- @poly@, although in this case the top coefficients of @poly@ are not set+-- to zero.+foreign import ccall "fmpz_poly.h _fmpz_poly_shift_right"+ _fmpz_poly_shift_right :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_shift_right/ /res/ /poly/ /n/ +-- +-- Sets @res@ to @poly@ shifted right by \(n\) coefficients. If \(n\) is+-- equal to or greater than the current length of @poly@, @res@ is set to+-- the zero polynomial.+foreign import ccall "fmpz_poly.h fmpz_poly_shift_right"+ fmpz_poly_shift_right :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- Bit sizes and norms ---------------------------------------------------------++-- | /fmpz_poly_max_limbs/ /poly/ +-- +-- Returns the maximum number of limbs required to store the absolute value+-- of coefficients of @poly@. If @poly@ is zero, returns \(0\).+foreign import ccall "fmpz_poly.h fmpz_poly_max_limbs"+ fmpz_poly_max_limbs :: Ptr CFmpzPoly -> IO CULong++-- | /fmpz_poly_max_bits/ /poly/ +-- +-- Computes the maximum number of bits \(b\) required to store the absolute+-- value of coefficients of @poly@. If all the coefficients of @poly@ are+-- non-negative, \(b\) is returned, otherwise \(-b\) is returned.+foreign import ccall "fmpz_poly.h fmpz_poly_max_bits"+ fmpz_poly_max_bits :: Ptr CFmpzPoly -> IO CLong++-- | /fmpz_poly_height/ /height/ /poly/ +-- +-- Computes the height of @poly@, defined as the largest of the absolute+-- values the coefficients of @poly@. Equivalently, this gives the infinity+-- norm of the coefficients. If @poly@ is zero, the height is \(0\).+foreign import ccall "fmpz_poly.h fmpz_poly_height"+ fmpz_poly_height :: Ptr CFmpz -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_2norm/ /res/ /poly/ /len/ +-- +-- Sets @res@ to the Euclidean norm of @(poly, len)@, that is, the integer+-- square root of the sum of the squares of the coefficients of @poly@.+foreign import ccall "fmpz_poly.h _fmpz_poly_2norm"+ _fmpz_poly_2norm :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_2norm/ /res/ /poly/ +-- +-- Sets @res@ to the Euclidean norm of @poly@, that is, the integer square+-- root of the sum of the squares of the coefficients of @poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_2norm"+ fmpz_poly_2norm :: Ptr CFmpz -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_2norm_normalised_bits/ /poly/ /len/ +-- +-- Returns an upper bound on the number of bits of the normalised Euclidean+-- norm of @(poly, len)@, i.e. the number of bits of the Euclidean norm+-- divided by the absolute value of the leading coefficient. The returned+-- value will be no more than 1 bit too large.+-- +-- This is used in the computation of the Landau-Mignotte bound.+-- +-- It is assumed that @len > 0@. The result only makes sense if the leading+-- coefficient is nonzero.+foreign import ccall "fmpz_poly.h _fmpz_poly_2norm_normalised_bits"+ _fmpz_poly_2norm_normalised_bits :: Ptr CFmpz -> CLong -> IO CMpLimb++-- Greatest common divisor -----------------------------------------------------++-- | /_fmpz_poly_gcd_subresultant/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Computes the greatest common divisor @(res, len2)@ of @(poly1, len1)@+-- and @(poly2, len2)@, assuming @len1 >= len2 > 0@. The result is+-- normalised to have positive leading coefficient. Aliasing between @res@,+-- @poly1@ and @poly2@ is supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_gcd_subresultant"+ _fmpz_poly_gcd_subresultant :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_gcd_subresultant/ /res/ /poly1/ /poly2/ +-- +-- Computes the greatest common divisor @res@ of @poly1@ and @poly2@,+-- normalised to have non-negative leading coefficient.+-- +-- This function uses the subresultant algorithm as described in [Algorithm+-- 3.3.1]< [Coh1996]>.+foreign import ccall "fmpz_poly.h fmpz_poly_gcd_subresultant"+ fmpz_poly_gcd_subresultant :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_gcd_heuristic/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Computes the greatest common divisor @(res, len2)@ of @(poly1, len1)@+-- and @(poly2, len2)@, assuming @len1 >= len2 > 0@. The result is+-- normalised to have positive leading coefficient. Aliasing between @res@,+-- @poly1@ and @poly2@ is not supported. The function may not always+-- succeed in finding the GCD. If it fails, the function returns 0,+-- otherwise it returns 1.+foreign import ccall "fmpz_poly.h _fmpz_poly_gcd_heuristic"+ _fmpz_poly_gcd_heuristic :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_poly_gcd_heuristic/ /res/ /poly1/ /poly2/ +-- +-- Computes the greatest common divisor @res@ of @poly1@ and @poly2@,+-- normalised to have non-negative leading coefficient.+-- +-- The function may not always succeed in finding the GCD. If it fails, the+-- function returns 0, otherwise it returns 1.+-- +-- This function uses the heuristic GCD algorithm (GCDHEU). The basic+-- strategy is to remove the content of the polynomials, pack them using+-- Kronecker segmentation (given a bound on the size of the coefficients of+-- the GCD) and take the integer GCD. Unpack the result and test+-- divisibility.+foreign import ccall "fmpz_poly.h fmpz_poly_gcd_heuristic"+ fmpz_poly_gcd_heuristic :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO CInt++-- | /_fmpz_poly_gcd_modular/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Computes the greatest common divisor @(res, len2)@ of @(poly1, len1)@+-- and @(poly2, len2)@, assuming @len1 >= len2 > 0@. The result is+-- normalised to have positive leading coefficient. Aliasing between @res@,+-- @poly1@ and @poly2@ is not supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_gcd_modular"+ _fmpz_poly_gcd_modular :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_gcd_modular/ /res/ /poly1/ /poly2/ +-- +-- Computes the greatest common divisor @res@ of @poly1@ and @poly2@,+-- normalised to have non-negative leading coefficient.+-- +-- This function uses the modular GCD algorithm. The basic strategy is to+-- remove the content of the polynomials, reduce them modulo sufficiently+-- many primes and do CRT reconstruction until some bound is reached (or we+-- can prove with trial division that we have the GCD).+foreign import ccall "fmpz_poly.h fmpz_poly_gcd_modular"+ fmpz_poly_gcd_modular :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_gcd/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Computes the greatest common divisor @res@ of @(poly1, len1)@ and+-- @(poly2, len2)@, assuming @len1 >= len2 > 0@. The result is normalised+-- to have positive leading coefficient.+-- +-- Assumes that @res@ has space for @len2@ coefficients. Aliasing between+-- @res@, @poly1@ and @poly2@ is not supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_gcd"+ _fmpz_poly_gcd :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_gcd/ /res/ /poly1/ /poly2/ +-- +-- Computes the greatest common divisor @res@ of @poly1@ and @poly2@,+-- normalised to have non-negative leading coefficient.+foreign import ccall "fmpz_poly.h fmpz_poly_gcd"+ fmpz_poly_gcd :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_xgcd_modular/ /r/ /s/ /t/ /f/ /len1/ /g/ /len2/ +-- +-- Set \(r\) to the resultant of @(f, len1)@ and @(g, len2)@. If the+-- resultant is zero, the function returns immediately. Otherwise it finds+-- polynomials \(s\) and \(t\) such that @s*f + t*g = r@. The length of+-- \(s\) will be no greater than @len2@ and the length of \(t\) will be no+-- greater than @len1@ (both are zero padded if necessary).+-- +-- It is assumed that @len1 >= len2 > 0@. No aliasing of inputs and outputs+-- is permitted.+-- +-- The function assumes that \(f\) and \(g\) are primitive (have Gaussian+-- content equal to 1). The result is undefined otherwise.+-- +-- Uses a multimodular algorithm. The resultant is first computed and+-- extended GCD\'s modulo various primes \(p\) are computed and combined+-- using CRT. When the CRT stabilises the resulting polynomials are simply+-- reduced modulo further primes until a proven bound is reached.+foreign import ccall "fmpz_poly.h _fmpz_poly_xgcd_modular"+ _fmpz_poly_xgcd_modular :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_xgcd_modular/ /r/ /s/ /t/ /f/ /g/ +-- +-- Set \(r\) to the resultant of \(f\) and \(g\). If the resultant is zero,+-- the function then returns immediately, otherwise \(s\) and \(t\) are+-- found such that @s*f + t*g = r@.+-- +-- The function assumes that \(f\) and \(g\) are primitive (have Gaussian+-- content equal to 1). The result is undefined otherwise.+-- +-- Uses the multimodular algorithm.+foreign import ccall "fmpz_poly.h fmpz_poly_xgcd_modular"+ fmpz_poly_xgcd_modular :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_xgcd/ /r/ /s/ /t/ /f/ /len1/ /g/ /len2/ +-- +-- Set \(r\) to the resultant of @(f, len1)@ and @(g, len2)@. If the+-- resultant is zero, the function returns immediately. Otherwise it finds+-- polynomials \(s\) and \(t\) such that @s*f + t*g = r@. The length of+-- \(s\) will be no greater than @len2@ and the length of \(t\) will be no+-- greater than @len1@ (both are zero padded if necessary).+-- +-- The function assumes that \(f\) and \(g\) are primitive (have Gaussian+-- content equal to 1). The result is undefined otherwise.+-- +-- It is assumed that @len1 >= len2 > 0@. No aliasing of inputs and outputs+-- is permitted.+foreign import ccall "fmpz_poly.h _fmpz_poly_xgcd"+ _fmpz_poly_xgcd :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_xgcd/ /r/ /s/ /t/ /f/ /g/ +-- +-- Set \(r\) to the resultant of \(f\) and \(g\). If the resultant is zero,+-- the function then returns immediately, otherwise \(s\) and \(t\) are+-- found such that @s*f + t*g = r@.+-- +-- The function assumes that \(f\) and \(g\) are primitive (have Gaussian+-- content equal to 1). The result is undefined otherwise.+foreign import ccall "fmpz_poly.h fmpz_poly_xgcd"+ fmpz_poly_xgcd :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_lcm/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @(res, len1 + len2 - 1)@ to the least common multiple of the two+-- polynomials @(poly1, len1)@ and @(poly2, len2)@, normalised to have+-- non-negative leading coefficient.+-- +-- Assumes that @len1 >= len2 > 0@.+-- +-- Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_lcm"+ _fmpz_poly_lcm :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_lcm/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the least common multiple of the two polynomials @poly1@+-- and @poly2@, normalised to have non-negative leading coefficient.+-- +-- If either of the two polynomials is zero, sets @res@ to zero.+-- +-- This ensures that the equality+-- +-- \[`\]+-- \[f g = \gcd(f, g) \operatorname{lcm}(f, g)\]+-- +-- holds up to sign.+foreign import ccall "fmpz_poly.h fmpz_poly_lcm"+ fmpz_poly_lcm :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_resultant_modular/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @res@ to the resultant of @(poly1, len1)@ and @(poly2, len2)@,+-- assuming that @len1 >= len2 > 0@.+foreign import ccall "fmpz_poly.h _fmpz_poly_resultant_modular"+ _fmpz_poly_resultant_modular :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_resultant_modular/ /res/ /poly1/ /poly2/ +-- +-- Computes the resultant of @poly1@ and @poly2@.+-- +-- For two non-zero polynomials \(f(x) = a_m x^m + \dotsb + a_0\) and+-- \(g(x) = b_n x^n + \dotsb + b_0\) of degrees \(m\) and \(n\), the+-- resultant is defined to be+-- +-- \[`\]+-- \[a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y).\]+-- +-- For convenience, we define the resultant to be equal to zero if either+-- of the two polynomials is zero.+-- +-- This function uses the modular algorithm described in < [Col1971]>.+foreign import ccall "fmpz_poly.h fmpz_poly_resultant_modular"+ fmpz_poly_resultant_modular :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_resultant_modular_div/ /res/ /poly1/ /poly2/ /div/ /nbits/ +-- +-- Computes the resultant of @poly1@ and @poly2@ divided by @div@ using a+-- slight modification of the above function. It is assumed that the+-- resultant is exactly divisible by @div@ and the result @res@ has at most+-- @nbits@ bits. This bypasses the computation of general bounds.+foreign import ccall "fmpz_poly.h fmpz_poly_resultant_modular_div"+ fmpz_poly_resultant_modular_div :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_poly_resultant_euclidean/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @res@ to the resultant of @(poly1, len1)@ and @(poly2, len2)@,+-- assuming that @len1 >= len2 > 0@.+foreign import ccall "fmpz_poly.h _fmpz_poly_resultant_euclidean"+ _fmpz_poly_resultant_euclidean :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_resultant_euclidean/ /res/ /poly1/ /poly2/ +-- +-- Computes the resultant of @poly1@ and @poly2@.+-- +-- For two non-zero polynomials \(f(x) = a_m x^m + \dotsb + a_0\) and+-- \(g(x) = b_n x^n + \dotsb + b_0\) of degrees \(m\) and \(n\), the+-- resultant is defined to be+-- +-- \[`\]+-- \[a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y).\]+-- +-- For convenience, we define the resultant to be equal to zero if either+-- of the two polynomials is zero.+-- +-- This function uses the algorithm described in [Algorithm+-- 3.3.7]< [Coh1996]>.+foreign import ccall "fmpz_poly.h fmpz_poly_resultant_euclidean"+ fmpz_poly_resultant_euclidean :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_resultant/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @res@ to the resultant of @(poly1, len1)@ and @(poly2, len2)@,+-- assuming that @len1 >= len2 > 0@.+foreign import ccall "fmpz_poly.h _fmpz_poly_resultant"+ _fmpz_poly_resultant :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_resultant/ /res/ /poly1/ /poly2/ +-- +-- Computes the resultant of @poly1@ and @poly2@.+-- +-- For two non-zero polynomials \(f(x) = a_m x^m + \dotsb + a_0\) and+-- \(g(x) = b_n x^n + \dotsb + b_0\) of degrees \(m\) and \(n\), the+-- resultant is defined to be+-- +-- \[`\]+-- \[a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y).\]+-- +-- For convenience, we define the resultant to be equal to zero if either+-- of the two polynomials is zero.+foreign import ccall "fmpz_poly.h fmpz_poly_resultant"+ fmpz_poly_resultant :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- Discriminant ----------------------------------------------------------------++-- | /_fmpz_poly_discriminant/ /res/ /poly/ /len/ +-- +-- Set @res@ to the discriminant of @(poly, len)@. Assumes @len > 1@.+foreign import ccall "fmpz_poly.h _fmpz_poly_discriminant"+ _fmpz_poly_discriminant :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_discriminant/ /res/ /poly/ +-- +-- Set @res@ to the discriminant of @poly@. We normalise the discriminant+-- so that \(\operatorname{disc}(f) = (-1)^{(n(n-1)/2)}+-- \operatorname{res}(f, f')/\operatorname{lc}(f)\), thus+-- \(\operatorname{disc}(f) = \operatorname{lc}(f)^{(2n - 2)} \prod_{i < j} (r_i+-- - r_j)^2\), where \(\operatorname{lc}(f)\) is the leading coefficient of+-- \(f\), \(n\) is the degree of \(f\) and \(r_i\) are the roots of \(f\).+foreign import ccall "fmpz_poly.h fmpz_poly_discriminant"+ fmpz_poly_discriminant :: Ptr CFmpz -> Ptr CFmpzPoly -> IO ()++-- Gaussian content ------------------------------------------------------------++-- | /_fmpz_poly_content/ /res/ /poly/ /len/ +-- +-- Sets @res@ to the non-negative content of @(poly, len)@. Aliasing+-- between @res@ and the coefficients of @poly@ is not supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_content"+ _fmpz_poly_content :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_content/ /res/ /poly/ +-- +-- Sets @res@ to the non-negative content of @poly@. The content of the+-- zero polynomial is defined to be zero. Supports aliasing, that is, @res@+-- is allowed to be one of the coefficients of @poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_content"+ fmpz_poly_content :: Ptr CFmpz -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_primitive_part/ /res/ /poly/ /len/ +-- +-- Sets @(res, len)@ to @(poly, len)@ divided by the content of+-- @(poly, len)@, and normalises the result to have non-negative leading+-- coefficient.+-- +-- Assumes that @(poly, len)@ is non-zero. Supports aliasing of @res@ and+-- @poly@.+foreign import ccall "fmpz_poly.h _fmpz_poly_primitive_part"+ _fmpz_poly_primitive_part :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_primitive_part/ /res/ /poly/ +-- +-- Sets @res@ to @poly@ divided by the content of @poly@, and normalises+-- the result to have non-negative leading coefficient. If @poly@ is zero,+-- sets @res@ to zero.+foreign import ccall "fmpz_poly.h fmpz_poly_primitive_part"+ fmpz_poly_primitive_part :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- Square-free -----------------------------------------------------------------++-- | /_fmpz_poly_is_squarefree/ /poly/ /len/ +-- +-- Returns whether the polynomial @(poly, len)@ is square-free.+foreign import ccall "fmpz_poly.h _fmpz_poly_is_squarefree"+ _fmpz_poly_is_squarefree :: Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_poly_is_squarefree/ /poly/ +-- +-- Returns whether the polynomial @poly@ is square-free. A non-zero+-- polynomial is defined to be square-free if it has no non-unit square+-- factors. We also define the zero polynomial to be square-free.+-- +-- Returns \(1\) if the length of @poly@ is at most \(2\). Returns whether+-- the discriminant is zero for quadratic polynomials. Otherwise, returns+-- whether the greatest common divisor of @poly@ and its derivative has+-- length \(1\).+foreign import ccall "fmpz_poly.h fmpz_poly_is_squarefree"+ fmpz_poly_is_squarefree :: Ptr CFmpzPoly -> IO CInt++-- Euclidean division ----------------------------------------------------------++-- | /_fmpz_poly_divrem_basecase/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /exact/ +-- +-- Computes @(Q, lenA - lenB + 1)@, @(R, lenA)@ such that \(A = B Q + R\)+-- and each coefficient of \(R\) beyond @lenB@ is reduced modulo the+-- leading coefficient of \(B\). If the leading coefficient of \(B\) is+-- \(\pm 1\) or the division is exact, this is the same thing as division+-- over \(\mathbb{Q}\).+-- +-- Assumes that \(\operatorname{len}(A), \operatorname{len}(B) > 0\).+-- Allows zero-padding in @(A, lenA)@. \(R\) and \(A\) may be aliased, but+-- apart from this no aliasing of input and output operands is allowed.+-- +-- If the flag @exact@ is \(1\), the function stops if an inexact division+-- is encountered, upon which the function will return \(0\). If no inexact+-- division is encountered, the function returns \(1\). Note that this does+-- not guarantee the remainder of the polynomial division is zero, merely+-- that its length is less than that of B. This feature is useful for+-- series division and for divisibility testing (upon testing the+-- remainder).+-- +-- For ordinary use set the flag @exact@ to \(0\). In this case, no checks+-- or early aborts occur and the function always returns \(1\).+foreign import ccall "fmpz_poly.h _fmpz_poly_divrem_basecase"+ _fmpz_poly_divrem_basecase :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /fmpz_poly_divrem_basecase/ /Q/ /R/ /A/ /B/ +-- +-- Computes \(Q\), \(R\) such that \(A = B Q + R\) and each coefficient of+-- \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced modulo the leading+-- coefficient of \(B\). If the leading coefficient of \(B\) is \(\pm 1\)+-- or the division is exact, this is the same thing as division over+-- \(\mathbb{Q}\). An exception is raised if \(B\) is zero.+foreign import ccall "fmpz_poly.h fmpz_poly_divrem_basecase"+ fmpz_poly_divrem_basecase :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_divrem_divconquer_recursive/ /Q/ /BQ/ /W/ /A/ /B/ /lenB/ /exact/ +-- +-- Computes @(Q, lenB)@, @(BQ, 2 lenB - 1)@ such that \(BQ = B \times Q\)+-- and \(A = B Q + R\) where each coefficient of \(R\) beyond+-- \(\operatorname{len}(B) - 1\) is reduced modulo the leading coefficient+-- of \(B\). We assume that+-- \(\operatorname{len}(A) = 2 \operatorname{len}(B) - 1\). If the leading+-- coefficient of \(B\) is \(\pm 1\) or the division is exact, this is the+-- same as division over \(\mathbb{Q}\).+-- +-- Assumes \(\operatorname{len}(B) > 0\). Allows zero-padding in+-- @(A, lenA)@. Requires a temporary array @(W, 2 lenB - 1)@. No aliasing+-- of input and output operands is allowed.+-- +-- This function does not read the bottom \(\operatorname{len}(B) - 1\)+-- coefficients from \(A\), which means that they might not even need to+-- exist in allocated memory.+-- +-- If the flag @exact@ is \(1\), the function stops if an inexact division+-- is encountered, upon which the function will return \(0\). If no inexact+-- division is encountered, the function returns \(1\). Note that this does+-- not guarantee the remainder of the polynomial division is zero, merely+-- that its length is less than that of B. This feature is useful for+-- series division and for divisibility testing (upon testing the+-- remainder).+-- +-- For ordinary use set the flag @exact@ to \(0\). In this case, no checks+-- or early aborts occur and the function always returns \(1\).+foreign import ccall "fmpz_poly.h _fmpz_poly_divrem_divconquer_recursive"+ _fmpz_poly_divrem_divconquer_recursive :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /_fmpz_poly_divrem_divconquer/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /exact/ +-- +-- Computes @(Q, lenA - lenB + 1)@, @(R, lenA)@ such that \(A = B Q + R\)+-- and each coefficient of \(R\) beyond \(\operatorname{len}(B) - 1\) is+-- reduced modulo the leading coefficient of \(B\). If the leading+-- coefficient of \(B\) is \(\pm 1\) or the division is exact, this is the+-- same as division over \(\mathbb{Q}\).+-- +-- Assumes \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\). Allows+-- zero-padding in @(A, lenA)@. No aliasing of input and output operands is+-- allowed.+-- +-- If the flag @exact@ is \(1\), the function stops if an inexact division+-- is encountered, upon which the function will return \(0\). If no inexact+-- division is encountered, the function returns \(1\). Note that this does+-- not guarantee the remainder of the polynomial division is zero, merely+-- that its length is less than that of B. This feature is useful for+-- series division and for divisibility testing (upon testing the+-- remainder).+-- +-- For ordinary use set the flag @exact@ to \(0\). In this case, no checks+-- or early aborts occur and the function always returns \(1\).+foreign import ccall "fmpz_poly.h _fmpz_poly_divrem_divconquer"+ _fmpz_poly_divrem_divconquer :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /fmpz_poly_divrem_divconquer/ /Q/ /R/ /A/ /B/ +-- +-- Computes \(Q\), \(R\) such that \(A = B Q + R\) and each coefficient of+-- \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced modulo the leading+-- coefficient of \(B\). If the leading coefficient of \(B\) is \(\pm 1\)+-- or the division is exact, this is the same as division over+-- \(\mathbb{Q}\). An exception is raised if \(B\) is zero.+foreign import ccall "fmpz_poly.h fmpz_poly_divrem_divconquer"+ fmpz_poly_divrem_divconquer :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_divrem/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /exact/ +-- +-- Computes @(Q, lenA - lenB + 1)@, @(R, lenA)@ such that \(A = B Q + R\)+-- and each coefficient of \(R\) beyond \(\operatorname{len}(B) - 1\) is+-- reduced modulo the leading coefficient of \(B\). If the leading+-- coefficient of \(B\) is \(\pm 1\) or the division is exact, this is the+-- same thing as division over \(\mathbb{Q}\).+-- +-- Assumes \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\). Allows+-- zero-padding in @(A, lenA)@. No aliasing of input and output operands is+-- allowed.+-- +-- If the flag @exact@ is \(1\), the function stops if an inexact division+-- is encountered, upon which the function will return \(0\). If no inexact+-- division is encountered, the function returns \(1\). Note that this does+-- not guarantee the remainder of the polynomial division is zero, merely+-- that its length is less than that of B. This feature is useful for+-- series division and for divisibility testing (upon testing the+-- remainder).+-- +-- For ordinary use set the flag @exact@ to \(0\). In this case, no checks+-- or early aborts occur and the function always returns \(1\).+foreign import ccall "fmpz_poly.h _fmpz_poly_divrem"+ _fmpz_poly_divrem :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /fmpz_poly_divrem/ /Q/ /R/ /A/ /B/ +-- +-- Computes \(Q\), \(R\) such that \(A = B Q + R\) and each coefficient of+-- \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced modulo the leading+-- coefficient of \(B\). If the leading coefficient of \(B\) is \(\pm 1\)+-- or the division is exact, this is the same as division over+-- \(\mathbb{Q}\). An exception is raised if \(B\) is zero.+foreign import ccall "fmpz_poly.h fmpz_poly_divrem"+ fmpz_poly_divrem :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_div_basecase/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /exact/ +-- +-- Computes the quotient @(Q, lenA - lenB + 1)@ of @(A, lenA)@ divided by+-- @(B, lenB)@.+-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) and each+-- coefficient of \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced+-- modulo the leading coefficient of \(B\).+-- +-- If the leading coefficient of \(B\) is \(\pm 1\) or the division is+-- exact, this is the same as division over \(\mathbb{Q}\).+-- +-- Assumes \(\operatorname{len}(A), \operatorname{len}(B) > 0\). Allows+-- zero-padding in @(A, lenA)@. Requires a temporary array \(R\) of size at+-- least the (actual) length of \(A\). For convenience, \(R\) may be+-- @NULL@. \(R\) and \(A\) may be aliased, but apart from this no aliasing+-- of input and output operands is allowed.+-- +-- If the flag @exact@ is \(1\), the function stops if an inexact division+-- is encountered, upon which the function will return \(0\). If no inexact+-- division is encountered, the function returns \(1\). Note that this does+-- not guarantee the remainder of the polynomial division is zero, merely+-- that its length is less than that of B. This feature is useful for+-- series division and for divisibility testing (upon testing the+-- remainder).+-- +-- For ordinary use set the flag @exact@ to \(0\). In this case, no checks+-- or early aborts occur and the function always returns \(1\).+foreign import ccall "fmpz_poly.h _fmpz_poly_div_basecase"+ _fmpz_poly_div_basecase :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /fmpz_poly_div_basecase/ /Q/ /A/ /B/ +-- +-- Computes the quotient \(Q\) of \(A\) divided by \(Q\).+-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) and each+-- coefficient of \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced+-- modulo the leading coefficient of \(B\).+-- +-- If the leading coefficient of \(B\) is \(\pm 1\) or the division is+-- exact, this is the same as division over \(\mathbb{Q}\). An exception is+-- raised if \(B\) is zero.+foreign import ccall "fmpz_poly.h fmpz_poly_div_basecase"+ fmpz_poly_div_basecase :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_divremlow_divconquer_recursive/ /Q/ /BQ/ /A/ /B/ /lenB/ /exact/ +-- +-- Divide and conquer division of @(A, 2 lenB - 1)@ by @(B, lenB)@,+-- computing only the bottom \(\operatorname{len}(B) - 1\) coefficients of+-- \(B Q\).+-- +-- Assumes \(\operatorname{len}(B) > 0\). Requires \(B Q\) to have length+-- at least \(2 \operatorname{len}(B) - 1\), although only the bottom+-- \(\operatorname{len}(B) - 1\) coefficients will carry meaningful output.+-- Does not support any aliasing. Allows zero-padding in \(A\), but not in+-- \(B\).+-- +-- If the flag @exact@ is \(1\), the function stops if an inexact division+-- is encountered, upon which the function will return \(0\). If no inexact+-- division is encountered, the function returns \(1\). Note that this does+-- not guarantee the remainder of the polynomial division is zero, merely+-- that its length is less than that of B. This feature is useful for+-- series division and for divisibility testing (upon testing the+-- remainder).+-- +-- For ordinary use set the flag @exact@ to \(0\). In this case, no checks+-- or early aborts occur and the function always returns \(1\).+foreign import ccall "fmpz_poly.h _fmpz_poly_divremlow_divconquer_recursive"+ _fmpz_poly_divremlow_divconquer_recursive :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /_fmpz_poly_div_divconquer_recursive/ /Q/ /temp/ /A/ /B/ /lenB/ /exact/ +-- +-- Recursive short division in the balanced case.+-- +-- Computes the quotient @(Q, lenB)@ of @(A, 2 lenB - 1)@ upon division by+-- @(B, lenB)@. Requires \(\operatorname{len}(B) > 0\). Needs a temporary+-- array @temp@ of length \(2 \operatorname{len}(B) - 1\). Does not support+-- any aliasing.+-- +-- For further details, see < [Mul2000]>.+-- +-- If the flag @exact@ is \(1\), the function stops if an inexact division+-- is encountered, upon which the function will return \(0\). If no inexact+-- division is encountered, the function returns \(1\). Note that this does+-- not guarantee the remainder of the polynomial division is zero, merely+-- that its length is less than that of B. This feature is useful for+-- series division and for divisibility testing (upon testing the+-- remainder).+-- +-- For ordinary use set the flag @exact@ to \(0\). In this case, no checks+-- or early aborts occur and the function always returns \(1\).+foreign import ccall "fmpz_poly.h _fmpz_poly_div_divconquer_recursive"+ _fmpz_poly_div_divconquer_recursive :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /_fmpz_poly_div_divconquer/ /Q/ /A/ /lenA/ /B/ /lenB/ /exact/ +-- +-- Computes the quotient @(Q, lenA - lenB + 1)@ of @(A, lenA)@ upon+-- division by @(B, lenB)@. Assumes that+-- \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\). Does not+-- support aliasing.+-- +-- If the flag @exact@ is \(1\), the function stops if an inexact division+-- is encountered, upon which the function will return \(0\). If no inexact+-- division is encountered, the function returns \(1\). Note that this does+-- not guarantee the remainder of the polynomial division is zero, merely+-- that its length is less than that of B. This feature is useful for+-- series division and for divisibility testing (upon testing the+-- remainder).+-- +-- For ordinary use set the flag @exact@ to \(0\). In this case, no checks+-- or early aborts occur and the function always returns \(1\).+foreign import ccall "fmpz_poly.h _fmpz_poly_div_divconquer"+ _fmpz_poly_div_divconquer :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /fmpz_poly_div_divconquer/ /Q/ /A/ /B/ +-- +-- Computes the quotient \(Q\) of \(A\) divided by \(B\).+-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) and each+-- coefficient of \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced+-- modulo the leading coefficient of \(B\).+-- +-- If the leading coefficient of \(B\) is \(\pm 1\) or the division is+-- exact, this is the same as division over \(\mathbb{Q}\). An exception is+-- raised if \(B\) is zero.+foreign import ccall "fmpz_poly.h fmpz_poly_div_divconquer"+ fmpz_poly_div_divconquer :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_div/ /Q/ /A/ /lenA/ /B/ /lenB/ /exact/ +-- +-- Computes the quotient @(Q, lenA - lenB + 1)@ of @(A, lenA)@ divided by+-- @(B, lenB)@.+-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) and each+-- coefficient of \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced+-- modulo the leading coefficient of \(B\). If the leading coefficient of+-- \(B\) is \(\pm 1\) or the division is exact, this is the same as+-- division over \(\mathbb{Q}\).+-- +-- Assumes \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\). Allows+-- zero-padding in @(A, lenA)@. Aliasing of input and output operands is+-- not allowed.+-- +-- If the flag @exact@ is \(1\), the function stops if an inexact division+-- is encountered, upon which the function will return \(0\). If no inexact+-- division is encountered, the function returns \(1\). Note that this does+-- not guarantee the remainder of the polynomial division is zero, merely+-- that its length is less than that of B. This feature is useful for+-- series division and for divisibility testing (upon testing the+-- remainder).+-- +-- For ordinary use set the flag @exact@ to \(0\). In this case, no checks+-- or early aborts occur and the function always returns \(1\).+foreign import ccall "fmpz_poly.h _fmpz_poly_div"+ _fmpz_poly_div :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /fmpz_poly_div/ /Q/ /A/ /B/ +-- +-- Computes the quotient \(Q\) of \(A\) divided by \(B\).+-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) and each+-- coefficient of \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced+-- modulo the leading coefficient of \(B\). If the leading coefficient of+-- \(B\) is \(\pm 1\) or the division is exact, this is the same as+-- division over \(Q\). An exception is raised if \(B\) is zero.+foreign import ccall "fmpz_poly.h fmpz_poly_div"+ fmpz_poly_div :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_rem_basecase/ /R/ /A/ /lenA/ /B/ /lenB/ +-- +-- Computes the remainder @(R, lenA)@ of @(A, lenA)@ upon division by+-- @(B, lenB)@.+-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) and each+-- coefficient of \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced+-- modulo the leading coefficient of \(B\). If the leading coefficient of+-- \(B\) is \(\pm 1\) or the division is exact, this is the same thing as+-- division over \(\mathbb{Q}\).+-- +-- Assumes that \(\operatorname{len}(A), \operatorname{len}(B) > 0\).+-- Allows zero-padding in @(A, lenA)@. \(R\) and \(A\) may be aliased, but+-- apart from this no aliasing of input and output operands is allowed.+foreign import ccall "fmpz_poly.h _fmpz_poly_rem_basecase"+ _fmpz_poly_rem_basecase :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_rem_basecase/ /R/ /A/ /B/ +-- +-- Computes the remainder \(R\) of \(A\) upon division by \(B\).+-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) and each+-- coefficient of \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced+-- modulo the leading coefficient of \(B\). If the leading coefficient of+-- \(B\) is \(\pm 1\) or the division is exact, this is the same as+-- division over \(\mathbb{Q}\). An exception is raised if \(B\) is zero.+foreign import ccall "fmpz_poly.h fmpz_poly_rem_basecase"+ fmpz_poly_rem_basecase :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_rem/ /R/ /A/ /lenA/ /B/ /lenB/ +-- +-- Computes the remainder @(R, lenA)@ of @(A, lenA)@ upon division by+-- @(B, lenB)@.+-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) and each+-- coefficient of \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced+-- modulo the leading coefficient of \(B\). If the leading coefficient of+-- \(B\) is \(\pm 1\) or the division is exact, this is the same thing as+-- division over \(\mathbb{Q}\).+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\).+-- Allows zero-padding in @(A, lenA)@. Aliasing of input and output+-- operands is not allowed.+foreign import ccall "fmpz_poly.h _fmpz_poly_rem"+ _fmpz_poly_rem :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_rem/ /R/ /A/ /B/ +-- +-- Computes the remainder \(R\) of \(A\) upon division by \(B\).+-- +-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) and each+-- coefficient of \(R\) beyond \(\operatorname{len}(B) - 1\) is reduced+-- modulo the leading coefficient of \(B\). If the leading coefficient of+-- \(B\) is \(\pm 1\) or the division is exact, this is the same as+-- division over \(\mathbb{Q}\). An exception is raised if \(B\) is zero.+foreign import ccall "fmpz_poly.h fmpz_poly_rem"+ fmpz_poly_rem :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_div_root/ /Q/ /A/ /len/ /c/ +-- +-- Computes the quotient @(Q, len-1)@ of @(A, len)@ upon division by+-- \(x - c\).+-- +-- Supports aliasing of @Q@ and @A@, but the result is undefined in case of+-- partial overlap.+foreign import ccall "fmpz_poly.h _fmpz_poly_div_root"+ _fmpz_poly_div_root :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_div_root/ /Q/ /A/ /c/ +-- +-- Computes the quotient @(Q, len-1)@ of @(A, len)@ upon division by+-- \(x - c\).+foreign import ccall "fmpz_poly.h fmpz_poly_div_root"+ fmpz_poly_div_root :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- Division with precomputed inverse -------------------------------------------++-- | /_fmpz_poly_preinvert/ /B_inv/ /B/ /n/ +-- +-- Given a monic polynomial @B@ of length @n@, compute a precomputed+-- inverse @B_inv@ of length @n@ for use in the functions below. No+-- aliasing of @B@ and @B_inv@ is permitted. We assume @n@ is not zero.+foreign import ccall "fmpz_poly.h _fmpz_poly_preinvert"+ _fmpz_poly_preinvert :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_preinvert/ /B_inv/ /B/ +-- +-- Given a monic polynomial @B@, compute a precomputed inverse @B_inv@ for+-- use in the functions below. An exception is raised if @B@ is zero.+foreign import ccall "fmpz_poly.h fmpz_poly_preinvert"+ fmpz_poly_preinvert :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_div_preinv/ /Q/ /A/ /len1/ /B/ /B_inv/ /len2/ +-- +-- Given a precomputed inverse @B_inv@ of the polynomial @B@ of length+-- @len2@, compute the quotient @Q@ of @A@ by @B@. We assume the length+-- @len1@ of @A@ is at least @len2@. The polynomial @Q@ must have space for+-- @len1 - len2 + 1@ coefficients. No aliasing of operands is permitted.+foreign import ccall "fmpz_poly.h _fmpz_poly_div_preinv"+ _fmpz_poly_div_preinv :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_div_preinv/ /Q/ /A/ /B/ /B_inv/ +-- +-- Given a precomputed inverse @B_inv@ of the polynomial @B@, compute the+-- quotient @Q@ of @A@ by @B@. Aliasing of @B@ and @B_inv@ is not+-- permitted.+foreign import ccall "fmpz_poly.h fmpz_poly_div_preinv"+ fmpz_poly_div_preinv :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_divrem_preinv/ /Q/ /A/ /len1/ /B/ /B_inv/ /len2/ +-- +-- Given a precomputed inverse @B_inv@ of the polynomial @B@ of length+-- @len2@, compute the quotient @Q@ of @A@ by @B@. The remainder is then+-- placed in @A@. We assume the length @len1@ of @A@ is at least @len2@.+-- The polynomial @Q@ must have space for @len1 - len2 + 1@ coefficients.+-- No aliasing of operands is permitted.+foreign import ccall "fmpz_poly.h _fmpz_poly_divrem_preinv"+ _fmpz_poly_divrem_preinv :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_divrem_preinv/ /Q/ /R/ /A/ /B/ /B_inv/ +-- +-- Given a precomputed inverse @B_inv@ of the polynomial @B@, compute the+-- quotient @Q@ of @A@ by @B@ and the remainder @R@. Aliasing of @B@ and+-- @B_inv@ is not permitted.+foreign import ccall "fmpz_poly.h fmpz_poly_divrem_preinv"+ fmpz_poly_divrem_preinv :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_powers_precompute/ /B/ /len/ +-- +-- Computes @2*len - 1@ powers of \(x\) modulo the polynomial \(B\) of the+-- given length. This is used as a kind of precomputed inverse in the+-- remainder routine below.+foreign import ccall "fmpz_poly.h _fmpz_poly_powers_precompute"+ _fmpz_poly_powers_precompute :: Ptr CFmpz -> CLong -> IO (Ptr (Ptr CFmpz))++-- | /fmpz_poly_powers_precompute/ /pinv/ /poly/ +-- +-- Computes @2*len - 1@ powers of \(x\) modulo the polynomial \(B\) of the+-- given length. This is used as a kind of precomputed inverse in the+-- remainder routine below.+foreign import ccall "fmpz_poly.h fmpz_poly_powers_precompute"+ fmpz_poly_powers_precompute :: Ptr CFmpzPolyPowersPrecomp -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_powers_clear/ /powers/ /len/ +-- +-- Clean up resources used by precomputed powers which have been computed+-- by @_fmpz_poly_powers_precompute@.+foreign import ccall "fmpz_poly.h _fmpz_poly_powers_clear"+ _fmpz_poly_powers_clear :: Ptr (Ptr CFmpz) -> CLong -> IO ()++-- | /fmpz_poly_powers_clear/ /pinv/ +-- +-- Clean up resources used by precomputed powers which have been computed+-- by @fmpz_poly_powers_precompute@.+foreign import ccall "fmpz_poly.h fmpz_poly_powers_clear"+ fmpz_poly_powers_clear :: Ptr CFmpzPolyPowersPrecomp -> IO ()++-- | /_fmpz_poly_rem_powers_precomp/ /A/ /m/ /B/ /n/ /powers/ +-- +-- Set \(A\) to the remainder of \(A\) divide \(B\) given precomputed+-- powers mod \(B\) provided by @_fmpz_poly_powers_precompute@. No aliasing+-- is allowed.+foreign import ccall "fmpz_poly.h _fmpz_poly_rem_powers_precomp"+ _fmpz_poly_rem_powers_precomp :: Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr (Ptr CFmpz) -> IO ()++-- | /fmpz_poly_rem_powers_precomp/ /R/ /A/ /B/ /B_inv/ +-- +-- Set \(R\) to the remainder of \(A\) divide \(B\) given precomputed+-- powers mod \(B\) provided by @fmpz_poly_powers_precompute@.+foreign import ccall "fmpz_poly.h fmpz_poly_rem_powers_precomp"+ fmpz_poly_rem_powers_precomp :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPolyPowersPrecomp -> IO ()++-- Divisibility testing --------------------------------------------------------++-- | /_fmpz_poly_divides/ /Q/ /A/ /lenA/ /B/ /lenB/ +-- +-- Returns 1 if @(B, lenB)@ divides @(A, lenA)@ exactly and sets \(Q\) to+-- the quotient, otherwise returns 0.+-- +-- It is assumed that+-- \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\) and that \(Q\)+-- has space for \(\operatorname{len}(A) - \operatorname{len}(B) + 1\)+-- coefficients.+-- +-- Aliasing of \(Q\) with either of the inputs is not permitted.+-- +-- This function is currently unoptimised and provided for convenience+-- only.+foreign import ccall "fmpz_poly.h _fmpz_poly_divides"+ _fmpz_poly_divides :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_poly_divides/ /Q/ /A/ /B/ +-- +-- Returns 1 if \(B\) divides \(A\) exactly and sets \(Q\) to the quotient,+-- otherwise returns 0.+-- +-- This function is currently unoptimised and provided for convenience+-- only.+foreign import ccall "fmpz_poly.h fmpz_poly_divides"+ fmpz_poly_divides :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO CInt++-- | /fmpz_poly_remove/ /res/ /poly1/ /poly2/ +-- +-- Set @res@ to @poly1@ divided by the highest power of @poly2@ that+-- divides it and return the power. The divisor @poly2@ must not be zero or+-- \(\pm 1\), otherwise an exception is raised.+foreign import ccall "fmpz_poly.h fmpz_poly_remove"+ fmpz_poly_remove :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO CLong++-- Division mod p --------------------------------------------------------------++-- | /fmpz_poly_divlow_smodp/ /res/ /f/ /g/ /p/ /n/ +-- +-- Compute the \(n\) lowest coefficients of \(f\) divided by \(g\),+-- assuming the division is exact modulo \(p\). The computed coefficients+-- are reduced modulo \(p\) using the symmetric remainder system. We+-- require \(f\) to be at least \(n\) in length. The function can handle+-- trailing zeroes, but the low nonzero coefficient of \(g\) must be+-- coprime to \(p\). This is a bespoke function used by factoring.+foreign import ccall "fmpz_poly.h fmpz_poly_divlow_smodp"+ fmpz_poly_divlow_smodp :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_divhigh_smodp/ /res/ /f/ /g/ /p/ /n/ +-- +-- Compute the \(n\) highest coefficients of \(f\) divided by \(g\),+-- assuming the division is exact modulo \(p\). The computed coefficients+-- are reduced modulo \(p\) using the symmetric remainder system. We+-- require \(f\) to be as output by @fmpz_poly_mulhigh_n@ given polynomials+-- \(g\) and a polynomial of length \(n\) as inputs. The leading+-- coefficient of \(g\) must be coprime to \(p\). This is a bespoke+-- function used by factoring.+foreign import ccall "fmpz_poly.h fmpz_poly_divhigh_smodp"+ fmpz_poly_divhigh_smodp :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> CLong -> IO ()++-- Power series division -------------------------------------------------------++-- | /_fmpz_poly_inv_series_basecase/ /Qinv/ /Q/ /Qlen/ /n/ +-- +-- Computes the first \(n\) terms of the inverse power series of+-- @(Q, lenQ)@ using a recurrence.+-- +-- Assumes that \(n \geq 1\) and that \(Q\) has constant term \(\pm 1\).+-- Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_inv_series_basecase"+ _fmpz_poly_inv_series_basecase :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_inv_series_basecase/ /Qinv/ /Q/ /n/ +-- +-- Computes the first \(n\) terms of the inverse power series of \(Q\)+-- using a recurrence, assuming that \(Q\) has constant term \(\pm 1\) and+-- \(n \geq 1\).+foreign import ccall "fmpz_poly.h fmpz_poly_inv_series_basecase"+ fmpz_poly_inv_series_basecase :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_inv_series_newton/ /Qinv/ /Q/ /n/ +-- +-- Computes the first \(n\) terms of the inverse power series of+-- @(Q, lenQ)@ using Newton iteration.+-- +-- Assumes that \(n \geq 1\) and that \(Q\) has constant term \(\pm 1\).+-- Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_inv_series_newton"+ _fmpz_poly_inv_series_newton :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_inv_series_newton/ /Qinv/ /Q/ /Qlen/ /n/ +-- +-- Computes the first \(n\) terms of the inverse power series of \(Q\)+-- using Newton iteration, assuming \(Q\) has constant term \(\pm 1\) and+-- \(n \geq 1\).+foreign import ccall "fmpz_poly.h fmpz_poly_inv_series_newton"+ fmpz_poly_inv_series_newton :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> CLong -> IO ()++-- | /_fmpz_poly_inv_series/ /Qinv/ /Q/ /n/ +-- +-- Computes the first \(n\) terms of the inverse power series of+-- @(Q, lenQ)@.+-- +-- Assumes that \(n \geq 1\) and that \(Q\) has constant term \(\pm 1\).+-- Does not support aliasing.+foreign import ccall "fmpz_poly.h _fmpz_poly_inv_series"+ _fmpz_poly_inv_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_inv_series/ /Qinv/ /Q/ /n/ +-- +-- Computes the first \(n\) terms of the inverse power series of \(Q\),+-- assuming \(Q\) has constant term \(\pm 1\) and \(n \geq 1\).+foreign import ccall "fmpz_poly.h fmpz_poly_inv_series"+ fmpz_poly_inv_series :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++foreign import ccall "fmpz_poly.h _fmpz_poly_div_series_basecase"+ _fmpz_poly_div_series_basecase :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++foreign import ccall "fmpz_poly.h _fmpz_poly_div_series_divconquer"+ _fmpz_poly_div_series_divconquer :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /_fmpz_poly_div_series/ /Q/ /A/ /Alen/ /B/ /Blen/ /n/ +-- +-- Divides @(A, Alen)@ by @(B, Blen)@ as power series over \(\mathbb{Z}\),+-- assuming \(B\) has constant term \(\pm 1\) and \(n \geq 1\). Aliasing is+-- not supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_div_series"+ _fmpz_poly_div_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++foreign import ccall "fmpz_poly.h fmpz_poly_div_series_basecase"+ fmpz_poly_div_series_basecase :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++foreign import ccall "fmpz_poly.h fmpz_poly_div_series_divconquer"+ fmpz_poly_div_series_divconquer :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_div_series/ /Q/ /A/ /B/ /n/ +-- +-- Performs power series division in \(\mathbb{Z}[[x]] / (x^n)\). The+-- function considers the polynomials \(A\) and \(B\) as power series of+-- length \(n\) starting with the constant terms. The function assumes that+-- \(B\) has constant term \(\pm 1\) and \(n \geq 1\).+foreign import ccall "fmpz_poly.h fmpz_poly_div_series"+ fmpz_poly_div_series :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- Pseudo division -------------------------------------------------------------++-- | /_fmpz_poly_pseudo_divrem_basecase/ /Q/ /R/ /d/ /A/ /lenA/ /B/ /lenB/ /inv/ +-- +-- If \(\ell\) is the leading coefficient of \(B\), then computes \(Q\),+-- \(R\) such that \(\ell^d A = Q B + R\). This function is used for+-- simulating division over \(\mathbb{Q}\).+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\).+-- Assumes that \(Q\) can fit+-- \(\operatorname{len}(A) - \operatorname{len}(B) + 1\) coefficients, and+-- that \(R\) can fit \(\operatorname{len}(A)\) coefficients. Supports+-- aliasing of @(R, lenA)@ and @(A, lenA)@. But other than this, no+-- aliasing of the inputs and outputs is supported.+-- +-- An optional precomputed inverse of the leading coefficient of \(B\) from+-- @fmpz_preinvn_init@ can be supplied. Otherwise @inv@ should be @NULL@.+foreign import ccall "fmpz_poly.h _fmpz_poly_pseudo_divrem_basecase"+ _fmpz_poly_pseudo_divrem_basecase :: Ptr CFmpz -> Ptr CFmpz -> Ptr CULong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpzPreInvN -> IO ()++-- | /fmpz_poly_pseudo_divrem_basecase/ /Q/ /R/ /d/ /A/ /B/ +-- +-- If \(\ell\) is the leading coefficient of \(B\), then computes \(Q\),+-- \(R\) such that \(\ell^d A = Q B + R\). This function is used for+-- simulating division over \(\mathbb{Q}\).+foreign import ccall "fmpz_poly.h fmpz_poly_pseudo_divrem_basecase"+ fmpz_poly_pseudo_divrem_basecase :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CULong -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_pseudo_divrem_divconquer/ /Q/ /R/ /d/ /A/ /lenA/ /B/ /lenB/ /inv/ +-- +-- Computes @(Q, lenA - lenB + 1)@, @(R, lenA)@ such that+-- \(\ell^d A = B Q + R\), only setting the bottom+-- \(\operatorname{len}(B) - 1\) coefficients of \(R\) to their correct+-- values. The remaining top coefficients of @(R, lenA)@ may be arbitrary.+-- +-- Assumes \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\). Allows+-- zero-padding in @(A, lenA)@. No aliasing of input and output operands is+-- allowed.+-- +-- An optional precomputed inverse of the leading coefficient of \(B\) from+-- @fmpz_preinvn_init@ can be supplied. Otherwise @inv@ should be @NULL@.+foreign import ccall "fmpz_poly.h _fmpz_poly_pseudo_divrem_divconquer"+ _fmpz_poly_pseudo_divrem_divconquer :: Ptr CFmpz -> Ptr CFmpz -> Ptr CULong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpzPreInvN -> IO ()++-- | /fmpz_poly_pseudo_divrem_divconquer/ /Q/ /R/ /d/ /A/ /B/ +-- +-- Computes \(Q\), \(R\), and \(d\) such that \(\ell^d A = B Q + R\), where+-- \(R\) has length less than the length of \(B\) and \(\ell\) is the+-- leading coefficient of \(B\). An exception is raised if \(B\) is zero.+foreign import ccall "fmpz_poly.h fmpz_poly_pseudo_divrem_divconquer"+ fmpz_poly_pseudo_divrem_divconquer :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CULong -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_pseudo_divrem_cohen/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ +-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\).+-- Assumes that \(Q\) can fit+-- \(\operatorname{len}(A) - \operatorname{len}(B) + 1\) coefficients, and+-- that \(R\) can fit \(\operatorname{len}(A)\) coefficients. Supports+-- aliasing of @(R, lenA)@ and @(A, lenA)@. But other than this, no+-- aliasing of the inputs and outputs is supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_pseudo_divrem_cohen"+ _fmpz_poly_pseudo_divrem_cohen :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_pseudo_divrem_cohen/ /Q/ /R/ /A/ /B/ +-- +-- This is a variant of @fmpz_poly_pseudo_divrem@ which computes+-- polynomials \(Q\) and \(R\) such that \(\ell^d A = B Q + R\). However,+-- the value of \(d\) is fixed at+-- \(\max{\{0, \operatorname{len}(A) - \operatorname{len}(B) + 1\}}\).+-- +-- This function is faster when the remainder is not well behaved, i.e.+-- where it is not expected to be close to zero. Note that this function is+-- not asymptotically fast. It is efficient only for short polynomials,+-- e.g.when \(\operatorname{len}(B) < 32\).+foreign import ccall "fmpz_poly.h fmpz_poly_pseudo_divrem_cohen"+ fmpz_poly_pseudo_divrem_cohen :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_pseudo_rem_cohen/ /R/ /A/ /lenA/ /B/ /lenB/ +-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\).+-- Assumes that \(R\) can fit \(\operatorname{len}(A)\) coefficients.+-- Supports aliasing of @(R, lenA)@ and @(A, lenA)@. But other than this,+-- no aliasing of the inputs and outputs is supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_pseudo_rem_cohen"+ _fmpz_poly_pseudo_rem_cohen :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_pseudo_rem_cohen/ /R/ /A/ /B/ +-- +-- This is a variant of @fmpz_poly_pseudo_rem@ which computes polynomials+-- \(Q\) and \(R\) such that \(\ell^d A = B Q + R\), but only returns+-- \(R\). However, the value of \(d\) is fixed at+-- \(\max{\{0, \operatorname{len}(A) - \operatorname{len}(B) + 1\}}\).+-- +-- This function is faster when the remainder is not well behaved, i.e.+-- where it is not expected to be close to zero. Note that this function is+-- not asymptotically fast. It is efficient only for short polynomials,+-- e.g.when \(\operatorname{len}(B) < 32\).+-- +-- This function uses the algorithm described in [Algorithm+-- 3.1.2]< [Coh1996]>.+foreign import ccall "fmpz_poly.h fmpz_poly_pseudo_rem_cohen"+ fmpz_poly_pseudo_rem_cohen :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- -- | /_fmpz_poly_pseudo_divrem/ /Q/ /R/ /d/ /A/ /lenA/ /B/ /lenB/ /inv/ +-- -- +-- -- If \(\ell\) is the leading coefficient of \(B\), then computes+-- -- @(Q, lenA - lenB + 1)@, @(R, lenB - 1)@ and \(d\) such that+-- -- \(\ell^d A = B Q + R\). This function is used for simulating division+-- -- over \(\mathbb{Q}\).+-- -- +-- -- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\).+-- -- Assumes that \(Q\) can fit+-- -- \(\operatorname{len}(A) - \operatorname{len}(B) + 1\) coefficients, and+-- -- that \(R\) can fit \(\operatorname{len}(A)\) coefficients, although on+-- -- exit only the bottom \(\operatorname{len}(B)\) coefficients will carry+-- -- meaningful data.+-- -- +-- -- Supports aliasing of @(R, lenA)@ and @(A, lenA)@. But other than this,+-- -- no aliasing of the inputs and outputs is supported.+-- -- +-- -- An optional precomputed inverse of the leading coefficient of \(B\) from+-- -- @fmpz_preinvn_init@ can be supplied. Otherwise @inv@ should be @NULL@.+-- foreign import ccall "fmpz_poly.h _fmpz_poly_pseudo_divrem"+-- _fmpz_poly_pseudo_divrem :: Ptr CFmpz -> Ptr CFmpz -> Ptr CULong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpzPreInvN -> IO ()++-- -- | /fmpz_poly_pseudo_divrem/ /Q/ /R/ /d/ /A/ /B/ +-- -- +-- -- Computes \(Q\), \(R\), and \(d\) such that \(\ell^d A = B Q + R\).+-- foreign import ccall "fmpz_poly.h fmpz_poly_pseudo_divrem"+-- fmpz_poly_pseudo_divrem :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CULong -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_pseudo_div/ /Q/ /d/ /A/ /lenA/ /B/ /lenB/ /inv/ +-- +-- Pseudo-division, only returning the quotient.+foreign import ccall "fmpz_poly.h _fmpz_poly_pseudo_div"+ _fmpz_poly_pseudo_div :: Ptr CFmpz -> Ptr CULong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpzPreInvN -> IO ()++-- | /fmpz_poly_pseudo_div/ /Q/ /d/ /A/ /B/ +-- +-- Pseudo-division, only returning the quotient.+foreign import ccall "fmpz_poly.h fmpz_poly_pseudo_div"+ fmpz_poly_pseudo_div :: Ptr CFmpzPoly -> Ptr CULong -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_pseudo_rem/ /R/ /d/ /A/ /lenA/ /B/ /lenB/ /inv/ +-- +-- Pseudo-division, only returning the remainder.+foreign import ccall "fmpz_poly.h _fmpz_poly_pseudo_rem"+ _fmpz_poly_pseudo_rem :: Ptr CFmpz -> Ptr CULong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpzPreInvN -> IO ()++-- | /fmpz_poly_pseudo_rem/ /R/ /d/ /A/ /B/ +-- +-- Pseudo-division, only returning the remainder.+foreign import ccall "fmpz_poly.h fmpz_poly_pseudo_rem"+ fmpz_poly_pseudo_rem :: Ptr CFmpzPoly -> Ptr CULong -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- Derivative ------------------------------------------------------------------++-- | /_fmpz_poly_derivative/ /rpoly/ /poly/ /len/ +-- +-- Sets @(rpoly, len - 1)@ to the derivative of @(poly, len)@. Also handles+-- the cases where @len@ is \(0\) or \(1\) correctly. Supports aliasing of+-- @rpoly@ and @poly@.+foreign import ccall "fmpz_poly.h _fmpz_poly_derivative"+ _fmpz_poly_derivative :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_derivative/ /res/ /poly/ +-- +-- Sets @res@ to the derivative of @poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_derivative"+ fmpz_poly_derivative :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_nth_derivative/ /rpoly/ /poly/ /n/ /len/ +-- +-- Sets @(rpoly, len - n)@ to the nth derivative of @(poly, len)@. Also+-- handles the cases where @len \<= n@ correctly. Supports aliasing of+-- @rpoly@ and @poly@.+foreign import ccall "fmpz_poly.h _fmpz_poly_nth_derivative"+ _fmpz_poly_nth_derivative :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CLong -> IO ()++-- | /fmpz_poly_nth_derivative/ /res/ /poly/ /n/ +-- +-- Sets @res@ to the nth derivative of @poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_nth_derivative"+ fmpz_poly_nth_derivative :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- Evaluation ------------------------------------------------------------------++-- | /_fmpz_poly_evaluate_divconquer_fmpz/ /res/ /poly/ /len/ /a/ +-- +-- Evaluates the polynomial @(poly, len)@ at the integer \(a\) using a+-- divide and conquer approach. Assumes that the length of the polynomial+-- is at least one. Allows zero padding. Does not allow aliasing between+-- @res@ and @x@.+foreign import ccall "fmpz_poly.h _fmpz_poly_evaluate_divconquer_fmpz"+ _fmpz_poly_evaluate_divconquer_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_evaluate_divconquer_fmpz/ /res/ /poly/ /a/ +-- +-- Evaluates the polynomial @poly@ at the integer \(a\) using a divide and+-- conquer approach.+-- +-- Aliasing between @res@ and @a@ is supported, however, @res@ may not be+-- part of @poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_evaluate_divconquer_fmpz"+ fmpz_poly_evaluate_divconquer_fmpz :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /_fmpz_poly_evaluate_horner_fmpz/ /res/ /f/ /len/ /a/ +-- +-- Evaluates the polynomial @(f, len)@ at the integer \(a\) using Horner\'s+-- rule, and sets @res@ to the result. Aliasing between @res@ and \(a\) or+-- any of the coefficients of \(f\) is not supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_evaluate_horner_fmpz"+ _fmpz_poly_evaluate_horner_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_evaluate_horner_fmpz/ /res/ /f/ /a/ +-- +-- Evaluates the polynomial \(f\) at the integer \(a\) using Horner\'s+-- rule, and sets @res@ to the result.+-- +-- As expected, aliasing between @res@ and @a@ is supported. However, @res@+-- may not be aliased with a coefficient of \(f\).+foreign import ccall "fmpz_poly.h fmpz_poly_evaluate_horner_fmpz"+ fmpz_poly_evaluate_horner_fmpz :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /_fmpz_poly_evaluate_fmpz/ /res/ /f/ /len/ /a/ +-- +-- Evaluates the polynomial @(f, len)@ at the integer \(a\) and sets @res@+-- to the result. Aliasing between @res@ and \(a\) or any of the+-- coefficients of \(f\) is not supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_evaluate_fmpz"+ _fmpz_poly_evaluate_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_evaluate_fmpz/ /res/ /f/ /a/ +-- +-- Evaluates the polynomial \(f\) at the integer \(a\) and sets @res@ to+-- the result.+-- +-- As expected, aliasing between @res@ and \(a\) is supported. However,+-- @res@ may not be aliased with a coefficient of \(f\).+foreign import ccall "fmpz_poly.h fmpz_poly_evaluate_fmpz"+ fmpz_poly_evaluate_fmpz :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /_fmpz_poly_evaluate_divconquer_fmpq/ /rnum/ /rden/ /f/ /len/ /anum/ /aden/ +-- +-- Evaluates the polynomial @(f, len)@ at the rational @(anum, aden)@ using+-- a divide and conquer approach, and sets @(rnum, rden)@ to the result in+-- lowest terms. Assumes that the length of the polynomial is at least one.+-- +-- Aliasing between @(rnum, rden)@ and @(anum, aden)@ or any of the+-- coefficients of \(f\) is not supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_evaluate_divconquer_fmpq"+ _fmpz_poly_evaluate_divconquer_fmpq :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_evaluate_divconquer_fmpq/ /res/ /f/ /a/ +-- +-- Evaluates the polynomial \(f\) at the rational \(a\) using a divide and+-- conquer approach, and sets @res@ to the result.+foreign import ccall "fmpz_poly.h fmpz_poly_evaluate_divconquer_fmpq"+ fmpz_poly_evaluate_divconquer_fmpq :: Ptr CFmpq -> Ptr CFmpzPoly -> Ptr CFmpq -> IO ()++-- | /_fmpz_poly_evaluate_horner_fmpq/ /rnum/ /rden/ /f/ /len/ /anum/ /aden/ +-- +-- Evaluates the polynomial @(f, len)@ at the rational @(anum, aden)@ using+-- Horner\'s rule, and sets @(rnum, rden)@ to the result in lowest terms.+-- +-- Aliasing between @(rnum, rden)@ and @(anum, aden)@ or any of the+-- coefficients of \(f\) is not supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_evaluate_horner_fmpq"+ _fmpz_poly_evaluate_horner_fmpq :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_evaluate_horner_fmpq/ /res/ /f/ /a/ +-- +-- Evaluates the polynomial \(f\) at the rational \(a\) using Horner\'s+-- rule, and sets @res@ to the result.+foreign import ccall "fmpz_poly.h fmpz_poly_evaluate_horner_fmpq"+ fmpz_poly_evaluate_horner_fmpq :: Ptr CFmpq -> Ptr CFmpzPoly -> Ptr CFmpq -> IO ()++-- | /_fmpz_poly_evaluate_fmpq/ /rnum/ /rden/ /f/ /len/ /anum/ /aden/ +-- +-- Evaluates the polynomial @(f, len)@ at the rational @(anum, aden)@ and+-- sets @(rnum, rden)@ to the result in lowest terms.+-- +-- Aliasing between @(rnum, rden)@ and @(anum, aden)@ or any of the+-- coefficients of \(f\) is not supported.+foreign import ccall "fmpz_poly.h _fmpz_poly_evaluate_fmpq"+ _fmpz_poly_evaluate_fmpq :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_evaluate_fmpq/ /res/ /f/ /a/ +-- +-- Evaluates the polynomial \(f\) at the rational \(a\), and sets @res@ to+-- the result.+foreign import ccall "fmpz_poly.h fmpz_poly_evaluate_fmpq"+ fmpz_poly_evaluate_fmpq :: Ptr CFmpq -> Ptr CFmpzPoly -> Ptr CFmpq -> IO ()++-- -- | /fmpz_poly_evaluate_mpq/ /res/ /f/ /a/ +-- -- +-- -- Evaluates the polynomial \(f\) at the rational \(a\) and sets @res@ to+-- -- the result.+-- foreign import ccall "fmpz_poly.h fmpz_poly_evaluate_mpq"+-- fmpz_poly_evaluate_mpq :: Ptr CMpq -> Ptr CFmpzPoly -> Ptr CMpq -> IO ()++-- | /_fmpz_poly_evaluate_mod/ /poly/ /len/ /a/ /n/ /ninv/ +-- +-- Evaluates @(poly, len)@ at the value \(a\) modulo \(n\) and returns the+-- result. The last argument @ninv@ must be set to the precomputed inverse+-- of \(n\), which can be obtained using the function @n_preinvert_limb@.+foreign import ccall "fmpz_poly.h _fmpz_poly_evaluate_mod"+ _fmpz_poly_evaluate_mod :: Ptr CFmpz -> CLong -> CMpLimb -> CMpLimb -> CMpLimb -> IO CMpLimb++-- | /fmpz_poly_evaluate_mod/ /poly/ /a/ /n/ +-- +-- Evaluates @poly@ at the value \(a\) modulo \(n\) and returns the result.+foreign import ccall "fmpz_poly.h fmpz_poly_evaluate_mod"+ fmpz_poly_evaluate_mod :: Ptr CFmpzPoly -> CMpLimb -> CMpLimb -> IO CMpLimb++-- | /fmpz_poly_evaluate_fmpz_vec/ /res/ /f/ /a/ /n/ +-- +-- Evaluates @f@ at the \(n\) values given in the vector @f@, writing the+-- results to @res@.+foreign import ccall "fmpz_poly.h fmpz_poly_evaluate_fmpz_vec"+ fmpz_poly_evaluate_fmpz_vec :: Ptr CFmpz -> Ptr CFmpzPoly -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_poly_evaluate_horner_d/ /poly/ /n/ /d/ +-- +-- Evaluate @(poly, n)@ at the double \(d\). No attempt is made to do this+-- efficiently or in a numerically stable way. It is currently only used in+-- Flint for quick and dirty evaluations of polynomials with all+-- coefficients positive.+foreign import ccall "fmpz_poly.h _fmpz_poly_evaluate_horner_d"+ _fmpz_poly_evaluate_horner_d :: Ptr CFmpz -> CLong -> CDouble -> IO CDouble++-- | /fmpz_poly_evaluate_horner_d/ /poly/ /d/ +-- +-- Evaluate @poly@ at the double \(d\). No attempt is made to do this+-- efficiently or in a numerically stable way. It is currently only used in+-- Flint for quick and dirty evaluations of polynomials with all+-- coefficients positive.+foreign import ccall "fmpz_poly.h fmpz_poly_evaluate_horner_d"+ fmpz_poly_evaluate_horner_d :: Ptr CFmpzPoly -> CDouble -> IO CDouble++-- | /_fmpz_poly_evaluate_horner_d_2exp/ /exp/ /poly/ /n/ /d/ +-- +-- Evaluate @(poly, n)@ at the double \(d\). Return the result as a double+-- and an exponent @exp@ combination. No attempt is made to do this+-- efficiently or in a numerically stable way. It is currently only used in+-- Flint for quick and dirty evaluations of polynomials with all+-- coefficients positive.+foreign import ccall "fmpz_poly.h _fmpz_poly_evaluate_horner_d_2exp"+ _fmpz_poly_evaluate_horner_d_2exp :: Ptr CLong -> Ptr CFmpz -> CLong -> CDouble -> IO CDouble++-- | /fmpz_poly_evaluate_horner_d_2exp/ /exp/ /poly/ /d/ +-- +-- Evaluate @poly@ at the double \(d\). Return the result as a double and+-- an exponent @exp@ combination. No attempt is made to do this efficiently+-- or in a numerically stable way. It is currently only used in Flint for+-- quick and dirty evaluations of polynomials with all coefficients+-- positive.+foreign import ccall "fmpz_poly.h fmpz_poly_evaluate_horner_d_2exp"+ fmpz_poly_evaluate_horner_d_2exp :: Ptr CLong -> Ptr CFmpzPoly -> CDouble -> IO CDouble++-- | /_fmpz_poly_evaluate_horner_d_2exp2/ /exp/ /poly/ /n/ /d/ /dexp/ +-- +-- Evaluate @poly@ at @d*2^dexp@. Return the result as a double and an+-- exponent @exp@ combination. No attempt is made to do this efficiently or+-- in a numerically stable way. It is currently only used in Flint for+-- quick and dirty evaluations of polynomials with all coefficients+-- positive.+foreign import ccall "fmpz_poly.h _fmpz_poly_evaluate_horner_d_2exp2"+ _fmpz_poly_evaluate_horner_d_2exp2 :: Ptr CLong -> Ptr CFmpz -> CLong -> CDouble -> CLong -> IO CDouble++-- Newton basis ----------------------------------------------------------------++-- | /_fmpz_poly_monomial_to_newton/ /poly/ /roots/ /n/ +-- +-- Converts @(poly, n)@ in-place from its coefficients given in the+-- standard monomial basis to the Newton basis for the roots+-- \(r_0, r_1, \ldots, r_{n-2}\). In other words, this determines output+-- coefficients \(c_i\) such that+-- \(c_0 + c_1(x-r_0) + c_2(x-r_0)(x-r_1) + \ldots + c_{n-1}(x-r_0)(x-r_1)\cdots(x-r_{n-2})\)+-- is equal to the input polynomial. Uses repeated polynomial division.+foreign import ccall "fmpz_poly.h _fmpz_poly_monomial_to_newton"+ _fmpz_poly_monomial_to_newton :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_poly_newton_to_monomial/ /poly/ /roots/ /n/ +-- +-- Converts @(poly, n)@ in-place from its coefficients given in the Newton+-- basis for the roots \(r_0, r_1, \ldots, r_{n-2}\) to the standard+-- monomial basis. In other words, this evaluates+-- \(c_0 + c_1(x-r_0) + c_2(x-r_0)(x-r_1) + \ldots + c_{n-1}(x-r_0)(x-r_1)\cdots(x-r_{n-2})\)+-- where \(c_i\) are the input coefficients for @poly@. Uses Horner\'s+-- rule.+foreign import ccall "fmpz_poly.h _fmpz_poly_newton_to_monomial"+ _fmpz_poly_newton_to_monomial :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- Interpolation ---------------------------------------------------------------++-- | /fmpz_poly_interpolate_fmpz_vec/ /poly/ /xs/ /ys/ /n/ +-- +-- Sets @poly@ to the unique interpolating polynomial of degree at most+-- \(n - 1\) satisfying \(f(x_i) = y_i\) for every pair \(x_i, y_u\) in+-- @xs@ and @ys@, assuming that this polynomial has integer coefficients.+-- +-- If an interpolating polynomial with integer coefficients does not exist,+-- a @FLINT_INEXACT@ exception is thrown.+-- +-- It is assumed that the \(x\) values are distinct.+foreign import ccall "fmpz_poly.h fmpz_poly_interpolate_fmpz_vec"+ fmpz_poly_interpolate_fmpz_vec :: Ptr CFmpzPoly -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- Composition -----------------------------------------------------------------++-- | /_fmpz_poly_compose_horner/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @res@ to the composition of @(poly1, len1)@ and @(poly2, len2)@.+-- +-- Assumes that @res@ has space for @(len1-1)*(len2-1) + 1@ coefficients.+-- Assumes that @poly1@ and @poly2@ are non-zero polynomials. Does not+-- support aliasing between any of the inputs and the output.+foreign import ccall "fmpz_poly.h _fmpz_poly_compose_horner"+ _fmpz_poly_compose_horner :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_compose_horner/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@. To be more+-- precise, denoting @res@, @poly1@, and @poly2@ by \(f\), \(g\), and+-- \(h\), sets \(f(t) = g(h(t))\).+-- +-- This implementation uses Horner\'s method.+foreign import ccall "fmpz_poly.h fmpz_poly_compose_horner"+ fmpz_poly_compose_horner :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_compose_divconquer/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Computes the composition of @(poly1, len1)@ and @(poly2, len2)@ using a+-- divide and conquer approach and places the result into @res@, assuming+-- @res@ can hold the output of length @(len1 - 1) * (len2 - 1) + 1@.+-- +-- Assumes @len1, len2 > 0@. Does not support aliasing between @res@ and+-- any of @(poly1, len1)@ and @(poly2, len2)@.+foreign import ccall "fmpz_poly.h _fmpz_poly_compose_divconquer"+ _fmpz_poly_compose_divconquer :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_compose_divconquer/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@. To be precise+-- about the order of composition, denoting @res@, @poly1@, and @poly2@ by+-- \(f\), \(g\), and \(h\), respectively, sets \(f(t) = g(h(t))\).+foreign import ccall "fmpz_poly.h fmpz_poly_compose_divconquer"+ fmpz_poly_compose_divconquer :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_compose/ /res/ /poly1/ /len1/ /poly2/ /len2/ +-- +-- Sets @res@ to the composition of @(poly1, len1)@ and @(poly2, len2)@.+-- +-- Assumes that @res@ has space for @(len1-1)*(len2-1) + 1@ coefficients.+-- Assumes that @poly1@ and @poly2@ are non-zero polynomials. Does not+-- support aliasing between any of the inputs and the output.+foreign import ccall "fmpz_poly.h _fmpz_poly_compose"+ _fmpz_poly_compose :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_compose/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@. To be precise+-- about the order of composition, denoting @res@, @poly1@, and @poly2@ by+-- \(f\), \(g\), and \(h\), respectively, sets \(f(t) = g(h(t))\).+foreign import ccall "fmpz_poly.h fmpz_poly_compose"+ fmpz_poly_compose :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- Inflation and deflation -----------------------------------------------------++-- | /fmpz_poly_inflate/ /result/ /input/ /inflation/ +-- +-- Sets @result@ to the inflated polynomial \(p(x^n)\) where \(p\) is given+-- by @input@ and \(n\) is given by @inflation@.+foreign import ccall "fmpz_poly.h fmpz_poly_inflate"+ fmpz_poly_inflate :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /fmpz_poly_deflate/ /result/ /input/ /deflation/ +-- +-- Sets @result@ to the deflated polynomial \(p(x^{1/n})\) where \(p\) is+-- given by @input@ and \(n\) is given by @deflation@. Requires \(n > 0\).+foreign import ccall "fmpz_poly.h fmpz_poly_deflate"+ fmpz_poly_deflate :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CULong -> IO ()++-- | /fmpz_poly_deflation/ /input/ +-- +-- Returns the largest integer by which @input@ can be deflated. As special+-- cases, returns 0 if @input@ is the zero polynomial and 1 of @input@ is a+-- constant polynomial.+foreign import ccall "fmpz_poly.h fmpz_poly_deflation"+ fmpz_poly_deflation :: Ptr CFmpzPoly -> IO CULong++-- Taylor shift ----------------------------------------------------------------++-- | /_fmpz_poly_taylor_shift_horner/ /poly/ /c/ /n/ +-- +-- Performs the Taylor shift composing @poly@ by \(x+c\) in-place. Uses an+-- efficient version Horner\'s rule.+foreign import ccall "fmpz_poly.h _fmpz_poly_taylor_shift_horner"+ _fmpz_poly_taylor_shift_horner :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_taylor_shift_horner/ /g/ /f/ /c/ +-- +-- Performs the Taylor shift composing @f@ by \(x+c\).+foreign import ccall "fmpz_poly.h fmpz_poly_taylor_shift_horner"+ fmpz_poly_taylor_shift_horner :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /_fmpz_poly_taylor_shift_divconquer/ /poly/ /c/ /n/ +-- +-- Performs the Taylor shift composing @poly@ by \(x+c\) in-place. Uses the+-- divide-and-conquer polynomial composition algorithm.+foreign import ccall "fmpz_poly.h _fmpz_poly_taylor_shift_divconquer"+ _fmpz_poly_taylor_shift_divconquer :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_taylor_shift_divconquer/ /g/ /f/ /c/ +-- +-- Performs the Taylor shift composing @f@ by \(x+c\). Uses the+-- divide-and-conquer polynomial composition algorithm.+foreign import ccall "fmpz_poly.h fmpz_poly_taylor_shift_divconquer"+ fmpz_poly_taylor_shift_divconquer :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /_fmpz_poly_taylor_shift_multi_mod/ /poly/ /c/ /n/ +-- +-- Performs the Taylor shift composing @poly@ by \(x+c\) in-place. Uses a+-- multimodular algorithm, distributing the computation across+-- @flint_get_num_threads@ threads.+foreign import ccall "fmpz_poly.h _fmpz_poly_taylor_shift_multi_mod"+ _fmpz_poly_taylor_shift_multi_mod :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_taylor_shift_multi_mod/ /g/ /f/ /c/ +-- +-- Performs the Taylor shift composing @f@ by \(x+c\). Uses a multimodular+-- algorithm, distributing the computation across @flint_get_num_threads@+-- threads.+foreign import ccall "fmpz_poly.h fmpz_poly_taylor_shift_multi_mod"+ fmpz_poly_taylor_shift_multi_mod :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- | /_fmpz_poly_taylor_shift/ /poly/ /c/ /n/ +-- +-- Performs the Taylor shift composing @poly@ by \(x+c\) in-place.+foreign import ccall "fmpz_poly.h _fmpz_poly_taylor_shift"+ _fmpz_poly_taylor_shift :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_taylor_shift/ /g/ /f/ /c/ +-- +-- Performs the Taylor shift composing @f@ by \(x+c\).+foreign import ccall "fmpz_poly.h fmpz_poly_taylor_shift"+ fmpz_poly_taylor_shift :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> IO ()++-- Power series composition ----------------------------------------------------++-- | /_fmpz_poly_compose_series_horner/ /res/ /poly1/ /len1/ /poly2/ /len2/ /n/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@ modulo \(x^n\),+-- where the constant term of @poly2@ is required to be zero.+-- +-- Assumes that @len1, len2, n > 0@, that @len1, len2 \<= n@, and that+-- @(len1-1) * (len2-1) + 1 \<= n@, and that @res@ has space for @n@+-- coefficients. Does not support aliasing between any of the inputs and+-- the output.+-- +-- This implementation uses the Horner scheme.+foreign import ccall "fmpz_poly.h _fmpz_poly_compose_series_horner"+ _fmpz_poly_compose_series_horner :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_compose_series_horner/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@ modulo \(x^n\),+-- where the constant term of @poly2@ is required to be zero.+-- +-- This implementation uses the Horner scheme.+foreign import ccall "fmpz_poly.h fmpz_poly_compose_series_horner"+ fmpz_poly_compose_series_horner :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_compose_series_brent_kung/ /res/ /poly1/ /len1/ /poly2/ /len2/ /n/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@ modulo \(x^n\),+-- where the constant term of @poly2@ is required to be zero.+-- +-- Assumes that @len1, len2, n > 0@, that @len1, len2 \<= n@, and that+-- @(len1-1) * (len2-1) + 1 \<= n@, and that @res@ has space for @n@+-- coefficients. Does not support aliasing between any of the inputs and+-- the output.+-- +-- This implementation uses Brent-Kung algorithm 2.1 < [BrentKung1978]>.+foreign import ccall "fmpz_poly.h _fmpz_poly_compose_series_brent_kung"+ _fmpz_poly_compose_series_brent_kung :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_compose_series_brent_kung/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@ modulo \(x^n\),+-- where the constant term of @poly2@ is required to be zero.+-- +-- This implementation uses Brent-Kung algorithm 2.1 < [BrentKung1978]>.+foreign import ccall "fmpz_poly.h fmpz_poly_compose_series_brent_kung"+ fmpz_poly_compose_series_brent_kung :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_compose_series/ /res/ /poly1/ /len1/ /poly2/ /len2/ /n/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@ modulo \(x^n\),+-- where the constant term of @poly2@ is required to be zero.+-- +-- Assumes that @len1, len2, n > 0@, that @len1, len2 \<= n@, and that+-- @(len1-1) * (len2-1) + 1 \<= n@, and that @res@ has space for @n@+-- coefficients. Does not support aliasing between any of the inputs and+-- the output.+-- +-- This implementation automatically switches between the Horner scheme and+-- Brent-Kung algorithm 2.1 depending on the size of the inputs.+foreign import ccall "fmpz_poly.h _fmpz_poly_compose_series"+ _fmpz_poly_compose_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_compose_series/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@ modulo \(x^n\),+-- where the constant term of @poly2@ is required to be zero.+-- +-- This implementation automatically switches between the Horner scheme and+-- Brent-Kung algorithm 2.1 depending on the size of the inputs.+foreign import ccall "fmpz_poly.h fmpz_poly_compose_series"+ fmpz_poly_compose_series :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- Power series reversion ------------------------------------------------------++-- | /_fmpz_poly_revert_series_lagrange/ /Qinv/ /Q/ /Qlen/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @(Q, Qlen)@ as+-- a power series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). The arguments may not be+-- aliased, and @Qlen@ must be at least 2. It is required that \(Q_0 = 0\)+-- and \(Q_1 = \pm 1\).+-- +-- This implementation uses the Lagrange inversion formula.+foreign import ccall "fmpz_poly.h _fmpz_poly_revert_series_lagrange"+ _fmpz_poly_revert_series_lagrange :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_revert_series_lagrange/ /Qinv/ /Q/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). It is required that+-- \(Q_0 = 0\) and \(Q_1 = \pm 1\).+-- +-- This implementation uses the Lagrange inversion formula.+foreign import ccall "fmpz_poly.h fmpz_poly_revert_series_lagrange"+ fmpz_poly_revert_series_lagrange :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_revert_series_lagrange_fast/ /Qinv/ /Q/ /Qlen/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @(Q, Qlen)@ as+-- a power series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). The arguments may not be+-- aliased, and @Qlen@ must be at least 2. It is required that \(Q_0 = 0\)+-- and \(Q_1 = \pm 1\).+-- +-- This implementation uses a reduced-complexity implementation of the+-- Lagrange inversion formula.+foreign import ccall "fmpz_poly.h _fmpz_poly_revert_series_lagrange_fast"+ _fmpz_poly_revert_series_lagrange_fast :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_revert_series_lagrange_fast/ /Qinv/ /Q/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). It is required that+-- \(Q_0 = 0\) and \(Q_1 = \pm 1\).+-- +-- This implementation uses a reduced-complexity implementation of the+-- Lagrange inversion formula.+foreign import ccall "fmpz_poly.h fmpz_poly_revert_series_lagrange_fast"+ fmpz_poly_revert_series_lagrange_fast :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_revert_series_newton/ /Qinv/ /Q/ /Qlen/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). The arguments may not be+-- aliased, and @Qlen@ must be at least 2. It is required that \(Q_0 = 0\)+-- and \(Q_1 = \pm 1\).+-- +-- This implementation uses Newton iteration < [BrentKung1978]>.+foreign import ccall "fmpz_poly.h _fmpz_poly_revert_series_newton"+ _fmpz_poly_revert_series_newton :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_revert_series_newton/ /Qinv/ /Q/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). It is required that+-- \(Q_0 = 0\) and \(Q_1 = \pm 1\).+-- +-- This implementation uses Newton iteration < [BrentKung1978]>.+foreign import ccall "fmpz_poly.h fmpz_poly_revert_series_newton"+ fmpz_poly_revert_series_newton :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_revert_series/ /Qinv/ /Q/ /Qlen/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). The arguments may not be+-- aliased, and @Qlen@ must be at least 2. It is required that \(Q_0 = 0\)+-- and \(Q_1 = \pm 1\).+-- +-- This implementation defaults to the fast version of Lagrange+-- interpolation.+foreign import ccall "fmpz_poly.h _fmpz_poly_revert_series"+ _fmpz_poly_revert_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_revert_series/ /Qinv/ /Q/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). It is required that+-- \(Q_0 = 0\) and \(Q_1 = \pm 1\).+-- +-- This implementation defaults to the fast version of Lagrange+-- interpolation.+foreign import ccall "fmpz_poly.h fmpz_poly_revert_series"+ fmpz_poly_revert_series :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- Square root -----------------------------------------------------------------++-- | /_fmpz_poly_sqrtrem_classical/ /res/ /r/ /poly/ /len/ +-- +-- Returns 1 if @(poly, len)@ can be written in the form \(A^2 + R\) where+-- deg\`(R) \< deg(@\`poly@), otherwise returns \(0\). If it can be so+-- written, @(res, m - 1)@ is set to \(A\) and @(res, m)@ is set to \(R\),+-- where \(m =\) deg\`(@\`poly@)\/2 + 1.+-- +-- For efficiency reasons, @r@ must have room for @len@ coefficients, and+-- may alias @poly@.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqrtrem_classical"+ _fmpz_poly_sqrtrem_classical :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_poly_sqrtrem_classical/ /b/ /r/ /a/ +-- +-- If \(a\) can be written as \(b^2 + r\) with deg\`(r) \< deg(a)\/2\`,+-- return \(1\) and set \(b\) and \(r\) appropriately. Otherwise return+-- \(0\).+foreign import ccall "fmpz_poly.h fmpz_poly_sqrtrem_classical"+ fmpz_poly_sqrtrem_classical :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO CInt++-- | /_fmpz_poly_sqrtrem_divconquer/ /res/ /r/ /poly/ /len/ /temp/ +-- +-- Returns 1 if @(poly, len)@ can be written in the form \(A^2 + R\) where+-- deg\`(R) \< deg(@\`poly@), otherwise returns \(0\). If it can be so+-- written, @(res, m - 1)@ is set to \(A\) and @(res, m)@ is set to \(R\),+-- where \(m =\) deg\`(@\`poly@)\/2 + 1.+-- +-- For efficiency reasons, @r@ must have room for @len@ coefficients, and+-- may alias @poly@. Temporary space of @len@ coefficients is required.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqrtrem_divconquer"+ _fmpz_poly_sqrtrem_divconquer :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO CInt++-- | /fmpz_poly_sqrtrem_divconquer/ /b/ /r/ /a/ +-- +-- If \(a\) can be written as \(b^2 + r\) with deg\`(r) \< deg(a)\/2\`,+-- return \(1\) and set \(b\) and \(r\) appropriately. Otherwise return+-- \(0\).+foreign import ccall "fmpz_poly.h fmpz_poly_sqrtrem_divconquer"+ fmpz_poly_sqrtrem_divconquer :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO CInt++-- | /_fmpz_poly_sqrt_classical/ /res/ /poly/ /len/ /exact/ +-- +-- If @exact@ is \(1\) and @(poly, len)@ is a perfect square, sets+-- @(res, len \/ 2 + 1)@ to the square root of @poly@ with positive leading+-- coefficient and returns 1. Otherwise returns 0.+-- +-- If @exact@ is \(0\), allows a remainder after the square root, which is+-- not computed.+-- +-- This function first uses various tests to detect nonsquares quickly.+-- Then, it computes the square root iteratively from top to bottom,+-- requiring \(O(n^2)\) coefficient operations.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqrt_classical"+ _fmpz_poly_sqrt_classical :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /fmpz_poly_sqrt_classical/ /b/ /a/ +-- +-- If @a@ is a perfect square, sets @b@ to the square root of @a@ with+-- positive leading coefficient and returns 1. Otherwise returns 0.+foreign import ccall "fmpz_poly.h fmpz_poly_sqrt_classical"+ fmpz_poly_sqrt_classical :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO CInt++-- | /_fmpz_poly_sqrt_KS/ /res/ /poly/ /len/ +-- +-- Heuristic square root. If the return value is \(-1\), the function+-- failed, otherwise it succeeded and the following applies.+-- +-- If @(poly, len)@ is a perfect square, sets @(res, len \/ 2 + 1)@ to the+-- square root of @poly@ with positive leading coefficient and returns 1.+-- Otherwise returns 0.+-- +-- This function first uses various tests to detect nonsquares quickly.+-- Then, it computes the square root iteratively from top to bottom.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqrt_KS"+ _fmpz_poly_sqrt_KS :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_poly_sqrt_KS/ /b/ /a/ +-- +-- Heuristic square root. If the return value is \(-1\), the function+-- failed, otherwise it succeeded and the following applies.+-- +-- If @a@ is a perfect square, sets @b@ to the square root of @a@ with+-- positive leading coefficient and returns 1. Otherwise returns 0.+foreign import ccall "fmpz_poly.h fmpz_poly_sqrt_KS"+ fmpz_poly_sqrt_KS :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO CInt++-- | /_fmpz_poly_sqrt_divconquer/ /res/ /poly/ /len/ /exact/ +-- +-- If @exact@ is \(1\) and @(poly, len)@ is a perfect square, sets+-- @(res, len \/ 2 + 1)@ to the square root of @poly@ with positive leading+-- coefficient and returns 1. Otherwise returns 0.+-- +-- If @exact@ is \(0\), allows a remainder after the square root, which is+-- not computed.+-- +-- This function first uses various tests to detect nonsquares quickly.+-- Then, it computes the square root iteratively from top to bottom.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqrt_divconquer"+ _fmpz_poly_sqrt_divconquer :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CInt -> IO CInt++-- | /fmpz_poly_sqrt_divconquer/ /b/ /a/ +-- +-- If @a@ is a perfect square, sets @b@ to the square root of @a@ with+-- positive leading coefficient and returns 1. Otherwise returns 0.+foreign import ccall "fmpz_poly.h fmpz_poly_sqrt_divconquer"+ fmpz_poly_sqrt_divconquer :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO CInt++-- | /_fmpz_poly_sqrt/ /res/ /poly/ /len/ +-- +-- If @(poly, len)@ is a perfect square, sets @(res, len \/ 2 + 1)@ to the+-- square root of @poly@ with positive leading coefficient and returns 1.+-- Otherwise returns 0.+foreign import ccall "fmpz_poly.h _fmpz_poly_sqrt"+ _fmpz_poly_sqrt :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_poly_sqrt/ /b/ /a/ +-- +-- If @a@ is a perfect square, sets @b@ to the square root of @a@ with+-- positive leading coefficient and returns 1. Otherwise returns 0.+foreign import ccall "fmpz_poly.h fmpz_poly_sqrt"+ fmpz_poly_sqrt :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO CInt++-- | /_fmpz_poly_sqrt_series/ /res/ /poly/ /len/ /n/ +-- +-- Set @(res, n)@ to the square root of the series @(poly, n)@, if it+-- exists, and return \(1\), otherwise, return \(0\).+-- +-- If the valuation of @poly@ is not zero, @res@ is zero padded to make up+-- for the fact that the square root may not be known to precision \(n\).+foreign import ccall "fmpz_poly.h _fmpz_poly_sqrt_series"+ _fmpz_poly_sqrt_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO CInt++-- | /fmpz_poly_sqrt_series/ /b/ /a/ /n/ +-- +-- Set @b@ to the square root of the series @a@, where the latter is taken+-- to be a series of precision \(n\). If such a square root exists, return+-- \(1\), otherwise, return \(0\).+-- +-- Note that if the valuation of @a@ is not zero, @b@ will not have+-- precision @n@. It is given only to the precision to which the square+-- root can be computed.+foreign import ccall "fmpz_poly.h fmpz_poly_sqrt_series"+ fmpz_poly_sqrt_series :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO CInt++-- Power sums ------------------------------------------------------------------++-- | /_fmpz_poly_power_sums_naive/ /res/ /poly/ /len/ /n/ +-- +-- Compute the (truncated) power sums series of the monic polynomial+-- @(poly,len)@ up to length \(n\) using Newton identities.+foreign import ccall "fmpz_poly.h _fmpz_poly_power_sums_naive"+ _fmpz_poly_power_sums_naive :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /fmpz_poly_power_sums_naive/ /res/ /poly/ /n/ +-- +-- Compute the (truncated) power sum series of the monic polynomial @poly@+-- up to length \(n\) using Newton identities.+foreign import ccall "fmpz_poly.h fmpz_poly_power_sums_naive"+ fmpz_poly_power_sums_naive :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_power_sums/ /res/ /poly/ /n/ +-- +-- Compute the (truncated) power sums series of the monic polynomial @poly@+-- up to length \(n\). That is the power series whose coefficient of degree+-- \(i\) is the sum of the \(i\)-th power of all (complex) roots of the+-- polynomial @poly@.+foreign import ccall "fmpz_poly.h fmpz_poly_power_sums"+ fmpz_poly_power_sums :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /_fmpz_poly_power_sums_to_poly/ /res/ /poly/ /len/ +-- +-- Compute the (monic) polynomial given by its power sums series+-- @(poly,len)@.+foreign import ccall "fmpz_poly.h _fmpz_poly_power_sums_to_poly"+ _fmpz_poly_power_sums_to_poly :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_power_sums_to_poly/ /res/ /Q/ +-- +-- Compute the (monic) polynomial given its power sums series @(Q)@.+foreign import ccall "fmpz_poly.h fmpz_poly_power_sums_to_poly"+ fmpz_poly_power_sums_to_poly :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> IO ()++-- Signature -------------------------------------------------------------------++-- | /_fmpz_poly_signature/ /r1/ /r2/ /poly/ /len/ +-- +-- Computes the signature \((r_1, r_2)\) of the polynomial @(poly, len)@.+-- Assumes that the polynomial is squarefree over \(\mathbb{Q}\).+foreign import ccall "fmpz_poly.h _fmpz_poly_signature"+ _fmpz_poly_signature :: Ptr CLong -> Ptr CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_signature/ /r1/ /r2/ /poly/ +-- +-- Computes the signature \((r_1, r_2)\) of the polynomial @poly@, which is+-- assumed to be square-free over \(\mathbb{Q}\). The values of \(r_1\) and+-- \(2 r_2\) are the number of real and complex roots of the polynomial,+-- respectively. For convenience, the zero polynomial is allowed, in which+-- case the output is \((0, 0)\).+-- +-- If the polynomial is not square-free, the behaviour is undefined and an+-- exception may be raised.+-- +-- This function uses the algorithm described in [Algorithm+-- 4.1.11]< [Coh1996]>.+foreign import ccall "fmpz_poly.h fmpz_poly_signature"+ fmpz_poly_signature :: Ptr CLong -> Ptr CLong -> Ptr CFmpzPoly -> IO ()++-- Hensel lifting --------------------------------------------------------------++-- | /fmpz_poly_hensel_build_tree/ /link/ /v/ /w/ /fac/ +-- +-- Initialises and builds a Hensel tree consisting of two arrays \(v\),+-- \(w\) of polynomials an array of links, called @link@.+-- +-- The caller supplies a set of \(r\) local factors (in the factor+-- structure @fac@) of some polynomial \(F\) over \(\mathbf{Z}\). They also+-- supply two arrays of initialised polynomials \(v\) and \(w\), each of+-- length \(2r - 2\) and an array @link@, also of length \(2r - 2\).+-- +-- We will have five arrays: a \(v\) of @fmpz_poly_t@\'s and a \(V\) of+-- @nmod_poly_t@\'s and also a \(w\) and a \(W\) and @link@. Here\'s the+-- idea: we sort each leaf and node of a factor tree by degree, in fact+-- choosing to multiply the two smallest factors, then the next two+-- smallest (factors or products) etc.until a tree is made. The tree will+-- be stored in the \(v\)\'s. The first two elements of \(v\) will be the+-- smallest modular factors, the last two elements of \(v\) will multiply+-- to form \(F\) itself. Since \(v\) will be rearranging the original+-- factors we will need to be able to recover the original order. For this+-- we use the array @link@ which has nonnegative even numbers and negative+-- numbers. It is an array of @slong@\'s which aligns with \(V\) and \(v\)+-- if @link@ has a negative number in spot \(j\) that means \(V_j\) is an+-- original modular factor which has been lifted, if @link[j]@ is a+-- nonnegative even number then \(V_j\) stores a product of the two entries+-- at @V[link[j]]@ and @V[link[j]+1]@. \(W\) and \(w\) play the role of the+-- extended GCD, at \(V_0\), \(V_2\), \(V_4\), etc.we have a new product,+-- \(W_0\), \(W_2\), \(W_4\), etc.are the XGCD cofactors of the \(V\)\'s.+-- For example, \(V_0 W_0 + V_1 W_1 \equiv 1 \pmod{p^{\ell}}\) for some+-- \(\ell\). These will be lifted along with the entries in \(V\). It is+-- not enough to just lift each factor, we have to lift the entire tree and+-- the tree of XGCD cofactors.+foreign import ccall "fmpz_poly.h fmpz_poly_hensel_build_tree"+ fmpz_poly_hensel_build_tree :: Ptr CLong -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CNModPolyFactor -> IO ()++-- | /fmpz_poly_hensel_lift/ /G/ /H/ /A/ /B/ /f/ /g/ /h/ /a/ /b/ /p/ /p1/ +-- +-- This is the main Hensel lifting routine, which performs a Hensel step+-- from polynomials mod \(p\) to polynomials mod \(P = p p_1\). One starts+-- with polynomials \(f\), \(g\), \(h\) such that \(f = gh \pmod p\). The+-- polynomials \(a\), \(b\) satisfy \(ag + bh = 1 \pmod p\).+-- +-- The lifting formulae are+-- +-- \[`\]+-- \[G = \biggl( \bigl( \frac{f-gh}{p} \bigr) b \bmod g \biggr) p + g\]+-- \[H = \biggl( \bigl( \frac{f-gh}{p} \bigr) a \bmod h \biggr) p + h\]+-- \[B = \biggl( \bigl( \frac{1-aG-bH}{p} \bigr) b \bmod g \biggr) p + b\]+-- \[A = \biggl( \bigl( \frac{1-aG-bH}{p} \bigr) a \bmod h \biggr) p + a\]+-- +-- Upon return we have \(A G + B H = 1 \pmod P\) and \(f = G H \pmod P\),+-- where \(G = g \pmod p\) etc.+-- +-- We require that \(1 < p_1 \leq p\) and that the input polynomials+-- \(f, g, h\) have degree at least \(1\) and that the input polynomials+-- \(a\) and \(b\) are non-zero.+-- +-- The output arguments \(G, H, A, B\) may only be aliased with the input+-- arguments \(g, h, a, b\), respectively.+foreign import ccall "fmpz_poly.h fmpz_poly_hensel_lift"+ fmpz_poly_hensel_lift :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_hensel_lift_without_inverse/ /Gout/ /Hout/ /f/ /g/ /h/ /a/ /b/ /p/ /p1/ +-- +-- Given polynomials such that \(f = gh \pmod p\) and+-- \(ag + bh = 1 \pmod p\), lifts only the factors \(g\) and \(h\) modulo+-- \(P = p p_1\).+-- +-- See @fmpz_poly_hensel_lift@.+foreign import ccall "fmpz_poly.h fmpz_poly_hensel_lift_without_inverse"+ fmpz_poly_hensel_lift_without_inverse :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_hensel_lift_only_inverse/ /Aout/ /Bout/ /G/ /H/ /a/ /b/ /p/ /p1/ +-- +-- Given polynomials such that \(f = gh \pmod p\) and+-- \(ag + bh = 1 \pmod p\), lifts only the cofactors \(a\) and \(b\) modulo+-- \(P = p p_1\).+-- +-- See @fmpz_poly_hensel_lift@.+foreign import ccall "fmpz_poly.h fmpz_poly_hensel_lift_only_inverse"+ fmpz_poly_hensel_lift_only_inverse :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_hensel_lift_tree_recursive/ /link/ /v/ /w/ /f/ /j/ /inv/ /p0/ /p1/ +-- +-- Takes a current Hensel tree @(link, v, w)@ and a pair \((j,j+1)\) of+-- entries in the tree and lifts the tree from mod \(p_0\) to mod+-- \(P = p_0 p_1\), where \(1 < p_1 \leq p_0\).+-- +-- Set @inv@ to \(-1\) if restarting Hensel lifting, \(0\) if stopping and+-- \(1\) otherwise.+-- +-- Here \(f = g h\) is the polynomial whose factors we are trying to lift.+-- We will have that @v[j]@ is the product of @v[link[j]]@ and+-- @v[link[j] + 1]@ as described above.+-- +-- Does support aliasing of \(f\) with one of the polynomials in the lists+-- \(v\) and \(w\). But the polynomials in these two lists are not allowed+-- to be aliases of each other.+foreign import ccall "fmpz_poly.h fmpz_poly_hensel_lift_tree_recursive"+ fmpz_poly_hensel_lift_tree_recursive :: Ptr CLong -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> CLong -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_hensel_lift_tree/ /link/ /v/ /w/ /f/ /r/ /p/ /e0/ /e1/ /inv/ +-- +-- Computes \(p_0 = p^{e_0}\) and \(p_1 = p^{e_1 - e_0}\) for a small prime+-- \(p\) and \(P = p^{e_1}\).+-- +-- If we aim to lift to \(p^b\) then \(f\) is the polynomial whose factors+-- we wish to lift, made monic mod \(p^b\). As usual, @(link, v, w)@ is an+-- initialised tree.+-- +-- This starts the recursion on lifting the /product tree/ for lifting from+-- \(p^{e_0}\) to \(p^{e_1}\). The value of @inv@ corresponds to that given+-- for the function @fmpz_poly_hensel_lift_tree_recursive@. We set \(r\) to+-- the number of local factors of \(f\).+-- +-- In terms of the notation, above \(P = p^{e_1}\), \(p_0 = p^{e_0}\) and+-- \(p_1 = p^{e_1-e_0}\).+-- +-- Assumes that \(f\) is monic.+-- +-- Assumes that \(1 < p_1 \leq p_0\), that is, \(0 < e_1 \leq e_0\).+foreign import ccall "fmpz_poly.h fmpz_poly_hensel_lift_tree"+ fmpz_poly_hensel_lift_tree :: Ptr CLong -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> Ptr CFmpz -> CLong -> CLong -> CLong -> IO ()++-- | /_fmpz_poly_hensel_start_lift/ /lifted_fac/ /link/ /v/ /w/ /f/ /local_fac/ /N/ +-- +-- This function takes the local factors in @local_fac@ and Hensel lifts+-- them until they are known mod \(p^N\), where \(N \geq 1\).+-- +-- These lifted factors will be stored (in the same ordering) in+-- @lifted_fac@. It is assumed that @link@, @v@, and @w@ are initialized+-- arrays @fmpz_poly_t@\'s with at least \(2*r - 2\) entries and that+-- \(r \geq 2\). This is done outside of this function so that you can keep+-- them for restarting Hensel lifting later. The product of local factors+-- must be squarefree.+-- +-- The return value is an exponent which must be passed to the function+-- @_fmpz_poly_hensel_continue_lift@ as @prev_exp@ if the Hensel lifting is+-- to be resumed.+-- +-- Currently, supports the case when \(N = 1\) for convenience, although it+-- is preferable in this case to simple iterate over the local factors and+-- convert them to polynomials over \(\mathbf{Z}\).+foreign import ccall "fmpz_poly.h _fmpz_poly_hensel_start_lift"+ _fmpz_poly_hensel_start_lift :: Ptr CFmpzPolyFactor -> Ptr CLong -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CNModPolyFactor -> CLong -> IO CLong++-- | /_fmpz_poly_hensel_continue_lift/ /lifted_fac/ /link/ /v/ /w/ /f/ /prev/ /curr/ /N/ /p/ +-- +-- This function restarts a stopped Hensel lift.+-- +-- It lifts from @curr@ to \(N\). It also requires @prev@ (to lift the+-- cofactors) given as the return value of the function+-- @_fmpz_poly_hensel_start_lift@ or the function+-- @_fmpz_poly_hensel_continue_lift@. The current lifted factors are+-- supplied in @lifted_fac@ and upon return are updated there. As usual+-- @link@, @v@, and @w@ describe the current Hensel tree, \(r\) is the+-- number of local factors and \(p\) is the small prime modulo whose power+-- we are lifting to. It is required that @curr@ be at least \(1\) and that+-- @N > curr@.+-- +-- Currently, supports the case when @prev@ and @curr@ are equal.+foreign import ccall "fmpz_poly.h _fmpz_poly_hensel_continue_lift"+ _fmpz_poly_hensel_continue_lift :: Ptr CFmpzPolyFactor -> Ptr CLong -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CLong -> CLong -> CLong -> Ptr CFmpz -> IO CLong++-- | /fmpz_poly_hensel_lift_once/ /lifted_fac/ /f/ /local_fac/ /N/ +-- +-- This function does a Hensel lift.+-- +-- It lifts local factors stored in @local_fac@ of \(f\) to \(p^N\), where+-- \(N \geq 2\). The lifted factors will be stored in @lifted_fac@. This+-- lift cannot be restarted. This function is a convenience function+-- intended for end users. The product of local factors must be squarefree.+foreign import ccall "fmpz_poly.h fmpz_poly_hensel_lift_once"+ fmpz_poly_hensel_lift_once :: Ptr CFmpzPolyFactor -> Ptr CFmpzPoly -> Ptr CNModPolyFactor -> CLong -> IO ()++-- Input and output ------------------------------------------------------------++-- The functions in this section are not intended to be particularly fast.+-- They are intended mainly as a debugging aid.+--+-- For the string output functions there are two variants. The first uses a+-- simple string representation of polynomials which prints only the length+-- of the polynomial and the integer coefficients, whilst the latter+-- variant, appended with @_pretty@, uses a more traditional string+-- representation of polynomials which prints a variable name as part of+-- the representation.+--+-- The first string representation is given by a sequence of integers, in+-- decimal notation, separated by white space. The first integer gives the+-- length of the polynomial; the remaining integers are the coefficients.+-- For example \(5x^3 - x + 1\) is represented by the string+-- @\"4 1 -1 0 5\"@, and the zero polynomial is represented by @\"0\"@.+-- The coefficients may be signed and arbitrary precision.+--+-- The string representation of the functions appended by @_pretty@+-- includes only the non-zero terms of the polynomial, starting with the+-- one of highest degree. Each term starts with a coefficient, prepended+-- with a sign, followed by the character @*@, followed by a variable name,+-- which must be passed as a string parameter to the function, followed by+-- a caret @^@ followed by a non-negative exponent.+--+-- If the sign of the leading coefficient is positive, it is omitted. Also+-- the exponents of the degree 1 and 0 terms are omitted, as is the+-- variable and the @*@ character in the case of the degree 0 coefficient.+-- If the coefficient is plus or minus one, the coefficient is omitted,+-- except for the sign.+--+-- Some examples of the @_pretty@ representation are:+--++++-- | /_fmpz_poly_print/ /poly/ /len/ +-- +-- Prints the polynomial @(poly, len)@ to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_poly.h _fmpz_poly_print"+ _fmpz_poly_print :: Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_poly_print/ /poly/ +-- +-- Prints the polynomial to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+fmpz_poly_print :: Ptr CFmpzPoly -> IO CInt+fmpz_poly_print poly = printCStr fmpz_poly_get_str poly++-- | /_fmpz_poly_print_pretty/ /poly/ /len/ /x/ +-- +-- Prints the pretty representation of @(poly, len)@ to @stdout@, using the+-- string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_poly.h _fmpz_poly_print_pretty"+ _fmpz_poly_print_pretty :: Ptr CFmpz -> CLong -> CString -> IO CInt++-- | /fmpz_poly_print_pretty/ /poly/ /x/ +-- +-- Prints the pretty representation of @poly@ to @stdout@, using the string+-- @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+fmpz_poly_print_pretty poly var =+ printCStr (flip fmpz_poly_get_str_pretty var) poly++-- | /_fmpz_poly_fprint/ /file/ /poly/ /len/ +-- +-- Prints the polynomial @(poly, len)@ to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_poly.h _fmpz_poly_fprint"+ _fmpz_poly_fprint :: Ptr CFile -> Ptr CFmpz -> CLong -> IO CInt++-- | /fmpz_poly_fprint/ /file/ /poly/ +-- +-- Prints the polynomial to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_poly.h fmpz_poly_fprint"+ fmpz_poly_fprint :: Ptr CFile -> Ptr CFmpzPoly -> IO CInt++-- | /_fmpz_poly_fprint_pretty/ /file/ /poly/ /len/ /x/ +-- +-- Prints the pretty representation of @(poly, len)@ to the stream @file@,+-- using the string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_poly.h _fmpz_poly_fprint_pretty"+ _fmpz_poly_fprint_pretty :: Ptr CFile -> Ptr CFmpz -> CLong -> CString -> IO CInt++-- | /fmpz_poly_fprint_pretty/ /file/ /poly/ /x/ +-- +-- Prints the pretty representation of @poly@ to the stream @file@, using+-- the string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_poly.h fmpz_poly_fprint_pretty"+ fmpz_poly_fprint_pretty :: Ptr CFile -> Ptr CFmpzPoly -> CString -> IO CInt++-- | /fmpz_poly_read/ /poly/ +-- +-- Reads a polynomial from @stdin@, storing the result in @poly@.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_poly.h fmpz_poly_read"+ fmpz_poly_read :: Ptr CFmpzPoly -> IO CInt++-- | /fmpz_poly_read_pretty/ /poly/ /x/ +-- +-- Reads a polynomial in pretty format from @stdin@.+-- +-- For further details, see the documentation for the function+-- @fmpz_poly_fread_pretty@.+foreign import ccall "fmpz_poly.h fmpz_poly_read_pretty"+ fmpz_poly_read_pretty :: Ptr CFmpzPoly -> Ptr (Ptr CChar) -> IO CInt++-- | /fmpz_poly_fread/ /file/ /poly/ +-- +-- Reads a polynomial from the stream @file@, storing the result in @poly@.+-- +-- In case of success, returns a positive number. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_poly.h fmpz_poly_fread"+ fmpz_poly_fread :: Ptr CFile -> Ptr CFmpzPoly -> IO CInt++-- | /fmpz_poly_fread_pretty/ /file/ /poly/ /x/ +-- +-- Reads a polynomial from the file @file@ and sets @poly@ to this+-- polynomial. The string @*x@ is set to the variable name that is used in+-- the input.+-- +-- Returns a positive value, equal to the number of characters read from+-- the file, in case of success. Returns a non-positive value in case of+-- failure, which could either be a read error or the indicator of a+-- malformed input.+foreign import ccall "fmpz_poly.h fmpz_poly_fread_pretty"+ fmpz_poly_fread_pretty :: Ptr CFile -> Ptr CFmpzPoly -> Ptr (Ptr CChar) -> IO CInt++-- Modular reduction and reconstruction ----------------------------------------++-- | /fmpz_poly_get_nmod_poly/ /Amod/ /A/ +-- +-- Sets the coefficients of @Amod@ to the coefficients in @A@, reduced by+-- the modulus of @Amod@.+foreign import ccall "fmpz_poly.h fmpz_poly_get_nmod_poly"+ fmpz_poly_get_nmod_poly :: Ptr CNModPoly -> Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_set_nmod_poly/ /A/ /Amod/ +-- +-- Sets the coefficients of @A@ to the residues in @Amod@, normalised to+-- the interval \(-m/2 \le r < m/2\) where \(m\) is the modulus.+foreign import ccall "fmpz_poly.h fmpz_poly_set_nmod_poly"+ fmpz_poly_set_nmod_poly :: Ptr CFmpzPoly -> Ptr CNModPoly -> IO ()++-- | /fmpz_poly_set_nmod_poly_unsigned/ /A/ /Amod/ +-- +-- Sets the coefficients of @A@ to the residues in @Amod@, normalised to+-- the interval \(0 \le r < m\) where \(m\) is the modulus.+foreign import ccall "fmpz_poly.h fmpz_poly_set_nmod_poly_unsigned"+ fmpz_poly_set_nmod_poly_unsigned :: Ptr CFmpzPoly -> Ptr CNModPoly -> IO ()++-- | /_fmpz_poly_CRT_ui_precomp/ /res/ /poly1/ /len1/ /m1/ /poly2/ /len2/ /m2/ /m2inv/ /m1m2/ /c/ /sign/ +-- +-- Sets the coefficients in @res@ to the CRT reconstruction modulo+-- \(m_1m_2\) of the residues @(poly1, len1)@ and @(poly2, len2)@ which are+-- images modulo \(m_1\) and \(m_2\) respectively. The caller must supply+-- the precomputed product of the input moduli as \(m_1m_2\), the inverse+-- of \(m_1\) modulo \(m_2\) as \(c\), and the precomputed inverse of+-- \(m_2\) (in the form computed by @n_preinvert_limb@) as @m2inv@.+-- +-- If @sign@ = 0, residues \(0 <= r < m_1 m_2\) are computed, while if+-- @sign@ = 1, residues \(-m_1 m_2/2 <= r < m_1 m_2/2\) are computed.+-- +-- Coefficients of @res@ are written up to the maximum of @len1@ and+-- @len2@.+foreign import ccall "fmpz_poly.h _fmpz_poly_CRT_ui_precomp"+ _fmpz_poly_CRT_ui_precomp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CMp -> CLong -> CMpLimb -> CMpLimb -> Ptr CFmpz -> CMpLimb -> CInt -> IO ()++-- | /_fmpz_poly_CRT_ui/ /res/ /poly1/ /len1/ /m1/ /poly2/ /len2/ /m2/ /m2inv/ /sign/ +-- +-- This function is identical to @_fmpz_poly_CRT_ui_precomp@, apart from+-- automatically computing \(m_1m_2\) and \(c\). It also aborts if \(c\)+-- cannot be computed.+foreign import ccall "fmpz_poly.h _fmpz_poly_CRT_ui"+ _fmpz_poly_CRT_ui :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CMp -> CLong -> CMpLimb -> CMpLimb -> CInt -> IO ()++-- | /fmpz_poly_CRT_ui/ /res/ /poly1/ /m/ /poly2/ /sign/ +-- +-- Given @poly1@ with coefficients modulo @m@ and @poly2@ with modulus+-- \(n\), sets @res@ to the CRT reconstruction modulo \(mn\) with+-- coefficients satisfying \(-mn/2 \le c < mn/2\) (if sign = 1) or+-- \(0 \le c < mn\) (if sign = 0).+foreign import ccall "fmpz_poly.h fmpz_poly_CRT_ui"+ fmpz_poly_CRT_ui :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpz -> Ptr CNModPoly -> CInt -> IO ()++-- Products --------------------------------------------------------------------++-- | /_fmpz_poly_product_roots_fmpz_vec/ /poly/ /xs/ /n/ +-- +-- Sets @(poly, n + 1)@ to the monic polynomial which is the product of+-- \((x - x_0)(x - x_1) \cdots (x - x_{n-1})\), the roots \(x_i\) being+-- given by @xs@.+-- +-- Aliasing of the input and output is not allowed.+foreign import ccall "fmpz_poly.h _fmpz_poly_product_roots_fmpz_vec"+ _fmpz_poly_product_roots_fmpz_vec :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_product_roots_fmpz_vec/ /poly/ /xs/ /n/ +-- +-- Sets @poly@ to the monic polynomial which is the product of+-- \((x - x_0)(x - x_1) \cdots (x - x_{n-1})\), the roots \(x_i\) being+-- given by @xs@.+foreign import ccall "fmpz_poly.h fmpz_poly_product_roots_fmpz_vec"+ fmpz_poly_product_roots_fmpz_vec :: Ptr CFmpzPoly -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_poly_product_roots_fmpq_vec/ /poly/ /xs/ /n/ +-- +-- Sets @(poly, n + 1)@ to the product of+-- \((q_0 x - p_0)(q_1 x - p_1) \cdots (q_{n-1} x - p_{n-1})\), the roots+-- \(p_i/q_i\) being given by @xs@.+foreign import ccall "fmpz_poly.h _fmpz_poly_product_roots_fmpq_vec"+ _fmpz_poly_product_roots_fmpq_vec :: Ptr CFmpz -> Ptr CFmpq -> CLong -> IO ()++-- | /fmpz_poly_product_roots_fmpq_vec/ /poly/ /xs/ /n/ +-- +-- Sets @poly@ to the polynomial which is the product of+-- \((q_0 x - p_0)(q_1 x - p_1) \cdots (q_{n-1} x - p_{n-1})\), the roots+-- \(p_i/q_i\) being given by @xs@.+foreign import ccall "fmpz_poly.h fmpz_poly_product_roots_fmpq_vec"+ fmpz_poly_product_roots_fmpq_vec :: Ptr CFmpzPoly -> Ptr CFmpq -> CLong -> IO ()++-- Roots -----------------------------------------------------------------------++-- | /_fmpz_poly_bound_roots/ /bound/ /poly/ /len/ +-- +-- Computes a nonnegative integer @bound@ that bounds the absolute value of+-- all complex roots of @poly@. Uses Fujiwara\'s bound+-- +-- \[`\]+-- \[2 \max \left(+-- \left|\frac{a_{n-1}}{a_n}\right|,+-- \left|\frac{a_{n-2}}{a_n}\right|^{\frac{1}{2}}, \dotsc+-- \left|\frac{a_1}{a_n}\right|^{\frac{1}{n-1}},+-- \left|\frac{a_0}{2a_n}\right|^{\frac{1}{n}}+-- \right)\]+-- +-- where the coefficients of the polynomial are \(a_0, \ldots, a_n\).+foreign import ccall "fmpz_poly.h _fmpz_poly_bound_roots"+ _fmpz_poly_bound_roots :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_poly_num_real_roots_sturm/ /n_neg/ /n_pos/ /pol/ /len/ +-- +-- Sets @n_neg@ and @n_pos@ to the number of negative and positive roots of+-- the polynomial @(pol, len)@ using Sturm sequence. The Sturm sequence is+-- computed via subresultant remainders obtained by repeated call to the+-- function @_fmpz_poly_pseudo_rem_cohen@.+-- +-- The polynomial is assumed to be squarefree, of degree larger than 1 and+-- with non-zero constant coefficient.+foreign import ccall "fmpz_poly.h _fmpz_poly_num_real_roots_sturm"+ _fmpz_poly_num_real_roots_sturm :: Ptr CLong -> Ptr CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /fmpz_poly_num_real_roots_sturm/ /pol/ +-- +-- Returns the number of real roots of the squarefree polynomial @pol@+-- using Sturm sequence.+-- +-- The polynomial is assumed to be squarefree.+foreign import ccall "fmpz_poly.h fmpz_poly_num_real_roots_sturm"+ fmpz_poly_num_real_roots_sturm :: Ptr CFmpzPoly -> IO CLong++-- | /_fmpz_poly_num_real_roots/ /pol/ /len/ +-- +-- Returns the number of real roots of the squarefree polynomial+-- @(pol, len)@.+-- +-- The polynomial is assumed to be squarefree.+foreign import ccall "fmpz_poly.h _fmpz_poly_num_real_roots"+ _fmpz_poly_num_real_roots :: Ptr CFmpz -> CLong -> IO CLong++-- | /fmpz_poly_num_real_roots/ /pol/ +-- +-- Returns the number of real roots of the squarefree polynomial @pol@.+-- +-- The polynomial is assumed to be squarefree.+foreign import ccall "fmpz_poly.h fmpz_poly_num_real_roots"+ fmpz_poly_num_real_roots :: Ptr CFmpzPoly -> IO CLong++-- Minimal polynomials ---------------------------------------------------------++-- | /_fmpz_poly_cyclotomic/ /a/ /n/ /factors/ /num_factors/ /phi/ +-- +-- Sets @a@ to the lower half of the cyclotomic polynomial \(\Phi_n(x)\),+-- given \(n \ge 3\) which must be squarefree.+-- +-- A precomputed array containing the prime factors of \(n\) must be+-- provided, as well as the value of the Euler totient function \(\phi(n)\)+-- as @phi@. If \(n\) is even, 2 must be the first factor in the list.+-- +-- The degree of \(\Phi_n(x)\) is exactly \(\phi(n)\). Only the low+-- \((\phi(n) + 1) / 2\) coefficients are written; the high coefficients+-- can be obtained afterwards by copying the low coefficients in reverse+-- order, since \(\Phi_n(x)\) is a palindrome for \(n \ne 1\).+-- +-- We use the sparse power series algorithm described as Algorithm 4+-- < [ArnoldMonagan2011]>. The algorithm is based on the identity+-- +-- \[`\]+-- \[\Phi_n(x) = \prod_{d|n} (x^d - 1)^{\mu(n/d)}.\]+-- +-- Treating the polynomial as a power series, the multiplications and+-- divisions can be done very cheaply using repeated additions and+-- subtractions. The complexity is \(O(2^k \phi(n))\) where \(k\) is the+-- number of prime factors in \(n\).+-- +-- To improve efficiency for small \(n\), we treat the @fmpz@ coefficients+-- as machine integers when there is no risk of overflow. The following+-- bounds are given in Table 6 of < [ArnoldMonagan2011]>:+-- +-- For \(n < 10163195\), the largest coefficient in any \(\Phi_n(x)\) has+-- 27 bits, so machine arithmetic is safe on 32 bits.+-- +-- For \(n < 169828113\), the largest coefficient in any \(\Phi_n(x)\) has+-- 60 bits, so machine arithmetic is safe on 64 bits.+-- +-- Further, the coefficients are always \(\pm 1\) or 0 if there are exactly+-- two prime factors, so in this case machine arithmetic can be used as+-- well.+-- +-- Finally, we handle two special cases: if there is exactly one prime+-- factor \(n = p\), then \(\Phi_n(x) = 1 + x + x^2 + \ldots + x^{n-1}\),+-- and if \(n = 2m\), we use \(\Phi_n(x) = \Phi_m(-x)\) to fall back to the+-- case when \(n\) is odd.+foreign import ccall "fmpz_poly.h _fmpz_poly_cyclotomic"+ _fmpz_poly_cyclotomic :: Ptr CFmpz -> CULong -> Ptr CMp -> CLong -> CULong -> IO ()++-- | /fmpz_poly_cyclotomic/ /poly/ /n/ +-- +-- Sets @poly@ to the \(n\)-th cyclotomic polynomial, defined as+-- \(\Phi_n(x) = \prod_{\omega} (x-\omega)\) where \(\omega\) runs over all+-- the \(n\)-th primitive roots of unity.+-- +-- We factor \(n\) into \(n = qs\) where \(q\) is squarefree, and compute+-- \(\Phi_q(x)\). Then \(\Phi_n(x) = \Phi_q(x^s)\).+foreign import ccall "fmpz_poly.h fmpz_poly_cyclotomic"+ fmpz_poly_cyclotomic :: Ptr CFmpzPoly -> CULong -> IO ()++-- | /_fmpz_poly_is_cyclotomic/ /poly/ /len/ +-- +-- If @poly@ is a cyclotomic polynomial, returns the index \(n\) of this+-- cyclotomic polynomial. If @poly@ is not a cyclotomic polynomial, returns+-- 0.+foreign import ccall "fmpz_poly.h _fmpz_poly_is_cyclotomic"+ _fmpz_poly_is_cyclotomic :: Ptr CFmpz -> CLong -> IO CULong++-- | /_fmpz_poly_cos_minpoly/ /coeffs/ /n/ +-- +-- Sets @poly@ to the minimal polynomial of \(2 \cos(2 \pi / n)\). For+-- suitable choice of \(n\), this gives the minimal polynomial of+-- \(2 \cos(a \pi)\) or \(2 \sin(a \pi)\) for any rational \(a\).+-- +-- The cosine is multiplied by a factor two since this gives a monic+-- polynomial with integer coefficients. One can obtain the minimal+-- polynomial for \(\cos(2 \pi / n)\) by making the substitution+-- \(x \to x / 2\).+-- +-- For \(n > 2\), the degree of the polynomial is \(\varphi(n) / 2\). For+-- \(n = 1, 2\), the degree is 1. For \(n = 0\), we define the output to be+-- the constant polynomial 1.+foreign import ccall "fmpz_poly.h _fmpz_poly_cos_minpoly"+ _fmpz_poly_cos_minpoly :: Ptr CFmpz -> CULong -> IO ()++-- | /_fmpz_poly_swinnerton_dyer/ /coeffs/ /n/ +-- +-- Sets @poly@ to the Swinnerton-Dyer polynomial \(S_n\), defined as the+-- integer polynomial+-- \(S_n = \prod (x \pm \sqrt{2} \pm \sqrt{3} \pm \sqrt{5} \pm \ldots \pm \sqrt{p_n})\)+-- where \(p_n\) denotes the \(n\)-th prime number and all combinations of+-- signs are taken. This polynomial has degree \(2^n\) and is irreducible+-- over the integers (it is the minimal polynomial of+-- \(\sqrt{2} + \ldots + \sqrt{p_n}\)).+foreign import ccall "fmpz_poly.h _fmpz_poly_swinnerton_dyer"+ _fmpz_poly_swinnerton_dyer :: Ptr CFmpz -> CULong -> IO ()++-- Orthogonal polynomials ------------------------------------------------------++-- | /_fmpz_poly_chebyshev_t/ /coeffs/ /n/ +-- +-- Sets @poly@ to the Chebyshev polynomial of the first kind \(T_n(x)\),+-- defined by \(T_n(x) = \cos(n \cos^{-1}(x))\), for \(n\ge0\). The+-- coefficients are calculated using a hypergeometric recurrence.+foreign import ccall "fmpz_poly.h _fmpz_poly_chebyshev_t"+ _fmpz_poly_chebyshev_t :: Ptr CFmpz -> CULong -> IO ()++-- | /_fmpz_poly_chebyshev_u/ /coeffs/ /n/ +-- +-- Sets @poly@ to the Chebyshev polynomial of the first kind \(U_n(x)\),+-- defined by \((n+1) U_n(x) = T'_{n+1}(x)\), for \(n\ge0\). The+-- coefficients are calculated using a hypergeometric recurrence.+foreign import ccall "fmpz_poly.h _fmpz_poly_chebyshev_u"+ _fmpz_poly_chebyshev_u :: Ptr CFmpz -> CULong -> IO ()++-- | /_fmpz_poly_legendre_pt/ /coeffs/ /n/ +-- +-- Sets @coeffs@ to the coefficient array of the shifted Legendre+-- polynomial \(\tilde{P_n}(x)\), defined by+-- \(\tilde{P_n}(x) = P_n(2x-1)\), for \(n\ge0\). The coefficients are+-- calculated using a hypergeometric recurrence. The length of the array+-- will be @n+1@. See @fmpq_poly@ for the Legendre polynomials.+foreign import ccall "fmpz_poly.h _fmpz_poly_legendre_pt"+ _fmpz_poly_legendre_pt :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_poly_legendre_pt/ /poly/ /n/ +-- +-- Sets @poly@ to the shifted Legendre polynomial \(\tilde{P_n}(x)\),+-- defined by \(\tilde{P_n}(x) = P_n(2x-1)\), for \(n\ge0\). The+-- coefficients are calculated using a hypergeometric recurrence. See+-- @fmpq_poly@ for the Legendre polynomials.+foreign import ccall "fmpz_poly.h fmpz_poly_legendre_pt"+ fmpz_poly_legendre_pt :: Ptr CFmpzPoly -> CULong -> IO ()++-- | /_fmpz_poly_hermite_h/ /coeffs/ /n/ +-- +-- Sets @coeffs@ to the coefficient array of the Hermite polynomial+-- \(H_n(x)\), defined by \(H'_n(x) = 2nH_{n-1}(x)\), for \(n\ge0\). The+-- coefficients are calculated using a hypergeometric recurrence. The+-- length of the array will be @n+1@.+foreign import ccall "fmpz_poly.h _fmpz_poly_hermite_h"+ _fmpz_poly_hermite_h :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_poly_hermite_h/ /poly/ /n/ +-- +-- Sets @poly@ to the Hermite polynomial \(H_n(x)\), defined by+-- \(H'_n(x) = 2nH_{n-1}(x)\), for \(n\ge0\). The coefficients are+-- calculated using a hypergeometric recurrence.+foreign import ccall "fmpz_poly.h fmpz_poly_hermite_h"+ fmpz_poly_hermite_h :: Ptr CFmpzPoly -> CULong -> IO ()++-- | /_fmpz_poly_hermite_he/ /coeffs/ /n/ +-- +-- Sets @coeffs@ to the coefficient array of the Hermite polynomial+-- \(He_n(x)\), defined by+-- \(He_n(x) = 2^{-\tfrac{n}{2}}H_n\left(\frac{x}{\sqrt2}\right)\), for+-- \(n\ge0\). The coefficients are calculated using a hypergeometric+-- recurrence. The length of the array will be @n+1@.+foreign import ccall "fmpz_poly.h _fmpz_poly_hermite_he"+ _fmpz_poly_hermite_he :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_poly_hermite_he/ /poly/ /n/ +-- +-- Sets @poly@ to the Hermite polynomial \(He_n(x)\), defined by+-- \(He_n(x) = 2^{-\tfrac{n}{2}}H_n\left(\frac{x}{\sqrt2}\right)\), for+-- \(n\ge0\). The coefficients are calculated using a hypergeometric+-- recurrence.+foreign import ccall "fmpz_poly.h fmpz_poly_hermite_he"+ fmpz_poly_hermite_he :: Ptr CFmpzPoly -> CULong -> IO ()++-- Fibonacci polynomials -------------------------------------------------------++-- | /_fmpz_poly_fibonacci/ /coeffs/ /n/ +-- +-- Sets @coeffs@ to the coefficient array of the \(n\)-th Fibonacci+-- polynomial. The coefficients are calculated using a hypergeometric+-- recurrence.+foreign import ccall "fmpz_poly.h _fmpz_poly_fibonacci"+ _fmpz_poly_fibonacci :: Ptr CFmpz -> CULong -> IO ()++-- | /fmpz_poly_fibonacci/ /poly/ /n/ +-- +-- Sets @poly@ to the \(n\)-th Fibonacci polynomial. The coefficients are+-- calculated using a hypergeometric recurrence.+foreign import ccall "fmpz_poly.h fmpz_poly_fibonacci"+ fmpz_poly_fibonacci :: Ptr CFmpzPoly -> CULong -> IO ()++-- THIS DOES NOT SEEM TO EXIST IN THE ACTUAL IMPLEMENTATION --------------------++-- -- Eulerian numbers and polynomials --------------------------------------------++-- -- Eulerian numbers are the coefficients to the Eulerian polynomials+-- --+-- -- \[`\]+-- -- \[A_n(x) = \sum_{m = 0}^{n} A(n, m) x^m,\]+-- --+-- -- where the Eulerian polynomials are defined by the exponential generating+-- -- function+-- --+-- -- \[`\]+-- -- \[\frac{x - 1}{x - e^{(x - 1) t}}+-- -- = \sum_{n = 0}^{\infty} A_n(x) \frac{t^n}{n!}.\]+-- --+-- -- The Eulerian numbers can be expressed explicitly via the formula ..+-- -- math::\` A(n, m) = s< um>{k = 0}^{m + 1} (-1)^k binom{n + 1}{k} (m + 1 -+-- -- k)^n.+-- --+-- -- Note: Not to be confused with Euler numbers and polynomials.+-- --+-- -- | /arith_eulerian_polynomial/ /res/ /n/ +-- -- +-- -- Sets @res@ to the Eulerian polynomial \(A_n(x)\), where we define+-- -- \(A_0(x) = 1\). The polynomial is calculated via a recursive relation.+-- foreign import ccall "fmpz_poly.h arith_eulerian_polynomial"+-- arith_eulerian_polynomial :: Ptr CFmpzPoly -> CULong -> IO ()++-- Modular forms and q-series --------------------------------------------------++-- | /_fmpz_poly_eta_qexp/ /f/ /r/ /len/ +-- +-- Sets \(f\) to the \(q\)-expansion to length \(n\) of the Dedekind eta+-- function (without the leading factor \(q^{1/24}\)) raised to the power+-- \(r\), i.e.+-- \((q^{-1/24} \eta(q))^r = \prod_{k=1}^{\infty} (1 - q^k)^r\).+-- +-- In particular, \(r = -1\) gives the generating function of the partition+-- function \(p(k)\), and \(r = 24\) gives, after multiplication by \(q\),+-- the modular discriminant \(\Delta(q)\) which generates the Ramanujan tau+-- function \(\tau(k)\).+-- +-- This function uses sparse formulas for \(r = 1, 2, 3, 4, 6\) and+-- otherwise reduces to one of those cases using power series arithmetic.+foreign import ccall "fmpz_poly.h _fmpz_poly_eta_qexp"+ _fmpz_poly_eta_qexp :: Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /_fmpz_poly_theta_qexp/ /f/ /r/ /len/ +-- +-- Sets \(f\) to the \(q\)-expansion to length \(n\) of the Jacobi theta+-- function raised to the power \(r\), i.e. \(\vartheta(q)^r\) where+-- \(\vartheta(q) = 1 + 2 \sum_{k=1}^{\infty} q^{k^2}\).+-- +-- This function uses sparse formulas for \(r = 1, 2\) and otherwise+-- reduces to those cases using power series arithmetic.+foreign import ccall "fmpz_poly.h _fmpz_poly_theta_qexp"+ _fmpz_poly_theta_qexp :: Ptr CFmpz -> CLong -> CLong -> IO ()++-- CLD bounds ------------------------------------------------------------------++-- | /fmpz_poly_CLD_bound/ /res/ /f/ /n/ +-- +-- Compute a bound on the \(n\) coefficient of \(fg'/g\) where \(g\) is any+-- factor of \(f\).+foreign import ccall "fmpz_poly.h fmpz_poly_CLD_bound"+ fmpz_poly_CLD_bound :: Ptr CFmpz -> Ptr CFmpzPoly -> CLong -> IO ()
+ src/Data/Number/Flint/Fmpz/Poly/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Poly.Factor (+ module Data.Number.Flint.Fmpz.Poly.Factor.FFI+ ) where++import Data.Number.Flint.Fmpz.Poly.Factor.FFI
+ src/Data/Number/Flint/Fmpz/Poly/Factor/FFI.hsc view
@@ -0,0 +1,247 @@+{-|+module : Data.Number.Flint.Fmpz.Poly.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Poly.Factor.FFI (+ -- * Factorisation of polynomials over the integers+ FmpzPolyFactor (..)+ , CFmpzPolyFactor (..)+ , newFmpzPolyFactor+ , withFmpzPolyFactor+ -- * Types, macros and constants+ -- * Memory management+ , fmpz_poly_factor_init+ , fmpz_poly_factor_init2+ , fmpz_poly_factor_realloc+ , fmpz_poly_factor_fit_length+ , fmpz_poly_factor_clear+ -- * Manipulating factors+ , fmpz_poly_factor_set+ , fmpz_poly_factor_insert+ , fmpz_poly_factor_concat+ -- * Input and output+ , fmpz_poly_factor_print+ -- * Factoring algorithms+ , fmpz_poly_factor_squarefree+ , fmpz_poly_factor_zassenhaus_recombination+ , _fmpz_poly_factor_zassenhaus+ , fmpz_poly_factor_zassenhaus+ , _fmpz_poly_factor_quadratic+ , fmpz_poly_factor+) where ++-- factorisation of polynomials over the integers ------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly++#include <flint/flint.h>++#include <flint/fmpz.h>+#include <flint/fmpz_poly.h>+#include <flint/fmpz_poly_factor.h>++-- fmpz_poly_factor_t ----------------------------------------------------------++-- Note that the structure of CFmpzPolyFactor is different from the+-- corresponding structure in <flint/fmpz_poly_factor.h>. The reason+-- for this is that we can only deal with `Ptr CFmpz` and not with the+-- structure `CFmpz` directly in Haskell. Otherwise we would have to+-- cope with the `fmpz_t` structure either containing an `slong` or+-- `mpz_ptr`.++data FmpzPolyFactor =+ FmpzPolyFactor {-# UNPACK #-} !(ForeignPtr CFmpzPolyFactor)+data CFmpzPolyFactor = CFmpzPolyFactor (Ptr CFmpz) (Ptr CFmpzPoly) (Ptr CLong) CLong CLong ++instance Storable CFmpzPolyFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_poly_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_poly_factor_t}+ peek ptr = CFmpzPolyFactor+ <$> (return $ castPtr ptr)+ <*> #{peek fmpz_poly_factor_struct, p } ptr+ <*> #{peek fmpz_poly_factor_struct, exp } ptr+ <*> #{peek fmpz_poly_factor_struct, num } ptr+ <*> #{peek fmpz_poly_factor_struct, alloc} ptr+ poke = error "CFmpzPolyFactor.poke: Not defined"++newFmpzPolyFactor = do+ p <- mallocForeignPtr+ withForeignPtr p fmpz_poly_factor_init+ addForeignPtrFinalizer p_fmpz_poly_factor_clear p+ return $ FmpzPolyFactor p++{-# INLINE withFmpzPolyFactor #-}+withFmpzPolyFactor (FmpzPolyFactor p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FmpzPolyFactor p,)++withNewFmpzPolyFactor f = do+ x <- newFmpzPolyFactor+ withFmpzPolyFactor x $ \x -> f x+ +-- Memory management -----------------------------------------------------------++-- | /fmpz_poly_factor_init/ /fac/ +-- +-- Initialises a new factor structure.+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_init"+ fmpz_poly_factor_init :: Ptr CFmpzPolyFactor -> IO ()++-- | /fmpz_poly_factor_init2/ /fac/ /alloc/ +-- +-- Initialises a new factor structure, providing space for at least @alloc@+-- factors.+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_init2"+ fmpz_poly_factor_init2 :: Ptr CFmpzPolyFactor -> CLong -> IO ()++-- | /fmpz_poly_factor_realloc/ /fac/ /alloc/ +-- +-- Reallocates the factor structure to provide space for precisely @alloc@+-- factors.+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_realloc"+ fmpz_poly_factor_realloc :: Ptr CFmpzPolyFactor -> CLong -> IO ()++-- | /fmpz_poly_factor_fit_length/ /fac/ /len/ +-- +-- Ensures that the factor structure has space for at least @len@ factors.+-- This functions takes care of the case of repeated calls by always at+-- least doubling the number of factors the structure can hold.+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_fit_length"+ fmpz_poly_factor_fit_length :: Ptr CFmpzPolyFactor -> CLong -> IO ()++-- | /fmpz_poly_factor_clear/ /fac/ +-- +-- Releases all memory occupied by the factor structure.+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_clear"+ fmpz_poly_factor_clear :: Ptr CFmpzPolyFactor -> IO ()++foreign import ccall "fmpz_poly_factor.h &fmpz_poly_factor_clear"+ p_fmpz_poly_factor_clear :: FunPtr (Ptr CFmpzPolyFactor -> IO ())++-- Manipulating factors --------------------------------------------------------++-- | /fmpz_poly_factor_set/ /res/ /fac/ +-- +-- Sets @res@ to the same factorisation as @fac@.+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_set"+ fmpz_poly_factor_set :: Ptr CFmpzPolyFactor -> Ptr CFmpzPolyFactor -> IO ()++-- | /fmpz_poly_factor_insert/ /fac/ /p/ /e/ +-- +-- Adds the primitive polynomial \(p^e\) to the factorisation @fac@.+-- +-- Assumes that \(\deg(p) \geq 2\) and \(e \neq 0\).+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_insert"+ fmpz_poly_factor_insert :: Ptr CFmpzPolyFactor -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_factor_concat/ /res/ /fac/ +-- +-- Concatenates two factorisations.+-- +-- This is equivalent to calling @fmpz_poly_factor_insert@ repeatedly with+-- the individual factors of @fac@.+-- +-- Does not support aliasing between @res@ and @fac@.+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_concat"+ fmpz_poly_factor_concat :: Ptr CFmpzPolyFactor -> Ptr CFmpzPolyFactor -> IO ()++-- Input and output ------------------------------------------------------------++-- | /fmpz_poly_factor_print/ /fac/ +-- +-- Prints the entries of @fac@ to standard output.+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_print"+ fmpz_poly_factor_print :: Ptr CFmpzPolyFactor -> IO ()++-- Factoring algorithms --------------------------------------------------------++-- | /fmpz_poly_factor_squarefree/ /fac/ /F/ +-- +-- Takes as input a polynomial \(F\) and a freshly initialized factor+-- structure @fac@. Updates @fac@ to contain a factorization of \(F\) into+-- (not necessarily irreducible) factors that themselves have no repeated+-- factors. None of the returned factors will have the same exponent. That+-- is we return \(g_i\) and unique \(e_i\) such that+-- +-- \[F = c \prod_{i} g_i^{e_i}\]+-- +-- where \(c\) is the signed content of \(F\) and \(\gcd(g_i, g_i') = 1\).+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_squarefree"+ fmpz_poly_factor_squarefree :: Ptr CFmpzPolyFactor -> Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_factor_zassenhaus_recombination/ /final_fac/ /lifted_fac/ /F/ /P/ /exp/ +-- +-- Takes as input a factor structure @lifted_fac@ containing a squarefree+-- factorization of the polynomial \(F \bmod p\). The algorithm does a+-- brute force search for irreducible factors of \(F\) over the integers,+-- and each factor is raised to the power @exp@.+-- +-- The impact of the algorithm is to augment a factorization of @F^exp@ to+-- the factor structure @final_fac@.+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_zassenhaus_recombination"+ fmpz_poly_factor_zassenhaus_recombination :: Ptr CFmpzPolyFactor -> Ptr CFmpzPolyFactor -> Ptr CFmpzPoly -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_poly_factor_zassenhaus/ /final_fac/ /exp/ /f/ /cutoff/ /use_van_hoeij/ +-- +-- This is the internal wrapper of Zassenhaus.+-- +-- It will attempt to find a small prime such that \(f\) modulo \(p\) has a+-- minimal number of factors. If it cannot find a prime giving less than+-- @cutoff@ factors it aborts. Then it decides a \(p\)-adic precision to+-- lift the factors to, hensel lifts, and finally calls Zassenhaus+-- recombination.+-- +-- Assumes that \(\operatorname{len}(f) \geq 2\).+-- +-- Assumes that \(f\) is primitive.+-- +-- Assumes that the constant coefficient of \(f\) is non-zero. Note that+-- this can be easily achieved by taking out factors of the form \(x^k\)+-- before calling this routine.+-- +-- If the final flag is set, the function will use the van Hoeij+-- factorisation algorithm with gradual feeding and mod \(2^k\) data+-- truncation to find factors when the number of local factors is large.+foreign import ccall "fmpz_poly_factor.h _fmpz_poly_factor_zassenhaus"+ _fmpz_poly_factor_zassenhaus :: Ptr CFmpzPolyFactor -> CLong -> Ptr CFmpzPoly -> CLong -> CInt -> IO ()++-- | /fmpz_poly_factor_zassenhaus/ /final_fac/ /F/ +-- +-- A wrapper of the Zassenhaus factoring algorithm, which takes as input+-- any polynomial \(F\), and stores a factorization in @final_fac@.+-- +-- The complexity will be exponential in the number of local factors we+-- find for the components of a squarefree factorization of \(F\).+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor_zassenhaus"+ fmpz_poly_factor_zassenhaus :: Ptr CFmpzPolyFactor -> Ptr CFmpzPoly -> IO ()++-- | /_fmpz_poly_factor_quadratic/ /fac/ /f/ /exp/ +-- +-- Inserts the factorisation of the quadratic (resp. cubic) polynomial /f/+-- into /fac/ with multiplicity /exp/. This function requires that the+-- content of /f/ has been removed, and does not update the content of+-- /fac/. The factorzation is calculated over \(\mathbb{R}\) or+-- \(\mathbb{Q}_2\) and then tested over \(\mathbb{Z}\).+foreign import ccall "fmpz_poly_factor.h _fmpz_poly_factor_quadratic"+ _fmpz_poly_factor_quadratic :: Ptr CFmpzPolyFactor -> Ptr CFmpzPoly -> CLong -> IO ()++-- | /fmpz_poly_factor/ /final_fac/ /F/ +-- +-- A wrapper of the Zassenhaus and van Hoeij factoring algorithms, which+-- takes as input any polynomial \(F\), and stores a factorization in+-- @final_fac@.+foreign import ccall "fmpz_poly_factor.h fmpz_poly_factor"+ fmpz_poly_factor :: Ptr CFmpzPolyFactor -> Ptr CFmpzPoly -> IO ()+
+ src/Data/Number/Flint/Fmpz/Poly/Instances.hs view
@@ -0,0 +1,167 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+{-|+module : Data.Number.Flint.Fmpz.Poly.Instances+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Poly.Instances (+ FmpzPoly (..)+ , module GHC.Exts+ , hermitePolynomial+ , cyclotomicPolynomial+) where++import Test.QuickCheck++import GHC.Exts++import System.IO.Unsafe+import Control.Monad++import Foreign.Ptr+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Alloc (free)+import Foreign.Marshal.Array (advancePtr)++import Data.Bits++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Instances+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Poly.Factor++import Data.Number.Flint.UFD++instance Show FmpzPoly where+ show p = snd $ unsafePerformIO $ do+ withFmpzPoly p $ \p -> do+ withCString "x" $ \x -> do+ cs <- fmpz_poly_get_str_pretty p x+ s <- peekCString cs+ free cs+ return s++instance Num FmpzPoly where+ (*) = lift2 fmpz_poly_mul+ (+) = lift2 fmpz_poly_add+ (-) = lift2 fmpz_poly_sub+ abs = undefined+ signum = undefined+ fromInteger x = unsafePerformIO $ do+ let tmp = fromInteger x :: Fmpz+ result <- newFmpzPoly+ withFmpzPoly result $ \result -> + withFmpz tmp $ \tmp -> do+ fmpz_poly_set_fmpz result tmp+ return result+ return result++instance Semigroup FmpzPoly where+ (<>) = lift2 fmpz_poly_compose++instance Eq FmpzPoly where+ (==) x y = snd $ snd $ unsafePerformIO $ do+ withFmpzPoly x $ \x ->+ withFmpzPoly y $ \y -> do+ f <- fmpz_poly_equal x y+ return $ f == 1++instance Ord FmpzPoly where+ compare = undefined+ +instance Real FmpzPoly where+ toRational = undefined++instance Enum FmpzPoly where+ toEnum = undefined+ fromEnum = undefined+ +instance Integral FmpzPoly where+ toInteger = undefined+ div x y = unsafePerformIO $ do+ p <- newFmpzPoly+ q <- newFmpzPoly+ withFmpzPoly x $ \x ->+ withFmpzPoly y $ \y ->+ withFmpzPoly q $ \q ->+ fmpz_poly_div q x y+ return q+ quotRem x y = unsafePerformIO $ do+ p <- newFmpzPoly+ q <- newFmpzPoly+ withFmpzPoly x $ \x ->+ withFmpzPoly y $ \y ->+ withFmpzPoly p $ \p ->+ withFmpzPoly q $ \q ->+ fmpz_poly_divrem p q x y+ return (p, q)++instance UFD FmpzPoly where+ factor x = snd $ snd $ unsafePerformIO $ do+ withFmpzPoly x $ \x -> do+ f <- newFmpzPolyFactor+ withFmpzPolyFactor f $ \f -> do+ fmpz_poly_factor f x+ CFmpzPolyFactor c d e n alloc <- peek f+ prefactor <- newFmpz+ withFmpz prefactor $ \prefactor -> fmpz_set prefactor c + let pre = (fromList [prefactor] :: FmpzPoly, 1)+ fac <- forM [0..fromIntegral n-1] $ \j -> do+ m <- peek (e `advancePtr` j)+ r <- newFmpzPoly+ withFmpzPoly r $ \r -> fmpz_poly_set r (d `advancePtr` j)+ return (r, fromIntegral m)+ return $ if prefactor == 1 then fac else pre : fac+ +instance Arbitrary FmpzPoly where+ arbitrary = do+ c <- listOf arbitrary+ return $ fromList (c ++ [1])++instance IsList FmpzPoly where+ type Item FmpzPoly = Fmpz+ fromList c = unsafePerformIO $ do+ p <- newFmpzPoly+ withFmpzPoly p $ \p -> + forM_ [0..length c-1] $ \j ->+ withFmpz (c!!j) $ \a -> + fmpz_poly_set_coeff_fmpz p (fromIntegral j) a+ return p+ toList p = snd $ unsafePerformIO $ + withFmpzPoly p $ \p -> do+ d <- fmpz_poly_degree p+ forM [0..d] $ \j -> do+ c <- newFmpz+ withFmpz c $ \c -> fmpz_poly_get_coeff_fmpz c p j+ return c++lift2 f x y = unsafePerformIO $ do+ result <- newFmpzPoly+ withFmpzPoly result $ \result -> do+ withFmpzPoly x $ \x -> do+ withFmpzPoly y $ \y -> do+ f result x y+ return result++lift1 f x = unsafePerformIO $ do+ result <- newFmpzPoly+ withFmpzPoly result $ \result ->+ withFmpzPoly x $ \x ->+ f result x+ return result++-- special functions -----------------------------------------------------------++cyclotomicPolynomial n = unsafePerformIO $ do+ poly <- newFmpzPoly+ withFmpzPoly poly $ \poly ->+ fmpz_poly_cyclotomic poly n+ return poly+ +hermitePolynomial n = unsafePerformIO $ do+ poly <- newFmpzPoly+ withFmpzPoly poly $ \poly ->+ fmpz_poly_hermite_h poly n+ return poly
+ src/Data/Number/Flint/Fmpz/Poly/Mat.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Poly.Mat (+ module Data.Number.Flint.Fmpz.Poly.Mat.FFI+ ) where++import Data.Number.Flint.Fmpz.Poly.Mat.FFI
+ src/Data/Number/Flint/Fmpz/Poly/Mat/FFI.hsc view
@@ -0,0 +1,642 @@+{-|+module : Data.Number.Flint.Fmpz.Poly.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Poly.Mat.FFI (+ -- * Matrices of polynomials over the integers+ FmpzPolyMat (..)+ , CFmpzPolyMat (..)+ , newFmpzPolyMat+ , withFmpzPolyMat+ , withNewFmpzPolyMat+ -- * Memory management+ , fmpz_poly_mat_init+ , fmpz_poly_mat_init_set+ , fmpz_poly_mat_clear+ -- * Basic properties+ , fmpz_poly_mat_nrows+ , fmpz_poly_mat_ncols+ -- * Basic assignment and manipulation+ , fmpz_poly_mat_entry+ , fmpz_poly_mat_set+ , fmpz_poly_mat_swap+ , fmpz_poly_mat_swap_entrywise+ -- * Input and output+ , fmpz_poly_mat_print+ -- * Random matrix generation+ , fmpz_poly_mat_randtest+ , fmpz_poly_mat_randtest_unsigned+ , fmpz_poly_mat_randtest_sparse+ -- * Special matrices+ , fmpz_poly_mat_zero+ , fmpz_poly_mat_one+ -- * Basic comparison and properties+ , fmpz_poly_mat_equal+ , fmpz_poly_mat_is_zero+ , fmpz_poly_mat_is_one+ , fmpz_poly_mat_is_empty+ , fmpz_poly_mat_is_square+ -- * Norms+ , fmpz_poly_mat_max_bits+ , fmpz_poly_mat_max_length+ -- * Transpose+ , fmpz_poly_mat_transpose+ -- * Evaluation+ , fmpz_poly_mat_evaluate_fmpz+ -- * Arithmetic+ , fmpz_poly_mat_scalar_mul_fmpz_poly+ , fmpz_poly_mat_scalar_mul_fmpz+ , fmpz_poly_mat_add+ , fmpz_poly_mat_sub+ , fmpz_poly_mat_neg+ , fmpz_poly_mat_mul+ , fmpz_poly_mat_mul_classical+ , fmpz_poly_mat_mul_KS+ , fmpz_poly_mat_mullow+ , fmpz_poly_mat_sqr+ , fmpz_poly_mat_sqr_classical+ , fmpz_poly_mat_sqr_KS+ , fmpz_poly_mat_sqrlow+ , fmpz_poly_mat_pow+ , fmpz_poly_mat_pow_trunc+ , fmpz_poly_mat_prod+ -- * Row reduction+ , fmpz_poly_mat_find_pivot_any+ , fmpz_poly_mat_find_pivot_partial+ , fmpz_poly_mat_fflu+ , fmpz_poly_mat_rref+ -- * Trace+ , fmpz_poly_mat_trace+ -- * Determinant and rank+ , fmpz_poly_mat_det+ , fmpz_poly_mat_det_fflu+ , fmpz_poly_mat_det_interpolate+ , fmpz_poly_mat_rank+ -- * Inverse+ , fmpz_poly_mat_inv+ -- * Nullspace+ , fmpz_poly_mat_nullspace+ -- * Solving+ , fmpz_poly_mat_solve+ , fmpz_poly_mat_solve_fflu+ , fmpz_poly_mat_solve_fflu_precomp+) where++-- Matrices of polynomials over the integers -----------------------------------++import System.IO.Unsafe++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpq+import Data.Number.Flint.NMod.Types+import Data.Number.Flint.Support.D.Mat+import Data.Number.Flint.Support.Mpf.Mat++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_mat.h>+#include <flint/fmpz_poly.h>+#include <flint/fmpz_poly_mat.h>+#include <flint/fmpq.h>++-- fmpz_poly_mat_t -------------------------------------------------------------++data FmpzPolyMat = FmpzPolyMat {-# UNPACK #-} !(ForeignPtr CFmpzPolyMat) +data CFmpzPolyMat = CFmpzPolyMat (Ptr CFmpzPoly) CLong CLong (Ptr (Ptr CFmpzPoly)) ++instance Storable CFmpzPolyMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpz_poly_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpz_poly_mat_t}+ peek ptr = CFmpzPolyMat+ <$> #{peek fmpz_poly_mat_struct, entries} ptr+ <*> #{peek fmpz_poly_mat_struct, r } ptr+ <*> #{peek fmpz_poly_mat_struct, c } ptr+ <*> #{peek fmpz_poly_mat_struct, rows } ptr+ poke = error "CFmpzPolyMat.poke: Not defined."+ +newFmpzPolyMat rows cols = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> fmpz_poly_mat_init x rows cols+ addForeignPtrFinalizer p_fmpz_poly_mat_clear x+ return $ FmpzPolyMat x++{-# INLINE withFmpzPolyMat #-}+withFmpzPolyMat (FmpzPolyMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FmpzPolyMat x,)++{-# INLINE withNewFmpzPolyMat #-}+withNewFmpzPolyMat rows cols f = do+ x <- newFmpzPolyMat rows cols+ withFmpzPolyMat x f+ +-- Memory management -----------------------------------------------------------++-- | /fmpz_poly_mat_init/ /mat/ /rows/ /cols/ +--+-- Initialises a matrix with the given number of rows and columns for use.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_init"+ fmpz_poly_mat_init :: Ptr CFmpzPolyMat -> CLong -> CLong -> IO ()++-- | /fmpz_poly_mat_init_set/ /mat/ /src/ +--+-- Initialises a matrix @mat@ of the same dimensions as @src@, and sets it+-- to a copy of @src@.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_init_set"+ fmpz_poly_mat_init_set :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_clear/ /mat/ +--+-- Frees all memory associated with the matrix. The matrix must be+-- reinitialised if it is to be used again.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_clear"+ fmpz_poly_mat_clear :: Ptr CFmpzPolyMat -> IO ()++foreign import ccall "fmpz_poly_mat.h &fmpz_poly_mat_clear"+ p_fmpz_poly_mat_clear :: FunPtr (Ptr CFmpzPolyMat -> IO ())++-- Basic properties ------------------------------------------------------------++-- | /fmpz_poly_mat_nrows/ /mat/ +--+-- Returns the number of rows in @mat@.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_nrows"+ fmpz_poly_mat_nrows :: Ptr CFmpzPolyMat -> IO CLong++-- | /fmpz_poly_mat_ncols/ /mat/ +--+-- Returns the number of columns in @mat@.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_ncols"+ fmpz_poly_mat_ncols :: Ptr CFmpzPolyMat -> IO CLong++-- Basic assignment and manipulation -------------------------------------------++-- | /fmpz_poly_mat_entry/ /mat/ /i/ /j/ +--+-- Gives a reference to the entry at row @i@ and column @j@. The reference+-- can be passed as an input or output variable to any @fmpz_poly@ function+-- for direct manipulation of the matrix element. No bounds checking is+-- performed.+fmpz_poly_mat_entry :: Ptr CFmpzPolyMat -> CLong -> CLong -> IO (Ptr CFmpzPoly)+fmpz_poly_mat_entry mat i j = do+ CFmpzPolyMat entries r c rows <- peek mat+ return $ entries `advancePtr` (fromIntegral (i*c+j))+ +-- | /fmpz_poly_mat_set/ /mat1/ /mat2/ +--+-- Sets @mat1@ to a copy of @mat2@.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_set"+ fmpz_poly_mat_set :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_swap/ /mat1/ /mat2/ +--+-- Swaps @mat1@ and @mat2@ efficiently.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_swap"+ fmpz_poly_mat_swap :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_swap_entrywise/ /mat1/ /mat2/ +--+-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_swap_entrywise"+ fmpz_poly_mat_swap_entrywise :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- Input and output ------------------------------------------------------------++foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_fprint"+ fmpz_poly_mat_fprint :: Ptr CFile -> Ptr CFmpzPolyMat -> CString -> IO ()++foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_get_str"+ fmpz_poly_mat_get_str :: Ptr CFmpzPolyMat -> CString -> IO CString+ +-- | /fmpz_poly_mat_print/ /mat/ /x/ +--+-- Prints the matrix @mat@ to standard output, using the variable @x@.+fmpz_poly_mat_print :: Ptr CFmpzPolyMat -> CString -> IO ()+fmpz_poly_mat_print mat x = do+ printCStr (\mat -> fmpz_poly_mat_get_str mat x) mat+ return ()++-- Random matrix generation ----------------------------------------------------++-- | /fmpz_poly_mat_randtest/ /mat/ /state/ /len/ /bits/ +--+-- This is equivalent to applying @fmpz_poly_randtest@ to all entries in+-- the matrix.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_randtest"+ fmpz_poly_mat_randtest :: Ptr CFmpzPolyMat -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- | /fmpz_poly_mat_randtest_unsigned/ /mat/ /state/ /len/ /bits/ +--+-- This is equivalent to applying @fmpz_poly_randtest_unsigned@ to all+-- entries in the matrix.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_randtest_unsigned"+ fmpz_poly_mat_randtest_unsigned :: Ptr CFmpzPolyMat -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- | /fmpz_poly_mat_randtest_sparse/ /A/ /state/ /len/ /bits/ /density/ +--+-- Creates a random matrix with the amount of nonzero entries given+-- approximately by the @density@ variable, which should be a fraction+-- between 0 (most sparse) and 1 (most dense).+-- +-- The nonzero entries will have random lengths between 1 and @len@.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_randtest_sparse"+ fmpz_poly_mat_randtest_sparse :: Ptr CFmpzPolyMat -> Ptr CFRandState -> CLong -> CFBitCnt -> CFloat -> IO ()++-- Special matrices ------------------------------------------------------------++-- | /fmpz_poly_mat_zero/ /mat/ +--+-- Sets @mat@ to the zero matrix.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_zero"+ fmpz_poly_mat_zero :: Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_one/ /mat/ +--+-- Sets @mat@ to the unit or identity matrix of given shape, having the+-- element 1 on the main diagonal and zeros elsewhere. If @mat@ is+-- nonsquare, it is set to the truncation of a unit matrix.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_one"+ fmpz_poly_mat_one :: Ptr CFmpzPolyMat -> IO ()++-- Basic comparison and properties ---------------------------------------------++-- | /fmpz_poly_mat_equal/ /mat1/ /mat2/ +--+-- Returns nonzero if @mat1@ and @mat2@ have the same shape and all their+-- entries agree, and returns zero otherwise.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_equal"+ fmpz_poly_mat_equal :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO CInt++-- | /fmpz_poly_mat_is_zero/ /mat/ +--+-- Returns nonzero if all entries in @mat@ are zero, and returns zero+-- otherwise.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_is_zero"+ fmpz_poly_mat_is_zero :: Ptr CFmpzPolyMat -> IO CInt++-- | /fmpz_poly_mat_is_one/ /mat/ +--+-- Returns nonzero if all entries of @mat@ on the main diagonal are the+-- constant polynomial 1 and all remaining entries are zero, and returns+-- zero otherwise. The matrix need not be square.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_is_one"+ fmpz_poly_mat_is_one :: Ptr CFmpzPolyMat -> IO CInt++-- | /fmpz_poly_mat_is_empty/ /mat/ +--+-- Returns a non-zero value if the number of rows or the number of columns+-- in @mat@ is zero, and otherwise returns zero.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_is_empty"+ fmpz_poly_mat_is_empty :: Ptr CFmpzPolyMat -> IO CInt++-- | /fmpz_poly_mat_is_square/ /mat/ +--+-- Returns a non-zero value if the number of rows is equal to the number of+-- columns in @mat@, and otherwise returns zero.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_is_square"+ fmpz_poly_mat_is_square :: Ptr CFmpzPolyMat -> IO CInt++-- Norms -----------------------------------------------------------------------++-- | /fmpz_poly_mat_max_bits/ /A/ +--+-- Returns the maximum number of bits among the coefficients of the entries+-- in @A@, or the negative of that value if any coefficient is negative.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_max_bits"+ fmpz_poly_mat_max_bits :: Ptr CFmpzPolyMat -> IO CLong++-- | /fmpz_poly_mat_max_length/ /A/ +--+-- Returns the maximum polynomial length among all the entries in @A@.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_max_length"+ fmpz_poly_mat_max_length :: Ptr CFmpzPolyMat -> IO CLong++-- Transpose -------------------------------------------------------------------++-- | /fmpz_poly_mat_transpose/ /B/ /A/ +--+-- Sets \(B\) to \(A^t\).+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_transpose"+ fmpz_poly_mat_transpose :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- Evaluation ------------------------------------------------------------------++-- | /fmpz_poly_mat_evaluate_fmpz/ /B/ /A/ /x/ +--+-- Sets the @fmpz_mat_t@ @B@ to @A@ evaluated entrywise at the point @x@.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_evaluate_fmpz"+ fmpz_poly_mat_evaluate_fmpz :: Ptr CFmpzMat -> Ptr CFmpzPolyMat -> Ptr CFmpz -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- | /fmpz_poly_mat_scalar_mul_fmpz_poly/ /B/ /A/ /c/ +--+-- Sets @B@ to @A@ multiplied entrywise by the polynomial @c@.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_scalar_mul_fmpz_poly"+ fmpz_poly_mat_scalar_mul_fmpz_poly :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> Ptr CFmpzPoly -> IO ()++-- | /fmpz_poly_mat_scalar_mul_fmpz/ /B/ /A/ /c/ +--+-- Sets @B@ to @A@ multiplied entrywise by the integer @c@.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_scalar_mul_fmpz"+ fmpz_poly_mat_scalar_mul_fmpz :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_mat_add/ /C/ /A/ /B/ +--+-- Sets @C@ to the sum of @A@ and @B@. All matrices must have the same+-- shape. Aliasing is allowed.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_add"+ fmpz_poly_mat_add :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_sub/ /C/ /A/ /B/ +--+-- Sets @C@ to the sum of @A@ and @B@. All matrices must have the same+-- shape. Aliasing is allowed.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_sub"+ fmpz_poly_mat_sub :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_neg/ /B/ /A/ +--+-- Sets @B@ to the negation of @A@. The matrices must have the same shape.+-- Aliasing is allowed.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_neg"+ fmpz_poly_mat_neg :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_mul/ /C/ /A/ /B/ +--+-- Sets @C@ to the matrix product of @A@ and @B@. The matrices must have+-- compatible dimensions for matrix multiplication. Aliasing is allowed.+-- This function automatically chooses between classical and KS+-- multiplication.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_mul"+ fmpz_poly_mat_mul :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_mul_classical/ /C/ /A/ /B/ +--+-- Sets @C@ to the matrix product of @A@ and @B@, computed using the+-- classical algorithm. The matrices must have compatible dimensions for+-- matrix multiplication. Aliasing is allowed.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_mul_classical"+ fmpz_poly_mat_mul_classical :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_mul_KS/ /C/ /A/ /B/ +--+-- Sets @C@ to the matrix product of @A@ and @B@, computed using Kronecker+-- segmentation. The matrices must have compatible dimensions for matrix+-- multiplication. Aliasing is allowed.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_mul_KS"+ fmpz_poly_mat_mul_KS :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_mullow/ /C/ /A/ /B/ /len/ +--+-- Sets @C@ to the matrix product of @A@ and @B@, truncating each entry in+-- the result to length @len@. Uses classical matrix multiplication. The+-- matrices must have compatible dimensions for matrix multiplication.+-- Aliasing is allowed.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_mullow"+ fmpz_poly_mat_mullow :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> CLong -> IO ()++-- | /fmpz_poly_mat_sqr/ /B/ /A/ +--+-- Sets @B@ to the square of @A@, which must be a square matrix. Aliasing+-- is allowed. This function automatically chooses between classical and KS+-- squaring.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_sqr"+ fmpz_poly_mat_sqr :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_sqr_classical/ /B/ /A/ +--+-- Sets @B@ to the square of @A@, which must be a square matrix. Aliasing+-- is allowed. This function uses direct formulas for very small matrices,+-- and otherwise classical matrix multiplication.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_sqr_classical"+ fmpz_poly_mat_sqr_classical :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_sqr_KS/ /B/ /A/ +--+-- Sets @B@ to the square of @A@, which must be a square matrix. Aliasing+-- is allowed. This function uses Kronecker segmentation.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_sqr_KS"+ fmpz_poly_mat_sqr_KS :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_sqrlow/ /B/ /A/ /len/ +--+-- Sets @B@ to the square of @A@, which must be a square matrix, truncating+-- all entries to length @len@. Aliasing is allowed. This function uses+-- direct formulas for very small matrices, and otherwise classical matrix+-- multiplication.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_sqrlow"+ fmpz_poly_mat_sqrlow :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> CLong -> IO ()++-- | /fmpz_poly_mat_pow/ /B/ /A/ /exp/ +--+-- Sets @B@ to @A@ raised to the power @exp@, where @A@ is a square matrix.+-- Uses exponentiation by squaring. Aliasing is allowed.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_pow"+ fmpz_poly_mat_pow :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> CULong -> IO ()++-- | /fmpz_poly_mat_pow_trunc/ /B/ /A/ /exp/ /len/ +--+-- Sets @B@ to @A@ raised to the power @exp@, truncating all entries to+-- length @len@, where @A@ is a square matrix. Uses exponentiation by+-- squaring. Aliasing is allowed.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_pow_trunc"+ fmpz_poly_mat_pow_trunc :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> CULong -> CLong -> IO ()++-- | /fmpz_poly_mat_prod/ /res/ /factors/ /n/ +--+-- Sets @res@ to the product of the @n@ matrices given in the vector+-- @factors@, all of which must be square and of the same size. Uses binary+-- splitting.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_prod"+ fmpz_poly_mat_prod :: Ptr CFmpzPolyMat -> Ptr (Ptr CFmpzPolyMat) -> CLong -> IO ()++-- Row reduction ---------------------------------------------------------------++-- | /fmpz_poly_mat_find_pivot_any/ /mat/ /start_row/ /end_row/ /c/ +--+-- Attempts to find a pivot entry for row reduction. Returns a row index+-- \(r\) between @start_row@ (inclusive) and @stop_row@ (exclusive) such+-- that column \(c\) in @mat@ has a nonzero entry on row \(r\), or returns+-- -1 if no such entry exists.+-- +-- This implementation simply chooses the first nonzero entry it+-- encounters. This is likely to be a nearly optimal choice if all entries+-- in the matrix have roughly the same size, but can lead to unnecessary+-- coefficient growth if the entries vary in size.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_find_pivot_any"+ fmpz_poly_mat_find_pivot_any :: Ptr CFmpzPolyMat -> CLong -> CLong -> CLong -> IO CLong++-- | /fmpz_poly_mat_find_pivot_partial/ /mat/ /start_row/ /end_row/ /c/ +--+-- Attempts to find a pivot entry for row reduction. Returns a row index+-- \(r\) between @start_row@ (inclusive) and @stop_row@ (exclusive) such+-- that column \(c\) in @mat@ has a nonzero entry on row \(r\), or returns+-- -1 if no such entry exists.+-- +-- This implementation searches all the rows in the column and chooses the+-- nonzero entry of smallest degree. If there are several entries with the+-- same minimal degree, it chooses the entry with the smallest coefficient+-- bit bound. This heuristic typically reduces coefficient growth when the+-- matrix entries vary in size.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_find_pivot_partial"+ fmpz_poly_mat_find_pivot_partial :: Ptr CFmpzPolyMat -> CLong -> CLong -> CLong -> IO CLong++-- | /fmpz_poly_mat_fflu/ /B/ /den/ /perm/ /A/ /rank_check/ +--+-- Uses fraction-free Gaussian elimination to set (@B@, @den@) to a+-- fraction-free LU decomposition of @A@ and returns the rank of @A@.+-- Aliasing of @A@ and @B@ is allowed.+-- +-- Pivot elements are chosen with @fmpz_poly_mat_find_pivot_partial@. If+-- @perm@ is non-@NULL@, the permutation of rows in the matrix will also be+-- applied to @perm@.+-- +-- If @rank_check@ is set, the function aborts and returns 0 if the matrix+-- is detected not to have full rank without completing the elimination.+-- +-- The denominator @den@ is set to \(\pm \operatorname{det}(A)\), where the+-- sign is decided by the parity of the permutation. Note that the+-- determinant is not generally the minimal denominator.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_fflu"+ fmpz_poly_mat_fflu :: Ptr CFmpzPolyMat -> Ptr CFmpzPoly -> Ptr CLong -> Ptr CFmpzPolyMat -> CInt -> IO CLong++-- | /fmpz_poly_mat_rref/ /B/ /den/ /A/ +--+-- Sets (@B@, @den@) to the reduced row echelon form of @A@ and returns the+-- rank of @A@. Aliasing of @A@ and @B@ is allowed.+-- +-- The denominator @den@ is set to \(\pm \operatorname{det}(A)\). Note that+-- the determinant is not generally the minimal denominator.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_rref"+ fmpz_poly_mat_rref :: Ptr CFmpzPolyMat -> Ptr CFmpzPoly -> Ptr CFmpzPolyMat -> IO CLong++-- Trace -----------------------------------------------------------------------++-- | /fmpz_poly_mat_trace/ /trace/ /mat/ +--+-- Computes the trace of the matrix, i.e. the sum of the entries on the+-- main diagonal. The matrix is required to be square.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_trace"+ fmpz_poly_mat_trace :: Ptr CFmpzPoly -> Ptr CFmpzPolyMat -> IO ()++-- Determinant and rank --------------------------------------------------------++-- | /fmpz_poly_mat_det/ /det/ /A/ +--+-- Sets @det@ to the determinant of the square matrix @A@. Uses a direct+-- formula, fraction-free LU decomposition, or interpolation, depending on+-- the size of the matrix.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_det"+ fmpz_poly_mat_det :: Ptr CFmpzPoly -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_det_fflu/ /det/ /A/ +--+-- Sets @det@ to the determinant of the square matrix @A@. The determinant+-- is computed by performing a fraction-free LU decomposition on a copy of+-- @A@.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_det_fflu"+ fmpz_poly_mat_det_fflu :: Ptr CFmpzPoly -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_det_interpolate/ /det/ /A/ +--+-- Sets @det@ to the determinant of the square matrix @A@. The determinant+-- is computed by determining a bound \(n\) for its length, evaluating the+-- matrix at \(n\) distinct points, computing the determinant of each+-- integer matrix, and forming the interpolating polynomial.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_det_interpolate"+ fmpz_poly_mat_det_interpolate :: Ptr CFmpzPoly -> Ptr CFmpzPolyMat -> IO ()++-- | /fmpz_poly_mat_rank/ /A/ +--+-- Returns the rank of @A@. Performs fraction-free LU decomposition on a+-- copy of @A@.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_rank"+ fmpz_poly_mat_rank :: Ptr CFmpzPolyMat -> IO CLong++-- Inverse ---------------------------------------------------------------------++-- | /fmpz_poly_mat_inv/ /Ainv/ /den/ /A/ +--+-- Sets (@Ainv@, @den@) to the inverse matrix of @A@. Returns 1 if @A@ is+-- nonsingular and 0 if @A@ is singular. Aliasing of @Ainv@ and @A@ is+-- allowed.+-- +-- More precisely, @det@ will be set to the determinant of @A@ and @Ainv@+-- will be set to the adjugate matrix of @A@. Note that the determinant is+-- not necessarily the minimal denominator.+-- +-- Uses fraction-free LU decomposition, followed by solving for the+-- identity matrix.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_inv"+ fmpz_poly_mat_inv :: Ptr CFmpzPolyMat -> Ptr CFmpzPoly -> Ptr CFmpzPolyMat -> IO CInt++-- Nullspace -------------------------------------------------------------------++-- | /fmpz_poly_mat_nullspace/ /res/ /mat/ +--+-- Computes the right rational nullspace of the matrix @mat@ and returns+-- the nullity.+-- +-- More precisely, assume that @mat@ has rank \(r\) and nullity \(n\). Then+-- this function sets the first \(n\) columns of @res@ to linearly+-- independent vectors spanning the nullspace of @mat@. As a result, we+-- always have rank(@res@) \(= n\), and @mat@ \(\times\) @res@ is the zero+-- matrix.+-- +-- The computed basis vectors will not generally be in a reduced form. In+-- general, the polynomials in each column vector in the result will have a+-- nontrivial common GCD.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_nullspace"+ fmpz_poly_mat_nullspace :: Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO CLong++-- Solving ---------------------------------------------------------------------++-- | /fmpz_poly_mat_solve/ /X/ /den/ /A/ /B/ +--+-- Solves the equation \(AX = B\) for nonsingular \(A\). More precisely,+-- computes (@X@, @den@) such that \(AX = B \times \operatorname{den}\).+-- Returns 1 if \(A\) is nonsingular and 0 if \(A\) is singular. The+-- computed denominator will not generally be minimal.+-- +-- Uses fraction-free LU decomposition followed by fraction-free forward+-- and back substitution.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_solve"+ fmpz_poly_mat_solve :: Ptr CFmpzPolyMat -> Ptr CFmpzPoly -> Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO CInt++-- | /fmpz_poly_mat_solve_fflu/ /X/ /den/ /A/ /B/ +--+-- Solves the equation \(AX = B\) for nonsingular \(A\). More precisely,+-- computes (@X@, @den@) such that \(AX = B \times \operatorname{den}\).+-- Returns 1 if \(A\) is nonsingular and 0 if \(A\) is singular. The+-- computed denominator will not generally be minimal.+-- +-- Uses fraction-free LU decomposition followed by fraction-free forward+-- and back substitution.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_solve_fflu"+ fmpz_poly_mat_solve_fflu :: Ptr CFmpzPolyMat -> Ptr CFmpzPoly -> Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO CInt++-- | /fmpz_poly_mat_solve_fflu_precomp/ /X/ /perm/ /FFLU/ /B/ +--+-- Performs fraction-free forward and back substitution given a precomputed+-- fraction-free LU decomposition and corresponding permutation.+foreign import ccall "fmpz_poly_mat.h fmpz_poly_mat_solve_fflu_precomp"+ fmpz_poly_mat_solve_fflu_precomp :: Ptr CFmpzPolyMat -> Ptr CLong -> Ptr CFmpzPolyMat -> Ptr CFmpzPolyMat -> IO ()+
+ src/Data/Number/Flint/Fmpz/Poly/Q.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Poly.Q (+ module Data.Number.Flint.Fmpz.Poly.Q.FFI+ ) where++import Data.Number.Flint.Fmpz.Poly.Q.FFI
+ src/Data/Number/Flint/Fmpz/Poly/Q/FFI.hsc view
@@ -0,0 +1,425 @@+{-|+module : Data.Number.Flint.Fmpz.Poly.Q.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Poly.Q.FFI (+ -- * Rational functions over the rational numbers+ FmpzPolyQ (..)+ , CFmpzPolyQ (..)+ , newFmpzPolyQ+ , withFmpzPolyQ+ , withNewFmpzPolyQ+ , withFmpzPolyQNum+ , withFmpzPolyQDen+ -- * Memory management+ , fmpz_poly_q_init+ , fmpz_poly_q_clear+ -- , fmpz_poly_q_numref+ -- , fmpz_poly_q_denref+ , fmpz_poly_q_canonicalise+ , fmpz_poly_q_is_canonical+ -- * Randomisation+ , fmpz_poly_q_randtest+ , fmpz_poly_q_randtest_not_zero+ -- * Assignment+ , fmpz_poly_q_set+ , fmpz_poly_q_set_si+ , fmpz_poly_q_swap+ , fmpz_poly_q_zero+ , fmpz_poly_q_one+ , fmpz_poly_q_neg+ , fmpz_poly_q_inv+ -- * Comparison+ , fmpz_poly_q_is_zero+ , fmpz_poly_q_is_one+ , fmpz_poly_q_equal+ -- * Addition and subtraction+ , fmpz_poly_q_add+ , fmpz_poly_q_sub+ , fmpz_poly_q_addmul+ , fmpz_poly_q_submul+ -- * Scalar multiplication and division+ , fmpz_poly_q_scalar_mul_si+ , fmpz_poly_q_scalar_mul_fmpz+ , fmpz_poly_q_scalar_mul_fmpq+ , fmpz_poly_q_scalar_div_si+ , fmpz_poly_q_scalar_div_fmpz+ , fmpz_poly_q_scalar_div_fmpq+ -- * Multiplication and division+ , fmpz_poly_q_mul+ , fmpz_poly_q_div+ -- * Powering+ , fmpz_poly_q_pow+ -- * Derivative+ , fmpz_poly_q_derivative+ -- * Evaluation+ , fmpz_poly_q_evaluate_fmpq+ -- * Input and output+ , fmpz_poly_q_set_str+ , fmpz_poly_q_get_str+ , fmpz_poly_q_get_str_pretty+ , fmpz_poly_q_print+ , fmpz_poly_q_print_pretty+) where ++-- Rational functions over the rational numbers --------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fmpq.Poly++#include <flint/fmpz_types.h>++-- fmpz_poly_q_t ---------------------------------------------------------------++data FmpzPolyQ = FmpzPolyQ {-# UNPACK #-} !(ForeignPtr CFmpzPolyQ)+data CFmpzPolyQ = CFmpzPolyQ (Ptr CFmpzPoly) (Ptr CFmpzPoly)++instance Storable CFmpzPolyQ where+ sizeOf _ = #{size fmpz_poly_q_t}+ alignment _ = #{size fmpz_poly_q_t}+ peek ptr = CFmpzPolyQ+ <$> #{peek fmpz_poly_q_struct, num} ptr+ <*> #{peek fmpz_poly_q_struct, den} ptr+ poke ptr (CFmpzPolyQ num den) = do+ #{poke fmpz_poly_q_struct, num} ptr num+ #{poke fmpz_poly_q_struct, den} ptr den++newFmpzPolyQ = do+ x <- mallocForeignPtr+ withForeignPtr x fmpz_poly_q_init+ addForeignPtrFinalizer p_fmpz_poly_q_clear x+ return $ FmpzPolyQ x++withFmpzPolyQ (FmpzPolyQ x) f = do+ withForeignPtr x $ \xp -> (FmpzPolyQ x,) <$> f xp++withNewFmpzPolyQ f = do+ x <- newFmpzPolyQ+ withFmpzPolyQ x f++withFmpzPolyQNum :: FmpzPolyQ -> (Ptr CFmpzPoly -> IO t) -> IO (FmpzPolyQ, t)+withFmpzPolyQNum x f = do+ (_, res) <- withFmpzPolyQ x $ \xp -> do+ CFmpzPolyQ n d <- peek xp+ (x,) <$> f n+ return res+ +withFmpzPolyQDen :: FmpzPolyQ -> (Ptr CFmpzPoly -> IO t) -> IO (FmpzPolyQ, t)+withFmpzPolyQDen x f = do+ (_, res) <- withFmpzPolyQ x $ \xp -> do+ CFmpzPolyQ n d <- peek xp+ (x,) <$> f d+ return res++-- Memory management -----------------------------------------------------------++-- We represent a rational function over \(\mathbf{Q}\) as the quotient of+-- two coprime integer polynomials of type @fmpz_poly_t@, enforcing that+-- the leading coefficient of the denominator is positive. The zero+-- function is represented as \(0/1\).+--+-- | /fmpz_poly_q_init/ /rop/ +--+-- Initialises @rop@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_init"+ fmpz_poly_q_init :: Ptr CFmpzPolyQ -> IO ()++-- | /fmpz_poly_q_clear/ /rop/ +--+-- Clears the object @rop@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_clear"+ fmpz_poly_q_clear :: Ptr CFmpzPolyQ -> IO ()++foreign import ccall "fmpz_poly_q.h &fmpz_poly_q_clear"+ p_fmpz_poly_q_clear :: FunPtr (Ptr CFmpzPolyQ -> IO ())++-- -- | /fmpz_poly_q_numref/ /op/ +-- --+-- -- Returns a reference to the numerator of @op@.+-- foreign import ccall "fmpz_poly_q.h fmpz_poly_q_numref"+-- fmpz_poly_q_numref :: Ptr CFmpzPolyQ -> IO (Ptr CFmpzPoly)++-- -- | /fmpz_poly_q_denref/ /op/ +-- --+-- -- Returns a reference to the denominator of @op@.+-- foreign import ccall "fmpz_poly_q.h fmpz_poly_q_denref"+-- fmpz_poly_q_denref :: Ptr CFmpzPolyQ -> IO (Ptr CFmpzPoly)++-- | /fmpz_poly_q_canonicalise/ /rop/ +--+-- Brings @rop@ into canonical form, only assuming that the denominator is+-- non-zero.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_canonicalise"+ fmpz_poly_q_canonicalise :: Ptr CFmpzPolyQ -> IO ()++-- | /fmpz_poly_q_is_canonical/ /op/ +--+-- Checks whether the rational function @op@ is in canonical form.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_is_canonical"+ fmpz_poly_q_is_canonical :: Ptr CFmpzPolyQ -> IO CInt++-- Randomisation ---------------------------------------------------------------++-- | /fmpz_poly_q_randtest/ /poly/ /state/ /len1/ /bits1/ /len2/ /bits2/ +--+-- Sets @poly@ to a random rational function.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_randtest"+ fmpz_poly_q_randtest :: Ptr CFmpzPolyQ -> Ptr CFRandState -> CLong -> CFBitCnt -> CLong -> CFBitCnt -> IO ()++-- | /fmpz_poly_q_randtest_not_zero/ /poly/ /state/ /len1/ /bits1/ /len2/ /bits2/ +--+-- Sets @poly@ to a random non-zero rational function.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_randtest_not_zero"+ fmpz_poly_q_randtest_not_zero :: Ptr CFmpzPolyQ -> Ptr CFRandState -> CLong -> CFBitCnt -> CLong -> CFBitCnt -> IO ()++-- Assignment ------------------------------------------------------------------++-- | /fmpz_poly_q_set/ /rop/ /op/ +--+-- Sets the element @rop@ to the same value as the element @op@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_set"+ fmpz_poly_q_set :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO ()++-- | /fmpz_poly_q_set_si/ /rop/ /op/ +--+-- Sets the element @rop@ to the value given by the @slong@ @op@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_set_si"+ fmpz_poly_q_set_si :: Ptr CFmpzPolyQ -> CLong -> IO ()++-- | /fmpz_poly_q_swap/ /op1/ /op2/ +--+-- Swaps the elements @op1@ and @op2@.+-- +-- This is done efficiently by swapping pointers.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_swap"+ fmpz_poly_q_swap :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO ()++-- | /fmpz_poly_q_zero/ /rop/ +--+-- Sets @rop@ to zero.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_zero"+ fmpz_poly_q_zero :: Ptr CFmpzPolyQ -> IO ()++-- | /fmpz_poly_q_one/ /rop/ +--+-- Sets @rop@ to one.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_one"+ fmpz_poly_q_one :: Ptr CFmpzPolyQ -> IO ()++-- | /fmpz_poly_q_neg/ /rop/ /op/ +--+-- Sets the element @rop@ to the additive inverse of @op@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_neg"+ fmpz_poly_q_neg :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO ()++-- | /fmpz_poly_q_inv/ /rop/ /op/ +--+-- Sets the element @rop@ to the multiplicative inverse of @op@.+-- +-- Assumes that the element @op@ is non-zero.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_inv"+ fmpz_poly_q_inv :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fmpz_poly_q_is_zero/ /op/ +--+-- Returns whether the element @op@ is zero.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_is_zero"+ fmpz_poly_q_is_zero :: Ptr CFmpzPolyQ -> IO CInt++-- | /fmpz_poly_q_is_one/ /op/ +--+-- Returns whether the element @rop@ is equal to the constant polynomial+-- \(1\).+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_is_one"+ fmpz_poly_q_is_one :: Ptr CFmpzPolyQ -> IO CInt++-- | /fmpz_poly_q_equal/ /op1/ /op2/ +--+-- Returns whether the two elements @op1@ and @op2@ are equal.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_equal"+ fmpz_poly_q_equal :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /fmpz_poly_q_add/ /rop/ /op1/ /op2/ +--+-- Sets @rop@ to the sum of @op1@ and @op2@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_add"+ fmpz_poly_q_add :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO ()++-- | /fmpz_poly_q_sub/ /rop/ /op1/ /op2/ +--+-- Sets @rop@ to the difference of @op1@ and @op2@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_sub"+ fmpz_poly_q_sub :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO ()++-- | /fmpz_poly_q_addmul/ /rop/ /op1/ /op2/ +--+-- Adds the product of @op1@ and @op2@ to @rop@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_addmul"+ fmpz_poly_q_addmul :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO ()++-- | /fmpz_poly_q_submul/ /rop/ /op1/ /op2/ +--+-- Subtracts the product of @op1@ and @op2@ from @rop@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_submul"+ fmpz_poly_q_submul :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO ()++-- Scalar multiplication and division ------------------------------------------++-- | /fmpz_poly_q_scalar_mul_si/ /rop/ /op/ /x/ +--+-- Sets @rop@ to the product of the rational function @op@ and the @slong@+-- integer \(x\).+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_scalar_mul_si"+ fmpz_poly_q_scalar_mul_si :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> CLong -> IO ()++-- | /fmpz_poly_q_scalar_mul_fmpz/ /rop/ /op/ /x/ +--+-- Sets @rop@ to the product of the rational function @op@ and the @fmpz_t@+-- integer \(x\).+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_scalar_mul_fmpz"+ fmpz_poly_q_scalar_mul_fmpz :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_q_scalar_mul_fmpq/ /rop/ /op/ /x/ +--+-- Sets @rop@ to the product of the rational function @op@ and the @fmpq_t@+-- rational \(x\).+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_scalar_mul_fmpq"+ fmpz_poly_q_scalar_mul_fmpq :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> Ptr CFmpq -> IO ()++-- | /fmpz_poly_q_scalar_div_si/ /rop/ /op/ /x/ +--+-- Sets @rop@ to the quotient of the rational function @op@ and the @slong@+-- integer \(x\).+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_scalar_div_si"+ fmpz_poly_q_scalar_div_si :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> CLong -> IO ()++-- | /fmpz_poly_q_scalar_div_fmpz/ /rop/ /op/ /x/ +--+-- Sets @rop@ to the quotient of the rational function @op@ and the+-- @fmpz_t@ integer \(x\).+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_scalar_div_fmpz"+ fmpz_poly_q_scalar_div_fmpz :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> Ptr CFmpz -> IO ()++-- | /fmpz_poly_q_scalar_div_fmpq/ /rop/ /op/ /x/ +--+-- Sets @rop@ to the quotient of the rational function @op@ and the+-- @fmpq_t@ rational \(x\).+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_scalar_div_fmpq"+ fmpz_poly_q_scalar_div_fmpq :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> Ptr CFmpq -> IO ()++-- Multiplication and division -------------------------------------------------++-- | /fmpz_poly_q_mul/ /rop/ /op1/ /op2/ +--+-- Sets @rop@ to the product of @op1@ and @op2@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_mul"+ fmpz_poly_q_mul :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO ()++-- | /fmpz_poly_q_div/ /rop/ /op1/ /op2/ +--+-- Sets @rop@ to the quotient of @op1@ and @op2@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_div"+ fmpz_poly_q_div :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO ()++-- Powering --------------------------------------------------------------------++-- | /fmpz_poly_q_pow/ /rop/ /op/ /exp/ +--+-- Sets @rop@ to the @exp@-th power of @op@.+-- +-- The corner case of @exp == 0@ is handled by setting @rop@ to the+-- constant function \(1\). Note that this includes the case \(0^0 = 1\).+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_pow"+ fmpz_poly_q_pow :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> CULong -> IO ()++-- Derivative ------------------------------------------------------------------++-- | /fmpz_poly_q_derivative/ /rop/ /op/ +--+-- Sets @rop@ to the derivative of @op@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_derivative"+ fmpz_poly_q_derivative :: Ptr CFmpzPolyQ -> Ptr CFmpzPolyQ -> IO ()++-- Evaluation ------------------------------------------------------------------++-- | /fmpz_poly_q_evaluate_fmpq/ /rop/ /f/ /a/ +--+-- Sets @rop@ to \(f\) evaluated at the rational \(a\).+-- +-- If the denominator evaluates to zero at \(a\), returns non-zero and does+-- not modify any of the variables. Otherwise, returns \(0\) and sets @rop@+-- to the rational \(f(a)\).+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_evaluate_fmpq"+ fmpz_poly_q_evaluate_fmpq :: Ptr CFmpq -> Ptr CFmpzPolyQ -> Ptr CFmpq -> IO CInt++-- Input and output ------------------------------------------------------------++-- | /fmpz_poly_q_set_str/ /rop/ /s/+--+-- Sets @rop@ to the rational function given by the string @s@.+-- The following three methods enable users to construct elements of type+-- @fmpz_poly_q_t@ from strings or to obtain string representations of such+-- elements. The format used is based on the FLINT format for integer+-- polynomials of type @fmpz_poly_t@, which we recall first: A non-zero+-- polynomial \(a_0 + a_1 X + \dotsb + a_n X^n\) of length n + 1 is+-- represented by the string @\"n+1 a_0 a_1 ... a_n\"@, where there are+-- two space characters following the length and single space characters+-- separating the individual coefficients. There is no leading or trailing+-- white-space. The zero polynomial is simply represented by @\"0\"@. We+-- adapt this notation for rational functions as follows. We denote the+-- zero function by @\"0\"@. Given a non-zero function with numerator and+-- denominator string representations @num@ and @den@, respectively, we use+-- the string @num\/den@ to represent the rational function, unless the+-- denominator is equal to one, in which case we simply use @num@. There is+-- also a @_pretty@ variant available, which bases the string parts for the+-- numerator and denominator on the output of the function+-- @fmpz_poly_get_str_pretty@ and introduces parentheses where necessary.+-- Note that currently these functions are not optimised for performance+-- and are intended to be used only for debugging purposes or one-off input+-- and output, rather than as a low-level parser.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_set_str"+ fmpz_poly_q_set_str :: Ptr CFmpzPolyQ -> CString -> IO CInt++-- | /fmpz_poly_q_get_str/ /op/ +--+-- Returns the string representation of the rational function @op@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_get_str"+ fmpz_poly_q_get_str :: Ptr CFmpzPolyQ -> IO CString++-- | /fmpz_poly_q_get_str_pretty/ /op/ /x/ +--+-- Returns the pretty string representation of the rational function @op@.+foreign import ccall "fmpz_poly_q.h fmpz_poly_q_get_str_pretty"+ fmpz_poly_q_get_str_pretty :: Ptr CFmpzPolyQ -> CString -> IO CString++-- | /fmpz_poly_q_print/ /op/ +--+-- Prints the representation of the rational function @op@ to @stdout@.+fmpz_poly_q_print :: Ptr CFmpzPolyQ -> IO CInt+fmpz_poly_q_print op = printCStr fmpz_poly_q_get_str op+ ++-- | /fmpz_poly_q_print_pretty/ /op/ /x/ +--+-- Prints the pretty representation of the rational function @op@ to+-- @stdout@.+fmpz_poly_q_print_pretty :: Ptr CFmpzPolyQ -> CString -> IO CInt+fmpz_poly_q_print_pretty op x = + printCStr (`fmpz_poly_q_get_str_pretty` x) op+
+ src/Data/Number/Flint/Fmpz/Poly/Q/Instances.hs view
@@ -0,0 +1,96 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Fmpz.Poly.Q.Instances (+ FmpzPolyQ (..)+) where++import Test.QuickCheck++import GHC.Exts++import System.IO.Unsafe+import Control.Monad++import Foreign.Ptr+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Alloc (free)+import Foreign.Marshal.Array (advancePtr)++import Data.Number.Flint.Quotient+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Instances+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Poly.Factor+import Data.Number.Flint.Fmpz.Poly.Q++instance Show FmpzPolyQ where+ show p = snd $ unsafePerformIO $ do+ withFmpzPolyQ p $ \p -> do+ withCString "x" $ \x -> do+ cs <- fmpz_poly_q_get_str_pretty p x+ s <- peekCString cs+ free cs+ return s++instance Quotient FmpzPolyQ FmpzPoly where+ (//) x y = fst $ unsafePerformIO $ do+ withNewFmpzPolyQ $ \poly -> do+ withFmpzPoly x $ \x -> do+ withFmpzPoly y $ \y -> do+ CFmpzPolyQ p q <- peek poly+ fmpz_poly_set p x+ fmpz_poly_set q y+ numerator q = fst $ unsafePerformIO $ do+ withNewFmpzPoly $ \poly -> do + withFmpzPolyQ q $ \q -> do+ CFmpzPolyQ num _ <- peek q+ fmpz_poly_set poly num+ denominator q = fst $ unsafePerformIO $ do+ withNewFmpzPoly $ \poly -> do + withFmpzPolyQ q $ \q -> do+ CFmpzPolyQ _ den <- peek q+ fmpz_poly_set poly den++instance Num FmpzPolyQ where+ (*) = lift2 fmpz_poly_q_mul+ (+) = lift2 fmpz_poly_q_add+ (-) = lift2 fmpz_poly_q_sub+ abs = undefined+ signum = undefined+ fromInteger x = unsafePerformIO $ do+ result <- newFmpzPolyQ+ withFmpzPolyQ result $ \result -> + fmpz_poly_q_set_si result (fromIntegral x)+ return result++instance Eq FmpzPolyQ where+ (==) x y = snd $ snd $ unsafePerformIO $ do+ withFmpzPolyQ x $ \x ->+ withFmpzPolyQ y $ \y -> do+ f <- fmpz_poly_q_equal x y+ return $ f == 1++instance Ord FmpzPolyQ where+ compare = undefined+ +instance Real FmpzPolyQ where+ toRational = undefined++instance Enum FmpzPolyQ where+ toEnum = undefined+ fromEnum = undefined++lift2 f x y = unsafePerformIO $ do+ result <- newFmpzPolyQ+ withFmpzPolyQ result $ \result -> do+ withFmpzPolyQ x $ \x -> do+ withFmpzPolyQ y $ \y -> do+ f result x y+ return result++lift1 f x = unsafePerformIO $ do+ result <- newFmpzPolyQ+ withFmpzPolyQ result $ \result ->+ withFmpzPolyQ x $ \x ->+ f result x+ return result
+ src/Data/Number/Flint/Fmpz/Vec.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fmpz.Vec (+ module Data.Number.Flint.Fmpz.Vec.FFI+ ) where++import Data.Number.Flint.Fmpz.Vec.FFI
+ src/Data/Number/Flint/Fmpz/Vec/FFI.hsc view
@@ -0,0 +1,609 @@+{-|+module : Data.Number.Flint.Fmpz.Vec.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fmpz.Vec.FFI (+ -- * Vectors of integers+ -- * Memory management+ _fmpz_vec_init+ , _fmpz_vec_clear+ -- * Randomisation+ , _fmpz_vec_randtest+ , _fmpz_vec_randtest_unsigned+ -- * Bit sizes and norms+ , _fmpz_vec_max_bits+ , _fmpz_vec_max_bits_ref+ , _fmpz_vec_sum_max_bits+ , _fmpz_vec_max_limbs+ , _fmpz_vec_height+ , _fmpz_vec_height_index+ -- * Input and output+ , _fmpz_vec_fread+ , _fmpz_vec_read+ , _fmpz_vec_fprint+ , _fmpz_vec_print+ , _fmpz_vec_get_str+ -- * Conversions+ , _fmpz_vec_get_nmod_vec+ , _fmpz_vec_set_nmod_vec+ , _fmpz_vec_get_fft+ , _fmpz_vec_set_fft+ , _fmpz_vec_get_d_vec_2exp+ -- , _fmpz_vec_get_mpf_vec+ -- * Assignment and basic manipulation+ , _fmpz_vec_set+ , _fmpz_vec_swap+ , _fmpz_vec_zero+ , _fmpz_vec_neg+ , _fmpz_vec_scalar_abs+ -- * Comparison+ , _fmpz_vec_equal+ , _fmpz_vec_is_zero+ , _fmpz_vec_max+ , _fmpz_vec_max_inplace+ -- * Sorting+ , _fmpz_vec_sort+ -- * Addition and subtraction+ , _fmpz_vec_add+ , _fmpz_vec_sub+ -- * Scalar multiplication and division+ , _fmpz_vec_scalar_mul_fmpz+ , _fmpz_vec_scalar_mul_si+ , _fmpz_vec_scalar_mul_ui+ , _fmpz_vec_scalar_mul_2exp+ , _fmpz_vec_scalar_divexact_fmpz+ , _fmpz_vec_scalar_divexact_si+ , _fmpz_vec_scalar_divexact_ui+ , _fmpz_vec_scalar_fdiv_q_fmpz+ , _fmpz_vec_scalar_fdiv_q_si+ , _fmpz_vec_scalar_fdiv_q_ui+ , _fmpz_vec_scalar_fdiv_q_2exp+ , _fmpz_vec_scalar_fdiv_r_2exp+ , _fmpz_vec_scalar_tdiv_q_fmpz+ , _fmpz_vec_scalar_tdiv_q_si+ , _fmpz_vec_scalar_tdiv_q_ui+ , _fmpz_vec_scalar_tdiv_q_2exp+ , _fmpz_vec_scalar_addmul_si+ , _fmpz_vec_scalar_addmul_ui+ , _fmpz_vec_scalar_addmul_fmpz+ , _fmpz_vec_scalar_addmul_si_2exp+ , _fmpz_vec_scalar_submul_fmpz+ , _fmpz_vec_scalar_submul_si+ , _fmpz_vec_scalar_submul_si_2exp+ -- * Sums and products+ , _fmpz_vec_sum+ , _fmpz_vec_prod+ -- * Reduction mod \(p\)+ , _fmpz_vec_scalar_mod_fmpz+ , _fmpz_vec_scalar_smod_fmpz+ -- * Gaussian content+ , _fmpz_vec_content+ , _fmpz_vec_content_chained+ , _fmpz_vec_lcm+ -- * Dot product+ , _fmpz_vec_dot+ , _fmpz_vec_dot_ptr+) where ++-- vectors of integers ---------------------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, nullPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.NMod++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_vec.h>++-- Memory management -----------------------------------------------------------++-- | /_fmpz_vec_init/ /len/ +-- +-- Returns an initialised vector of @fmpz@\'s of given length.+foreign import ccall "fmpz_vec.h _fmpz_vec_init"+ _fmpz_vec_init :: CLong -> IO (Ptr CFmpz)++-- | /_fmpz_vec_clear/ /vec/ /len/ +-- +-- Clears the entries of @(vec, len)@ and frees the space allocated for+-- @vec@.+foreign import ccall "fmpz_vec.h _fmpz_vec_clear"+ _fmpz_vec_clear :: Ptr CFmpz -> CLong -> IO ()++-- Randomisation ---------------------------------------------------------------++-- | /_fmpz_vec_randtest/ /f/ /state/ /len/ /bits/ +-- +-- Sets the entries of a vector of the given length to random integers with+-- up to the given number of bits per entry.+foreign import ccall "fmpz_vec.h _fmpz_vec_randtest"+ _fmpz_vec_randtest :: Ptr CFmpz -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- | /_fmpz_vec_randtest_unsigned/ /f/ /state/ /len/ /bits/ +-- +-- Sets the entries of a vector of the given length to random unsigned+-- integers with up to the given number of bits per entry.+foreign import ccall "fmpz_vec.h _fmpz_vec_randtest_unsigned"+ _fmpz_vec_randtest_unsigned :: Ptr CFmpz -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- Bit sizes and norms ---------------------------------------------------------++-- | /_fmpz_vec_max_bits/ /vec/ /len/ +-- +-- If \(b\) is the maximum number of bits of the absolute value of any+-- coefficient of @vec@, then if any coefficient of @vec@ is negative,+-- \(-b\) is returned, else \(b\) is returned.+foreign import ccall "fmpz_vec.h _fmpz_vec_max_bits"+ _fmpz_vec_max_bits :: Ptr CFmpz -> CLong -> IO CLong++-- | /_fmpz_vec_max_bits_ref/ /vec/ /len/ +-- +-- If \(b\) is the maximum number of bits of the absolute value of any+-- coefficient of @vec@, then if any coefficient of @vec@ is negative,+-- \(-b\) is returned, else \(b\) is returned. This is a slower reference+-- implementation of @_fmpz_vec_max_bits@.+foreign import ccall "fmpz_vec.h _fmpz_vec_max_bits_ref"+ _fmpz_vec_max_bits_ref :: Ptr CFmpz -> CLong -> IO CLong++-- | /_fmpz_vec_sum_max_bits/ /sumabs/ /maxabs/ /vec/ /len/ +-- +-- Sets @sumabs@ to the bit count of the sum of the absolute values of the+-- elements of @vec@. Sets @maxabs@ to the bit count of the maximum of the+-- absolute values of the elements of @vec@.+foreign import ccall "fmpz_vec.h _fmpz_vec_sum_max_bits"+ _fmpz_vec_sum_max_bits :: Ptr CLong -> Ptr CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_vec_max_limbs/ /vec/ /len/ +-- +-- Returns the maximum number of limbs needed to store the absolute value+-- of any entry in @(vec, len)@. If all entries are zero, returns zero.+foreign import ccall "fmpz_vec.h _fmpz_vec_max_limbs"+ _fmpz_vec_max_limbs :: Ptr CFmpz -> CLong -> IO CULong++-- | /_fmpz_vec_height/ /height/ /vec/ /len/ +-- +-- Computes the height of @(vec, len)@, defined as the largest of the+-- absolute values the coefficients. Equivalently, this gives the infinity+-- norm of the vector. If @len@ is zero, the height is \(0\).+foreign import ccall "fmpz_vec.h _fmpz_vec_height"+ _fmpz_vec_height :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_vec_height_index/ /vec/ /len/ +-- +-- Returns the index of an entry of maximum absolute value in the vector.+-- The the length must be at least 1.+foreign import ccall "fmpz_vec.h _fmpz_vec_height_index"+ _fmpz_vec_height_index :: Ptr CFmpz -> CLong -> IO CLong++-- Input and output ------------------------------------------------------------++foreign import ccall "_fmpz_vec_get_str"+ _fmpz_vec_get_str :: CLong -> Ptr CFmpz -> IO (CString)++-- | /_fmpz_vec_fread/ /file/ /vec/ /len/ +-- +-- Reads a vector from the stream @file@ and stores it at @*vec@. The+-- format is the same as the output format of @_fmpz_vec_fprint()@,+-- followed by either any character or the end of the file.+-- +-- The interpretation of the various input arguments depends on whether or+-- not @*vec@ is @NULL@:+-- +-- If @*vec == NULL@, the value of @*len@ on input is ignored. Once the+-- length has been read from @file@, @*len@ is set to that value and a+-- vector of this length is allocated at @*vec@. Finally, @*len@+-- coefficients are read from the input stream. In case of a file or+-- parsing error, clears the vector and sets @*vec@ and @*len@ to @NULL@+-- and @0@, respectively.+-- +-- Otherwise, if @*vec != NULL@, it is assumed that @(*vec, *len)@ is a+-- properly initialised vector. If the length on the input stream does not+-- match @*len@, a parsing error is raised. Attempts to read the right+-- number of coefficients from the input stream. In case of a file or+-- parsing error, leaves the vector @(*vec, *len)@ in its current state.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_vec.h _fmpz_vec_fread"+ _fmpz_vec_fread :: Ptr CFile -> Ptr CFmpz -> Ptr CLong -> IO CInt++-- | /_fmpz_vec_read/ /vec/ /len/ +-- +-- Reads a vector from @stdin@ and stores it at @*vec@.+-- +-- For further details, see @_fmpz_vec_fread()@.+foreign import ccall "fmpz_vec.h _fmpz_vec_read"+ _fmpz_vec_read :: Ptr CFmpz -> Ptr CLong -> IO CInt++-- | /_fmpz_vec_fprint/ /file/ /vec/ /len/ +-- +-- Prints the vector of given length to the stream @file@. The format is+-- the length followed by two spaces, then a space separated list of+-- coefficients. If the length is zero, only \(0\) is printed.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fmpz_vec.h _fmpz_vec_fprint"+ _fmpz_vec_fprint :: Ptr CFile -> Ptr CFmpz -> CLong -> IO CInt++-- | /_fmpz_vec_print/ /vec/ /len/ +-- +-- Prints the vector of given length to @stdout@.+-- +-- For further details, see @_fmpz_vec_fprint()@.+_fmpz_vec_print :: Ptr CFmpz -> CLong -> IO CInt+_fmpz_vec_print x n = printCStr (_fmpz_vec_get_str n) x++-- Conversions -----------------------------------------------------------------++-- | /_fmpz_vec_get_nmod_vec/ /res/ /poly/ /len/ /mod/ +-- +-- Reduce the coefficients of @(poly, len)@ modulo the given modulus and+-- set @(res, len)@ to the result.+foreign import ccall "fmpz_vec.h _fmpz_vec_get_nmod_vec"+ _fmpz_vec_get_nmod_vec :: Ptr CMp -> Ptr CFmpz -> CLong -> Ptr CNMod -> IO ()++-- | /_fmpz_vec_set_nmod_vec/ /res/ /poly/ /len/ /mod/ +-- +-- Set the coefficients of @(res, len)@ to the symmetric modulus of the+-- coefficients of @(poly, len)@, i.e. convert the given coefficients+-- modulo the given modulus \(n\) to their signed integer representatives+-- in the range \([-n/2, n/2)\).+foreign import ccall "fmpz_vec.h _fmpz_vec_set_nmod_vec"+ _fmpz_vec_set_nmod_vec :: Ptr CFmpz -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /_fmpz_vec_get_fft/ /coeffs_f/ /coeffs_m/ /l/ /length/ +-- +-- Convert the vector of coeffs @coeffs_m@ to an fft vector @coeffs_f@ of+-- the given @length@ with @l@ limbs per coefficient with an additional+-- limb for overflow.+foreign import ccall "fmpz_vec.h _fmpz_vec_get_fft"+ _fmpz_vec_get_fft :: Ptr (Ptr CMpLimb) -> Ptr CFmpz -> CLong -> CLong -> IO CLong++-- | /_fmpz_vec_set_fft/ /coeffs_m/ /length/ /coeffs_f/ /limbs/ /sign/ +-- +-- Convert an fft vector @coeffs_f@ of fully reduced Fermat numbers of the+-- given @length@ to a vector of @fmpz@\'s. Each is assumed to be the given+-- number of limbs in length with an additional limb for overflow. If the+-- output coefficients are to be signed then set @sign@, otherwise clear+-- it. The resulting @fmpz@s will be in the range \([-n,n]\) in the signed+-- case and in the range \([0,2n]\) in the unsigned case where+-- @n = 2^(FLINT_BITS*limbs - 1)@.+foreign import ccall "fmpz_vec.h _fmpz_vec_set_fft"+ _fmpz_vec_set_fft :: Ptr CFmpz -> CLong -> Ptr CMp -> CLong -> CLong -> IO ()++-- | /_fmpz_vec_get_d_vec_2exp/ /appv/ /vec/ /len/ +-- +-- Export the array of @len@ entries starting at the pointer @vec@ to an+-- array of doubles @appv@, each entry of which is notionally multiplied by+-- a single returned exponent to give the original entry. The returned+-- exponent is set to be the maximum exponent of all the original entries+-- so that all the doubles in @appv@ have a maximum absolute value of 1.0.+foreign import ccall "fmpz_vec.h _fmpz_vec_get_d_vec_2exp"+ _fmpz_vec_get_d_vec_2exp :: Ptr CDouble -> Ptr CFmpz -> CLong -> IO CLong++-- -- | /_fmpz_vec_get_mpf_vec/ /appv/ /vec/ /len/ +-- -- +-- -- Export the array of @len@ entries starting at the pointer @vec@ to an+-- -- array of mpfs @appv@.+-- foreign import ccall "fmpz_vec.h _fmpz_vec_get_mpf_vec"+-- _fmpz_vec_get_mpf_vec :: Ptr CMpf -> Ptr CFmpz -> CLong -> IO ()++-- Assignment and basic manipulation -------------------------------------------++-- | /_fmpz_vec_set/ /vec1/ /vec2/ /len2/ +-- +-- Makes a copy of @(vec2, len2)@ into @vec1@.+foreign import ccall "fmpz_vec.h _fmpz_vec_set"+ _fmpz_vec_set :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_vec_swap/ /vec1/ /vec2/ /len2/ +-- +-- Swaps the integers in @(vec1, len2)@ and @(vec2, len2)@.+foreign import ccall "fmpz_vec.h _fmpz_vec_swap"+ _fmpz_vec_swap :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_vec_zero/ /vec/ /len/ +-- +-- Zeros the entries of @(vec, len)@.+foreign import ccall "fmpz_vec.h _fmpz_vec_zero"+ _fmpz_vec_zero :: Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_vec_neg/ /vec1/ /vec2/ /len2/ +-- +-- Negates @(vec2, len2)@ and places it into @vec1@.+foreign import ccall "fmpz_vec.h _fmpz_vec_neg"+ _fmpz_vec_neg :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_vec_scalar_abs/ /vec1/ /vec2/ /len2/ +-- +-- Takes the absolute value of entries in @(vec2, len2)@ and places the+-- result into @vec1@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_abs"+ _fmpz_vec_scalar_abs :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /_fmpz_vec_equal/ /vec1/ /vec2/ /len/ +-- +-- Compares two vectors of the given length and returns \(1\) if they are+-- equal, otherwise returns \(0\).+foreign import ccall "fmpz_vec.h _fmpz_vec_equal"+ _fmpz_vec_equal :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO CInt++-- | /_fmpz_vec_is_zero/ /vec/ /len/ +-- +-- Returns \(1\) if @(vec, len)@ is zero, and \(0\) otherwise.+foreign import ccall "fmpz_vec.h _fmpz_vec_is_zero"+ _fmpz_vec_is_zero :: Ptr CFmpz -> CLong -> IO CInt++-- | /_fmpz_vec_max/ /vec1/ /vec2/ /vec3/ /len/ +-- +-- Sets @vec1@ to the pointwise maximum of @vec2@ and @vec3@.+foreign import ccall "fmpz_vec.h _fmpz_vec_max"+ _fmpz_vec_max :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_vec_max_inplace/ /vec1/ /vec2/ /len/ +-- +-- Sets @vec1@ to the pointwise maximum of @vec1@ and @vec2@.+foreign import ccall "fmpz_vec.h _fmpz_vec_max_inplace"+ _fmpz_vec_max_inplace :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- Sorting ---------------------------------------------------------------------++-- | /_fmpz_vec_sort/ /vec/ /len/ +-- +-- Sorts the coefficients of @vec@ in ascending order.+foreign import ccall "fmpz_vec.h _fmpz_vec_sort"+ _fmpz_vec_sort :: Ptr CFmpz -> CLong -> IO ()++-- Addition and subtraction ----------------------------------------------------++-- | /_fmpz_vec_add/ /res/ /vec1/ /vec2/ /len2/ +-- +-- Sets @(res, len2)@ to the sum of @(vec1, len2)@ and @(vec2, len2)@.+foreign import ccall "fmpz_vec.h _fmpz_vec_add"+ _fmpz_vec_add :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_vec_sub/ /res/ /vec1/ /vec2/ /len2/ +-- +-- Sets @(res, len2)@ to @(vec1, len2)@ minus @(vec2, len2)@.+foreign import ccall "fmpz_vec.h _fmpz_vec_sub"+ _fmpz_vec_sub :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- Scalar multiplication and division ------------------------------------------++-- | /_fmpz_vec_scalar_mul_fmpz/ /vec1/ /vec2/ /len2/ /x/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ multiplied by \(c\), where \(c\)+-- is an @fmpz_t@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_mul_fmpz"+ _fmpz_vec_scalar_mul_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /_fmpz_vec_scalar_mul_si/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ multiplied by \(c\), where \(c\)+-- is a @slong@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_mul_si"+ _fmpz_vec_scalar_mul_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /_fmpz_vec_scalar_mul_ui/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ multiplied by \(c\), where \(c\)+-- is an @ulong@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_mul_ui"+ _fmpz_vec_scalar_mul_ui :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /_fmpz_vec_scalar_mul_2exp/ /vec1/ /vec2/ /len2/ /exp/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ multiplied by @2^exp@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_mul_2exp"+ _fmpz_vec_scalar_mul_2exp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /_fmpz_vec_scalar_divexact_fmpz/ /vec1/ /vec2/ /len2/ /x/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ divided by \(x\), where the+-- division is assumed to be exact for every entry in @vec2@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_divexact_fmpz"+ _fmpz_vec_scalar_divexact_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /_fmpz_vec_scalar_divexact_si/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ divided by \(x\), where the+-- division is assumed to be exact for every entry in @vec2@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_divexact_si"+ _fmpz_vec_scalar_divexact_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /_fmpz_vec_scalar_divexact_ui/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ divided by \(x\), where the+-- division is assumed to be exact for every entry in @vec2@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_divexact_ui"+ _fmpz_vec_scalar_divexact_ui :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CULong -> IO ()++-- | /_fmpz_vec_scalar_fdiv_q_fmpz/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ divided by \(c\), rounding down+-- towards minus infinity whenever the division is not exact.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_fdiv_q_fmpz"+ _fmpz_vec_scalar_fdiv_q_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /_fmpz_vec_scalar_fdiv_q_si/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ divided by \(c\), rounding down+-- towards minus infinity whenever the division is not exact.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_fdiv_q_si"+ _fmpz_vec_scalar_fdiv_q_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /_fmpz_vec_scalar_fdiv_q_ui/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ divided by \(c\), rounding down+-- towards minus infinity whenever the division is not exact.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_fdiv_q_ui"+ _fmpz_vec_scalar_fdiv_q_ui :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /_fmpz_vec_scalar_fdiv_q_2exp/ /vec1/ /vec2/ /len2/ /exp/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ divided by @2^exp@, rounding down+-- towards minus infinity whenever the division is not exact.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_fdiv_q_2exp"+ _fmpz_vec_scalar_fdiv_q_2exp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /_fmpz_vec_scalar_fdiv_r_2exp/ /vec1/ /vec2/ /len2/ /exp/ +-- +-- Sets @(vec1, len2)@ to the remainder of @(vec2, len2)@ divided by+-- @2^exp@, rounding down the quotient towards minus infinity whenever the+-- division is not exact.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_fdiv_r_2exp"+ _fmpz_vec_scalar_fdiv_r_2exp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /_fmpz_vec_scalar_tdiv_q_fmpz/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ divided by \(c\), rounding towards+-- zero whenever the division is not exact.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_tdiv_q_fmpz"+ _fmpz_vec_scalar_tdiv_q_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /_fmpz_vec_scalar_tdiv_q_si/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ divided by \(c\), rounding towards+-- zero whenever the division is not exact.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_tdiv_q_si"+ _fmpz_vec_scalar_tdiv_q_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /_fmpz_vec_scalar_tdiv_q_ui/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ divided by \(c\), rounding towards+-- zero whenever the division is not exact.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_tdiv_q_ui"+ _fmpz_vec_scalar_tdiv_q_ui :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /_fmpz_vec_scalar_tdiv_q_2exp/ /vec1/ /vec2/ /len2/ /exp/ +-- +-- Sets @(vec1, len2)@ to @(vec2, len2)@ divided by @2^exp@, rounding down+-- towards zero whenever the division is not exact.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_tdiv_q_2exp"+ _fmpz_vec_scalar_tdiv_q_2exp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_addmul_si"+ _fmpz_vec_scalar_addmul_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_addmul_ui"+ _fmpz_vec_scalar_addmul_ui :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CULong -> IO ()++-- | /_fmpz_vec_scalar_addmul_fmpz/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Adds @(vec2, len2)@ times \(c\) to @(vec1, len2)@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_addmul_fmpz"+ _fmpz_vec_scalar_addmul_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /_fmpz_vec_scalar_addmul_si_2exp/ /vec1/ /vec2/ /len2/ /c/ /exp/ +-- +-- Adds @(vec2, len2)@ times @c * 2^exp@ to @(vec1, len2)@, where \(c\) is+-- a @slong@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_addmul_si_2exp"+ _fmpz_vec_scalar_addmul_si_2exp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> CULong -> IO ()++-- | /_fmpz_vec_scalar_submul_fmpz/ /vec1/ /vec2/ /len2/ /x/ +-- +-- Subtracts @(vec2, len2)@ times \(c\) from @(vec1, len2)@, where \(c\) is+-- a @fmpz_t@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_submul_fmpz"+ _fmpz_vec_scalar_submul_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /_fmpz_vec_scalar_submul_si/ /vec1/ /vec2/ /len2/ /c/ +-- +-- Subtracts @(vec2, len2)@ times \(c\) from @(vec1, len2)@, where \(c\) is+-- a @slong@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_submul_si"+ _fmpz_vec_scalar_submul_si :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> IO ()++-- | /_fmpz_vec_scalar_submul_si_2exp/ /vec1/ /vec2/ /len2/ /c/ /e/ +-- +-- Subtracts @(vec2, len2)@ times \(c \times 2^e\) from @(vec1, len2)@,+-- where \(c\) is a @slong@.+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_submul_si_2exp"+ _fmpz_vec_scalar_submul_si_2exp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> CULong -> IO ()++-- Sums and products -----------------------------------------------------------++-- | /_fmpz_vec_sum/ /res/ /vec/ /len/ +-- +-- Sets @res@ to the sum of the entries in @(vec, len)@. Aliasing of @res@+-- with the entries in @vec@ is not permitted.+foreign import ccall "fmpz_vec.h _fmpz_vec_sum"+ _fmpz_vec_sum :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_vec_prod/ /res/ /vec/ /len/ +-- +-- Sets @res@ to the product of the entries in @(vec, len)@. Aliasing of+-- @res@ with the entries in @vec@ is not permitted. Uses binary splitting.+foreign import ccall "fmpz_vec.h _fmpz_vec_prod"+ _fmpz_vec_prod :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- Reduction mod \(p\) ---------------------------------------------------------++-- | /_fmpz_vec_scalar_mod_fmpz/ /res/ /vec/ /len/ /p/ +-- +-- Reduces all entries in @(vec, len)@ modulo \(p > 0\).+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_mod_fmpz"+ _fmpz_vec_scalar_mod_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /_fmpz_vec_scalar_smod_fmpz/ /res/ /vec/ /len/ /p/ +-- +-- Reduces all entries in @(vec, len)@ modulo \(p > 0\), choosing the+-- unique representative in \((-p/2, p/2]\).+foreign import ccall "fmpz_vec.h _fmpz_vec_scalar_smod_fmpz"+ _fmpz_vec_scalar_smod_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- Gaussian content ------------------------------------------------------------++-- | /_fmpz_vec_content/ /res/ /vec/ /len/ +-- +-- Sets @res@ to the non-negative content of the entries in @vec@. The+-- content of a zero vector, including the case when the length is zero, is+-- defined to be zero.+foreign import ccall "fmpz_vec.h _fmpz_vec_content"+ _fmpz_vec_content :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_vec_content_chained/ /res/ /vec/ /len/ /input/ +-- +-- Sets @res@ to the non-negative content of @input@ and the entries in+-- @vec@. This is useful for calculating the common content of several+-- vectors.+foreign import ccall "fmpz_vec.h _fmpz_vec_content_chained"+ _fmpz_vec_content_chained :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /_fmpz_vec_lcm/ /res/ /vec/ /len/ +-- +-- Sets @res@ to the nonnegative least common multiple of the entries in+-- @vec@. The least common multiple is zero if any entry in the vector is+-- zero. The least common multiple of a length zero vector is defined to be+-- one.+foreign import ccall "fmpz_vec.h _fmpz_vec_lcm"+ _fmpz_vec_lcm :: Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- Dot product -----------------------------------------------------------------++-- | /_fmpz_vec_dot/ /res/ /vec1/ /vec2/ /len2/ +-- +-- Sets @res@ to the dot product of @(vec1, len2)@ and @(vec2, len2)@.+foreign import ccall "fmpz_vec.h _fmpz_vec_dot"+ _fmpz_vec_dot :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /_fmpz_vec_dot_ptr/ /res/ /vec1/ /vec2/ /offset/ /len/ +-- +-- Sets @res@ to the dot product of @len@ values at @vec1@ and the @len@+-- values @vec2[i] + offset@ for @0 \\leq i \< len@.+foreign import ccall "fmpz_vec.h _fmpz_vec_dot_ptr"+ _fmpz_vec_dot_ptr :: Ptr CFmpz -> Ptr CFmpz -> Ptr (Ptr CFmpz) -> CLong -> CLong -> IO ()+
+ src/Data/Number/Flint/Fq.hs view
@@ -0,0 +1,49 @@+{-|+module : Data.Number.Flint.Fq+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++= Finite fields++This module implements operations over the finite field \(\mathbb F_q\) where \( q = p^d \) with \(p\) prime.++== Basic usage++Consider the finite field \(\mathbb F_{11^4}\). Here we initialize the+context and set @x@ to the generator of the field and print it and its+fourth power.++@+import Data.Number.Flint++main = do+ ctx <- newFqCtx 11 4 "alpha"+ withNewFq ctx $ \\x -> do + withFqCtx ctx $ \\ctx -> do+ fq_ctx_print ctx+ putStr "\\n"+ fq_gen x ctx+ fq_print_pretty x ctx+ putStr "\\n"+ fq_pow_ui x x 4 ctx+ fq_print_pretty x ctx+ putStr "\\n"+@++Running main yields:++>>> main +p = 11+d = 4+f(X) = X^4+8*X^2+10*X+2+<BLANKLINE>+alpha +3*alpha^2+alpha+9+-}+module Data.Number.Flint.Fq (+ module Data.Number.Flint.Fq.FFI+) where++import Data.Number.Flint.Fq.FFI+
+ src/Data/Number/Flint/Fq/Embed.hs view
@@ -0,0 +1,6 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Fq.Embed (+ module Data.Number.Flint.Fq.Embed.FFI+ ) where++import Data.Number.Flint.Fq.Embed.FFI
+ src/Data/Number/Flint/Fq/Embed/FFI.hsc view
@@ -0,0 +1,153 @@+{-|+module : Data.Number.Flint.Fq.Embed.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Embed.FFI (+ -- * Computing isomorphisms and embeddings of finite fields+ fq_embed_gens+ , _fq_embed_gens_naive+ , fq_embed_matrices+ , fq_embed_trace_matrix+ , fq_embed_composition_matrix+ , fq_embed_composition_matrix_sub+ , fq_embed_mul_matrix+ , fq_embed_mono_to_dual_matrix+ , fq_embed_dual_to_mono_matrix+ , fq_modulus_pow_series_inv+ , fq_modulus_derivative_inv+) where++import Foreign.Ptr+import Foreign.C.Types++import Data.Number.Flint.Fmpz.Mod.Poly+import Data.Number.Flint.Fmpz.Mod.Mat++import Data.Number.Flint.Fq++-- Computing isomorphisms and embeddings of finite fields ----------------------++-- | /fq_embed_gens/ /gen_sub/ /gen_sup/ /minpoly/ /sub_ctx/ /sup_ctx/ +--+-- Given two contexts @sub_ctx@ and @sup_ctx@, such that @degree(sub_ctx)@+-- divides @degree(sup_ctx)@, compute:+-- +-- - an element @gen_sub@ in @sub_ctx@ such that @gen_sub@ generates the+-- finite field defined by @sub_ctx@,+-- - its minimal polynomial @minpoly@,+-- - a root @gen_sup@ of @minpoly@ inside the field defined by @sup_ctx@.+-- +-- These data uniquely define an embedding of @sub_ctx@ into @sup_ctx@.+foreign import ccall "fq_embed.h fq_embed_gens"+ fq_embed_gens :: Ptr CFq -> Ptr CFq -> Ptr CFmpzModPoly -> Ptr CFqCtx -> Ptr CFqCtx -> IO ()++-- | /_fq_embed_gens_naive/ /gen_sub/ /gen_sup/ /minpoly/ /sub_ctx/ /sup_ctx/ +--+-- Given two contexts @sub_ctx@ and @sup_ctx@, such that @degree(sub_ctx)@+-- divides @degree(sup_ctx)@, compute an embedding of @sub_ctx@ into+-- @sup_ctx@ defined as follows:+-- +-- - @gen_sub@ is the canonical generator of @sup_ctx@ (i.e., the class+-- of \(X\)),+-- - @minpoly@ is the defining polynomial of @sub_ctx@,+-- - @gen_sup@ is a root of @minpoly@ inside the field defined by+-- @sup_ctx@.+foreign import ccall "fq_embed.h _fq_embed_gens_naive"+ _fq_embed_gens_naive :: Ptr CFq -> Ptr CFq -> Ptr CFmpzModPoly -> Ptr CFqCtx -> Ptr CFqCtx -> IO ()++-- | /fq_embed_matrices/ /embed/ /project/ /gen_sub/ /sub_ctx/ /gen_sup/ /sup_ctx/ /gen_minpoly/ +--+-- Given:+-- +-- - two contexts @sub_ctx@ and @sup_ctx@, of respective degrees \(m\)+-- and \(n\), such that \(m\) divides \(n\);+-- - a generator @gen_sub@ of @sub_ctx@, its minimal polynomial+-- @gen_minpoly@, and a root @gen_sup@ of @gen_minpoly@ in @sup_ctx@,+-- as returned by @fq_embed_gens@;+-- +-- Compute:+-- +-- - the \(n\times m\) matrix @embed@ mapping @gen_sub@ to @gen_sup@, and+-- all their powers accordingly;+-- - an \(m\times n\) matrix @project@ such that @project@ \(\times\)+-- @embed@ is the \(m\times m\) identity matrix.+foreign import ccall "fq_embed.h fq_embed_matrices"+ fq_embed_matrices :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFq -> Ptr CFqCtx -> Ptr CFq -> Ptr CFqCtx -> Ptr CFmpzModPoly -> IO ()++-- | /fq_embed_trace_matrix/ /res/ /basis/ /sub_ctx/ /sup_ctx/ +--+-- Given:+-- +-- - two contexts @sub_ctx@ and @sup_ctx@, of degrees \(m\) and \(n\),+-- such that \(m\) divides \(n\);+-- - an \(n\times m\) matrix @basis@ that maps @sub_ctx@ to an isomorphic+-- subfield in @sup_ctx@;+-- +-- Compute the \(m\times n\) matrix of the trace from @sup_ctx@ to+-- @sub_ctx@.+-- +-- This matrix is computed as+-- +-- @embed_dual_to_mono_matrix(_, sub_ctx)@ \(\times\) @basis@t \(\times\)+-- @embed_mono_to_dual_matrix(_, sup_ctx)@.+-- +-- __Note:__ if \(m=n\), @basis@ represents a Frobenius, and the result is+-- its inverse matrix.+foreign import ccall "fq_embed.h fq_embed_trace_matrix"+ fq_embed_trace_matrix :: Ptr CFmpzModMat -> Ptr CFmpzModMat -> Ptr CFqCtx -> Ptr CFqCtx -> IO ()++-- | /fq_embed_composition_matrix/ /matrix/ /gen/ /ctx/ +--+-- Compute the /composition matrix/ of @gen@.+-- +-- For an element \(a\in\mathbf{F}_{p^n}\), its composition matrix is the+-- matrix whose columns are \(a^0, a^1, \ldots, a^{n-1}\).+foreign import ccall "fq_embed.h fq_embed_composition_matrix"+ fq_embed_composition_matrix :: Ptr CFmpzModMat -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_embed_composition_matrix_sub/ /matrix/ /gen/ /ctx/ /trunc/ +--+-- Compute the /composition matrix/ of @gen@, truncated to @trunc@ columns.+foreign import ccall "fq_embed.h fq_embed_composition_matrix_sub"+ fq_embed_composition_matrix_sub :: Ptr CFmpzModMat -> Ptr CFq -> Ptr CFqCtx -> CLong -> IO ()++-- | /fq_embed_mul_matrix/ /matrix/ /gen/ /ctx/ +--+-- Compute the /multiplication matrix/ of @gen@.+-- +-- For an element \(a\) in \(\mathbf{F}_{p^n}=\mathbf{F}_p[x]\), its+-- multiplication matrix is the matrix whose columns are \(a, ax,+-- \dots, ax^{n-1}\).+foreign import ccall "fq_embed.h fq_embed_mul_matrix"+ fq_embed_mul_matrix :: Ptr CFmpzModMat -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_embed_mono_to_dual_matrix/ /res/ /ctx/ +--+-- Compute the change of basis matrix from the monomial basis of @ctx@ to+-- its dual basis.+foreign import ccall "fq_embed.h fq_embed_mono_to_dual_matrix"+ fq_embed_mono_to_dual_matrix :: Ptr CFmpzModMat -> Ptr CFqCtx -> IO ()++-- | /fq_embed_dual_to_mono_matrix/ /res/ /ctx/ +--+-- Compute the change of basis matrix from the dual basis of @ctx@ to its+-- monomial basis.+foreign import ccall "fq_embed.h fq_embed_dual_to_mono_matrix"+ fq_embed_dual_to_mono_matrix :: Ptr CFmpzModMat -> Ptr CFqCtx -> IO ()++-- | /fq_modulus_pow_series_inv/ /res/ /ctx/ /trunc/ +--+-- Compute the power series inverse of the reverse of the modulus of @ctx@+-- up to \(O(x^\texttt{trunc})\).+foreign import ccall "fq_embed.h fq_modulus_pow_series_inv"+ fq_modulus_pow_series_inv :: Ptr CFmpzModPoly -> Ptr CFqCtx -> CLong -> IO ()++-- | /fq_modulus_derivative_inv/ /m_prime/ /m_prime_inv/ /ctx/ +--+-- Compute the derivative @m_prime@ of the modulus of @ctx@ as an element+-- of @ctx@, and its inverse @m_prime_inv@.+foreign import ccall "fq_embed.h fq_modulus_derivative_inv"+ fq_modulus_derivative_inv :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()+
+ src/Data/Number/Flint/Fq/FFI.hsc view
@@ -0,0 +1,864 @@+{-|+module : Data.Number.Flint.Fq.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.FFI (+ -- * Finite fields+ -- ** Finite field element+ --+ -- | The type `Fq` represents an element of the finite field \(\mathbb F_q\).+ Fq (..)+ , CFq (..)+ , newFq+ , withFq+ , withNewFq+ -- * Finite field context+ , FqCtx (..)+ , CFqCtx (..)+ , newFqCtx+ , withFqCtx+ , withNewFqCtx+ , newFqCtxConway+ , withNewFqCtxConway+ , newFqCtxModulus+ , withNewFqCtxModulus+ -- * Context Management+ , fq_ctx_init+ , _fq_ctx_init_conway+ , fq_ctx_init_conway+ , fq_ctx_init_modulus+ , fq_ctx_clear+ , fq_ctx_modulus+ , fq_ctx_degree+ , fq_ctx_prime+ , fq_ctx_order+ , fq_ctx_get_str+ , fq_ctx_fprint+ , fq_ctx_print+ , fq_ctx_randtest+ , fq_ctx_randtest_reducible+ -- * Memory management+ , fq_init+ , fq_init2+ , fq_clear+ , _fq_sparse_reduce+ , _fq_dense_reduce+ , _fq_reduce+ , fq_reduce+ -- * Basic arithmetic+ , fq_add+ , fq_sub+ , fq_sub_one+ , fq_neg+ , fq_mul+ , fq_mul_fmpz+ , fq_mul_si+ , fq_mul_ui+ , fq_sqr+ , fq_div+ , _fq_inv+ , fq_inv+ , fq_gcdinv+ , _fq_pow+ , fq_pow+ , fq_pow_ui+ -- * Roots+ , fq_sqrt+ , fq_pth_root+ , fq_is_square+ -- * Output+ , fq_fprint_pretty+ , fq_print_pretty+ , fq_fprint+ , fq_print+ , fq_get_str+ , fq_get_str_pretty+ -- * Randomisation+ , fq_randtest+ , fq_randtest_not_zero+ , fq_randtest_dense+ , fq_rand+ , fq_rand_not_zero+ -- * Assignments and conversions+ , fq_set+ , fq_set_si+ , fq_set_ui+ , fq_set_fmpz+ , fq_swap+ , fq_zero+ , fq_one+ , fq_gen+ , fq_get_fmpz+ , fq_get_fmpz_poly+ , fq_get_fmpz_mod_poly+ , fq_set_fmpz_poly+ , fq_set_fmpz_mod_poly+ , fq_get_fmpz_mod_mat+ , fq_set_fmpz_mod_mat+ -- * Comparison+ , fq_is_zero+ , fq_is_one+ , fq_equal+ , fq_is_invertible+ , fq_is_invertible_f+ -- * Special functions+ , _fq_trace+ , fq_trace+ , _fq_norm+ , fq_norm+ , _fq_frobenius+ , fq_frobenius+ , fq_multiplicative_order+ , fq_is_primitive+ -- * Bit packing+ , fq_bit_pack+ , fq_bit_unpack+) where ++-- finite fields ---------------------------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Mod+import Data.Number.Flint.Fmpz.Mod.Poly+import Data.Number.Flint.Fmpz.Mod.Mat+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fq.Types++#include <flint/flint.h>+#include <flint/fq.h>++-- fq_t ------------------------------------------------------------------------++-- | Create a new `Fq` with context `ctx`.+newFq :: FqCtx -> IO Fq+newFq ctx@(FqCtx pctx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqCtx ctx $ \ctx -> do+ fq_init x ctx+ addForeignPtrFinalizerEnv p_fq_clear x pctx+ return $ Fq x++-- | Use `Fq`.+{-# INLINE withFq #-}+withFq (Fq p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (Fq p,)++-- | Use a new `Fq`.+{-# INLINE withNewFq #-}+withNewFq ctx f = do+ x <- newFq ctx+ withFq x f++-- fq_ctx_t --------------------------------------------------------------------++-- | Context of the finite field (opaque pointer)+data FqCtx = FqCtx {-# UNPACK #-} !(ForeignPtr CFqCtx)+type CFqCtx = CFlint FqCtx++instance Storable CFqCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_ctx_t}+ peek = undefined+ poke = undefined++-- | Create a new `Fq` context using `fq_ctx_init`.+newFqCtx p d var = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFmpz p $ \p ->+ withCString var $ \var ->+ fq_ctx_init x p d var+ addForeignPtrFinalizer p_fq_ctx_clear x+ return $ FqCtx x++-- | Use the `FqCtx`.+{-# INLINE withFqCtx #-}+withFqCtx (FqCtx p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FqCtx p,)++-- | Apply function to new `FqCtx`.+-- parameters as in `newFqCtx`.+withNewFqCtx p d var f = do+ ctx <- newFqCtx p d var+ withFqCtx ctx f+ +-- | Create a new `Fq` context using `fq_ctx_init_conway`.+newFqCtxConway p d var = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFmpz p $ \p ->+ withCString var $ \var ->+ fq_ctx_init_conway x p d var+ addForeignPtrFinalizer p_fq_ctx_clear x+ return $ FqCtx x++-- | Apply function to new `Fq` initialized with `fq_ctx_init_conway`.+withNewFqCtxConway p d var f = do+ ctx <- newFqCtxConway p d var+ withFqCtx ctx f+ +-- | Create a new `Fq` context using `fq_ctx_init_modulus`.+newFqCtxModulus modulus mod_ctx var = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFmpzModPoly modulus $ \modulus ->+ withFmpzModCtx mod_ctx $ \mod_ctx -> + withCString var $ \var ->+ fq_ctx_init_modulus x modulus mod_ctx var+ addForeignPtrFinalizer p_fq_ctx_clear x+ return $ FqCtx x++-- | Create a new `Fq` initialized using `fq_ctx_init_modulus`.+withNewFqCtxModulus modulus mod_ctx var f = do+ ctx <- newFqCtxModulus modulus mod_ctx var+ withFqCtx ctx f+ +-- Context Management ----------------------------------------------------------++-- | /fq_ctx_init/ /ctx/ /p/ /d/ /var/ +-- +-- Initialises the context for prime \(p\) and extension degree \(d\), with+-- name @var@ for the generator. By default, it will try use a Conway+-- polynomial; if one is not available, a random irreducible polynomial+-- will be used.+-- +-- Assumes that \(p\) is a prime.+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq.h fq_ctx_init"+ fq_ctx_init :: Ptr CFqCtx -> Ptr CFmpz -> CLong -> CString -> IO ()++-- | /_fq_ctx_init_conway/ /ctx/ /p/ /d/ /var/ +-- +-- Attempts to initialise the context for prime \(p\) and extension degree+-- \(d\), with name @var@ for the generator using a Conway polynomial for+-- the modulus.+-- +-- Returns \(1\) if the Conway polynomial is in the database for the given+-- size and the initialization is successful; otherwise, returns \(0\).+-- +-- Assumes that \(p\) is a prime.+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq.h _fq_ctx_init_conway"+ _fq_ctx_init_conway :: Ptr CFqCtx -> Ptr CFmpz -> CLong -> CString -> IO CInt++-- | /fq_ctx_init_conway/ /ctx/ /p/ /d/ /var/ +-- +-- Initialises the context for prime \(p\) and extension degree \(d\), with+-- name @var@ for the generator using a Conway polynomial for the modulus.+-- +-- Assumes that \(p\) is a prime.+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq.h fq_ctx_init_conway"+ fq_ctx_init_conway :: Ptr CFqCtx -> Ptr CFmpz -> CLong -> CString -> IO ()++-- | /fq_ctx_init_modulus/ /ctx/ /modulus/ /ctxp/ /var/ +-- +-- Initialises the context for given @modulus@ with name @var@ for the+-- generator.+-- +-- Assumes that @modulus@ is an irreducible polynomial over the finite+-- field \(\mathbf{F}_{p}\) in @ctxp@.+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq.h fq_ctx_init_modulus"+ fq_ctx_init_modulus :: Ptr CFqCtx -> Ptr CFmpzModPoly -> Ptr CFmpzModCtx -> CString -> IO ()++-- | /fq_ctx_clear/ /ctx/ +-- +-- Clears all memory that has been allocated as part of the context.+foreign import ccall "fq.h fq_ctx_clear"+ fq_ctx_clear :: Ptr CFqCtx -> IO ()++foreign import ccall "fq.h &fq_ctx_clear"+ p_fq_ctx_clear :: FunPtr (Ptr CFqCtx -> IO ())++-- | /fq_ctx_modulus/ /ctx/ +-- +-- Returns a pointer to the modulus in the context.+foreign import ccall "fq.h fq_ctx_modulus"+ fq_ctx_modulus :: Ptr CFqCtx -> IO (Ptr CFmpzModPoly)++-- | /fq_ctx_degree/ /ctx/ +-- +-- Returns the degree of the field extension+-- \([\mathbf{F}_{q} : \mathbf{F}_{p}]\), which is equal to \(\log_{p} q\).+foreign import ccall "fq.h fq_ctx_degree"+ fq_ctx_degree :: Ptr CFqCtx -> IO CLong++-- | /fq_ctx_prime/ /ctx/ +-- +-- Returns a pointer to the prime \(p\) in the context.+foreign import ccall "fq.h fq_ctx_prime"+ fq_ctx_prime :: Ptr CFqCtx -> IO (Ptr CFmpz)++-- | /fq_ctx_order/ /f/ /ctx/ +-- +-- Sets \(f\) to be the size of the finite field.+foreign import ccall "fq.h fq_ctx_order"+ fq_ctx_order :: Ptr CFmpz -> Ptr CFqCtx -> IO ()++foreign import ccall "fq.h fq_ctx_get_str"+ fq_ctx_get_str :: Ptr CFqCtx -> IO CString++-- | /fq_ctx_fprint/ /file/ /ctx/ +-- +-- Prints the context information to @file@. Returns 1 for a success and a+-- negative number for an error.+foreign import ccall "fq.h fq_ctx_fprint"+ fq_ctx_fprint :: Ptr CFile -> Ptr CFqCtx -> IO CInt++-- | /fq_ctx_print/ /ctx/ +-- +-- Prints the context information to @stdout@.+fq_ctx_print :: Ptr CFqCtx -> IO ()+fq_ctx_print ctx = do+ printCStr fq_ctx_get_str ctx+ return ()+ +-- | /fq_ctx_randtest/ /ctx/ +-- +-- Initializes @ctx@ to a random finite field. Assumes that @fq_ctx_init@+-- has not been called on @ctx@ already.+foreign import ccall "fq.h fq_ctx_randtest"+ fq_ctx_randtest :: Ptr CFqCtx -> IO ()++-- | /fq_ctx_randtest_reducible/ /ctx/ +-- +-- Initializes @ctx@ to a random extension of a prime field. The modulus+-- may or may not be irreducible. Assumes that @fq_ctx_init@ has not been+-- called on @ctx@ already.+foreign import ccall "fq.h fq_ctx_randtest_reducible"+ fq_ctx_randtest_reducible :: Ptr CFqCtx -> IO ()++-- Memory management -----------------------------------------------------------++-- | /fq_init/ /rop/ /ctx/ +-- +-- Initialises the element @rop@, setting its value to \(0\).+foreign import ccall "fq.h fq_init"+ fq_init :: Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_init2/ /rop/ /ctx/ +-- +-- Initialises @poly@ with at least enough space for it to be an element of+-- @ctx@ and sets it to \(0\).+foreign import ccall "fq.h fq_init2"+ fq_init2 :: Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_clear/ /rop/ /ctx/ +-- +-- Clears the element @rop@.+foreign import ccall "fq.h fq_clear"+ fq_clear :: Ptr CFq -> Ptr CFqCtx -> IO ()++foreign import ccall "fq.h &fq_clear"+ p_fq_clear :: FunPtr (Ptr CFq -> Ptr CFqCtx -> IO ())++-- | /_fq_sparse_reduce/ /R/ /lenR/ /ctx/ +-- +-- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of+-- @ctx@.+foreign import ccall "fq.h _fq_sparse_reduce"+ _fq_sparse_reduce :: Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_dense_reduce/ /R/ /lenR/ /ctx/ +-- +-- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of+-- @ctx@ using Newton division.+foreign import ccall "fq.h _fq_dense_reduce"+ _fq_dense_reduce :: Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_reduce/ /r/ /lenR/ /ctx/ +-- +-- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of+-- @ctx@. Does either sparse or dense reduction based on+-- @ctx->sparse_modulus@.+foreign import ccall "fq.h _fq_reduce"+ _fq_reduce :: Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_reduce/ /rop/ /ctx/ +-- +-- Reduces the polynomial @rop@ as an element of+-- \(\mathbf{F}_p[X] / (f(X))\).+foreign import ccall "fq.h fq_reduce"+ fq_reduce :: Ptr CFq -> Ptr CFqCtx -> IO ()++-- Basic arithmetic ------------------------------------------------------------++-- | /fq_add/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the sum of @op1@ and @op2@.+foreign import ccall "fq.h fq_add"+ fq_add :: Ptr CFq -> Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_sub/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the difference of @op1@ and @op2@.+foreign import ccall "fq.h fq_sub"+ fq_sub :: Ptr CFq -> Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_sub_one/ /rop/ /op1/ /ctx/ +-- +-- Sets @rop@ to the difference of @op1@ and \(1\).+foreign import ccall "fq.h fq_sub_one"+ fq_sub_one :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_neg/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the negative of @op@.+foreign import ccall "fq.h fq_neg"+ fq_neg :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_mul/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the product of @op1@ and @op2@, reducing the output in the+-- given context.+foreign import ccall "fq.h fq_mul"+ fq_mul :: Ptr CFq -> Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_mul_fmpz/ /rop/ /op/ /x/ /ctx/ +-- +-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the+-- given context.+foreign import ccall "fq.h fq_mul_fmpz"+ fq_mul_fmpz :: Ptr CFq -> Ptr CFq -> Ptr CFmpz -> Ptr CFqCtx -> IO ()++-- | /fq_mul_si/ /rop/ /op/ /x/ /ctx/ +-- +-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the+-- given context.+foreign import ccall "fq.h fq_mul_si"+ fq_mul_si :: Ptr CFq -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_mul_ui/ /rop/ /op/ /x/ /ctx/ +-- +-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the+-- given context.+foreign import ccall "fq.h fq_mul_ui"+ fq_mul_ui :: Ptr CFq -> Ptr CFq -> CULong -> Ptr CFqCtx -> IO ()++-- | /fq_sqr/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the square of @op@, reducing the output in the given+-- context.+foreign import ccall "fq.h fq_sqr"+ fq_sqr :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_div/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the quotient of @op1@ and @op2@, reducing the output in+-- the given context.+foreign import ccall "fq.h fq_div"+ fq_div :: Ptr CFq -> Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /_fq_inv/ /rop/ /op/ /len/ /ctx/ +-- +-- Sets @(rop, d)@ to the inverse of the non-zero element @(op, len)@.+foreign import ccall "fq.h _fq_inv"+ _fq_inv :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_inv/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the inverse of the non-zero element @op@.+foreign import ccall "fq.h fq_inv"+ fq_inv :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_gcdinv/ /f/ /inv/ /op/ /ctx/ +-- +-- Sets @inv@ to be the inverse of @op@ modulo the modulus of @ctx@. If+-- @op@ is not invertible, then @f@ is set to a factor of the modulus;+-- otherwise, it is set to one.+foreign import ccall "fq.h fq_gcdinv"+ fq_gcdinv :: Ptr CFq -> Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /_fq_pow/ /rop/ /op/ /len/ /e/ /ctx/ +-- +-- Sets @(rop, 2*d-1)@ to @(op,len)@ raised to the power \(e\), reduced+-- modulo \(f(X)\), the modulus of @ctx@.+-- +-- Assumes that \(e \geq 0\) and that @len@ is positive and at most \(d\).+-- +-- Although we require that @rop@ provides space for \(2d - 1\)+-- coefficients, the output will be reduced modulo \(f(X)\), which is a+-- polynomial of degree \(d\).+-- +-- Does not support aliasing.+foreign import ccall "fq.h _fq_pow"+ _fq_pow :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFqCtx -> IO ()++-- | /fq_pow/ /rop/ /op/ /e/ /ctx/ +-- +-- Sets @rop@ the @op@ raised to the power \(e\).+-- +-- Currently assumes that \(e \geq 0\).+-- +-- Note that for any input @op@, @rop@ is set to \(1\) whenever \(e = 0\).+foreign import ccall "fq.h fq_pow"+ fq_pow :: Ptr CFq -> Ptr CFq -> Ptr CFmpz -> Ptr CFqCtx -> IO ()++-- | /fq_pow_ui/ /rop/ /op/ /e/ /ctx/ +-- +-- Sets @rop@ the @op@ raised to the power \(e\).+-- +-- Currently assumes that \(e \geq 0\).+-- +-- Note that for any input @op@, @rop@ is set to \(1\) whenever \(e = 0\).+foreign import ccall "fq.h fq_pow_ui"+ fq_pow_ui :: Ptr CFq -> Ptr CFq -> CULong -> Ptr CFqCtx -> IO ()++-- Roots -----------------------------------------------------------------------++-- | /fq_sqrt/ /rop/ /op1/ /ctx/ +-- +-- Sets @rop@ to the square root of @op1@ if it is a square, and return+-- \(1\), otherwise return \(0\).+foreign import ccall "fq.h fq_sqrt"+ fq_sqrt :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO CInt++-- | /fq_pth_root/ /rop/ /op1/ /ctx/ +-- +-- Sets @rop@ to a \(p^{th}\) root root of @op1@. Currently, this computes+-- the root by raising @op1@ to \(p^{d-1}\) where \(d\) is the degree of+-- the extension.+foreign import ccall "fq.h fq_pth_root"+ fq_pth_root :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_is_square/ /op/ /ctx/ +-- +-- Return @1@ if @op@ is a square.+foreign import ccall "fq.h fq_is_square"+ fq_is_square :: Ptr CFq -> Ptr CFqCtx -> IO CInt++-- Output ----------------------------------------------------------------------++-- | /fq_fprint_pretty/ /file/ /op/ /ctx/ +-- +-- Prints a pretty representation of @op@ to @file@.+-- +-- In the current implementation, always returns \(1\). The return code is+-- part of the function\'s signature to allow for a later implementation to+-- return the number of characters printed or a non-positive error code.+foreign import ccall "fq.h fq_fprint_pretty"+ fq_fprint_pretty :: Ptr CFile -> Ptr CFq -> Ptr CFqCtx -> IO CInt++-- | /fq_print_pretty/ /op/ /ctx/ +-- +-- Prints a pretty representation of @op@ to @stdout@.+-- +-- In the current implementation, always returns \(1\). The return code is+-- part of the function\'s signature to allow for a later implementation to+-- return the number of characters printed or a non-positive error code.+fq_print_pretty :: Ptr CFq -> Ptr CFqCtx -> IO CInt+fq_print_pretty x ctx = printCStr (flip fq_get_str_pretty ctx) x+ +-- | /fq_fprint/ /file/ /op/ /ctx/ +-- +-- Prints a representation of @op@ to @file@.+-- +-- For further details on the representation used, see+-- @fmpz_mod_poly_fprint@.+foreign import ccall "fq.h fq_fprint"+ fq_fprint :: Ptr CFile -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_print/ /op/ /ctx/ +-- +-- Prints a representation of @op@ to @stdout@.+-- +-- For further details on the representation used, see+-- @fmpz_mod_poly_print@.+fq_print :: Ptr CFq -> Ptr CFqCtx -> IO CInt+fq_print x ctx = printCStr (flip fq_get_str ctx) x+ +-- | /fq_get_str/ /op/ /ctx/ +-- +-- Returns the plain FLINT string representation of the element @op@.+foreign import ccall "fq.h fq_get_str"+ fq_get_str :: Ptr CFq -> Ptr CFqCtx -> IO CString++-- | /fq_get_str_pretty/ /op/ /ctx/ +-- +-- Returns a pretty representation of the element @op@ using the+-- null-terminated string @x@ as the variable name.+foreign import ccall "fq.h fq_get_str_pretty"+ fq_get_str_pretty :: Ptr CFq -> Ptr CFqCtx -> IO CString++-- Randomisation ---------------------------------------------------------------++-- | /fq_randtest/ /rop/ /state/ /ctx/ +-- +-- Generates a random element of \(\mathbf{F}_q\).+foreign import ccall "fq.h fq_randtest"+ fq_randtest :: Ptr CFq -> Ptr CFRandState -> Ptr CFqCtx -> IO ()++-- | /fq_randtest_not_zero/ /rop/ /state/ /ctx/ +-- +-- Generates a random non-zero element of \(\mathbf{F}_q\).+foreign import ccall "fq.h fq_randtest_not_zero"+ fq_randtest_not_zero :: Ptr CFq -> Ptr CFRandState -> Ptr CFqCtx -> IO ()++-- | /fq_randtest_dense/ /rop/ /state/ /ctx/ +-- +-- Generates a random element of \(\mathbf{F}_q\) which has an underlying+-- polynomial with dense coefficients.+foreign import ccall "fq.h fq_randtest_dense"+ fq_randtest_dense :: Ptr CFq -> Ptr CFRandState -> Ptr CFqCtx -> IO ()++-- | /fq_rand/ /rop/ /state/ /ctx/ +-- +-- Generates a high quality random element of \(\mathbf{F}_q\).+foreign import ccall "fq.h fq_rand"+ fq_rand :: Ptr CFq -> Ptr CFRandState -> Ptr CFqCtx -> IO ()++-- | /fq_rand_not_zero/ /rop/ /state/ /ctx/ +-- +-- Generates a high quality non-zero random element of \(\mathbf{F}_q\).+foreign import ccall "fq.h fq_rand_not_zero"+ fq_rand_not_zero :: Ptr CFq -> Ptr CFRandState -> Ptr CFqCtx -> IO ()++-- Assignments and conversions -------------------------------------------------++-- | /fq_set/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to @op@.+foreign import ccall "fq.h fq_set"+ fq_set :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_set_si/ /rop/ /x/ /ctx/ +-- +-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).+foreign import ccall "fq.h fq_set_si"+ fq_set_si :: Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_set_ui/ /rop/ /x/ /ctx/ +-- +-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).+foreign import ccall "fq.h fq_set_ui"+ fq_set_ui :: Ptr CFq -> CULong -> Ptr CFqCtx -> IO ()++-- | /fq_set_fmpz/ /rop/ /x/ /ctx/ +-- +-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).+foreign import ccall "fq.h fq_set_fmpz"+ fq_set_fmpz :: Ptr CFq -> Ptr CFmpz -> Ptr CFqCtx -> IO ()++-- | /fq_swap/ /op1/ /op2/ /ctx/ +-- +-- Swaps the two elements @op1@ and @op2@.+foreign import ccall "fq.h fq_swap"+ fq_swap :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_zero/ /rop/ /ctx/ +-- +-- Sets @rop@ to zero.+foreign import ccall "fq.h fq_zero"+ fq_zero :: Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_one/ /rop/ /ctx/ +-- +-- Sets @rop@ to one, reduced in the given context.+foreign import ccall "fq.h fq_one"+ fq_one :: Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_gen/ /rop/ /ctx/ +-- +-- Sets @rop@ to a generator for the finite field. There is no guarantee+-- this is a multiplicative generator of the finite field.+foreign import ccall "fq.h fq_gen"+ fq_gen :: Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_get_fmpz/ /rop/ /op/ /ctx/ +-- +-- If @op@ has a lift to the integers, return \(1\) and set @rop@ to the+-- lift in \([0,p)\). Otherwise, return \(0\) and leave \(rop\) undefined.+foreign import ccall "fq.h fq_get_fmpz"+ fq_get_fmpz :: Ptr CFmpz -> Ptr CFq -> Ptr CFqCtx -> IO CInt++foreign import ccall "fq.h fq_get_fmpz_poly"+ fq_get_fmpz_poly :: Ptr CFmpzPoly -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_get_fmpz_mod_poly/ /a/ /b/ /ctx/ +-- +-- Set @a@ to a representative of @b@ in @ctx@. The representatives are+-- taken in \((\mathbb{Z}/p\mathbb{Z})[x]/h(x)\) where \(h(x)\) is the+-- defining polynomial in @ctx@.+foreign import ccall "fq.h fq_get_fmpz_mod_poly"+ fq_get_fmpz_mod_poly :: Ptr CFmpzModPoly -> Ptr CFq -> Ptr CFqCtx -> IO ()++foreign import ccall "fq.h fq_set_fmpz_poly"+ fq_set_fmpz_poly :: Ptr CFq -> Ptr CFmpzPoly -> Ptr CFqCtx -> IO ()++-- | /fq_set_fmpz_mod_poly/ /a/ /b/ /ctx/ +-- +-- Set @a@ to the element in @ctx@ with representative @b@. The+-- representatives are taken in \((\mathbb{Z}/p\mathbb{Z})[x]/h(x)\) where+-- \(h(x)\) is the defining polynomial in @ctx@.+foreign import ccall "fq.h fq_set_fmpz_mod_poly"+ fq_set_fmpz_mod_poly :: Ptr CFq -> Ptr CFmpzModPoly -> Ptr CFqCtx -> IO ()++-- | /fq_get_fmpz_mod_mat/ /col/ /a/ /ctx/ +-- +-- Convert @a@ to a column vector of length @degree(ctx)@.+foreign import ccall "fq.h fq_get_fmpz_mod_mat"+ fq_get_fmpz_mod_mat :: Ptr CFmpzModMat -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_set_fmpz_mod_mat/ /a/ /col/ /ctx/ +-- +-- Convert a column vector @col@ of length @degree(ctx)@ to an element of+-- @ctx@.+foreign import ccall "fq.h fq_set_fmpz_mod_mat"+ fq_set_fmpz_mod_mat :: Ptr CFq -> Ptr CFmpzModMat -> Ptr CFqCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fq_is_zero/ /op/ /ctx/ +-- +-- Returns whether @op@ is equal to zero.+foreign import ccall "fq.h fq_is_zero"+ fq_is_zero :: Ptr CFq -> Ptr CFqCtx -> IO CInt++-- | /fq_is_one/ /op/ /ctx/ +-- +-- Returns whether @op@ is equal to one.+foreign import ccall "fq.h fq_is_one"+ fq_is_one :: Ptr CFq -> Ptr CFqCtx -> IO CInt++-- | /fq_equal/ /op1/ /op2/ /ctx/ +-- +-- Returns whether @op1@ and @op2@ are equal.+foreign import ccall "fq.h fq_equal"+ fq_equal :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO CInt++-- | /fq_is_invertible/ /op/ /ctx/ +-- +-- Returns whether @op@ is an invertible element.+foreign import ccall "fq.h fq_is_invertible"+ fq_is_invertible :: Ptr CFq -> Ptr CFqCtx -> IO CInt++-- | /fq_is_invertible_f/ /f/ /op/ /ctx/ +-- +-- Returns whether @op@ is an invertible element. If it is not, then @f@ is+-- set of a factor of the modulus.+foreign import ccall "fq.h fq_is_invertible_f"+ fq_is_invertible_f :: Ptr CFq -> Ptr CFq -> Ptr CFqCtx -> IO CInt++-- Special functions -----------------------------------------------------------++-- | /_fq_trace/ /rop/ /op/ /len/ /ctx/ +-- +-- Sets @rop@ to the trace of the non-zero element @(op, len)@ in+-- \(\mathbf{F}_{q}\).+foreign import ccall "fq.h _fq_trace"+ _fq_trace :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_trace/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the trace of @op@.+-- +-- For an element \(a \in \mathbf{F}_q\), multiplication by \(a\) defines a+-- \(\mathbf{F}_p\)-linear map on \(\mathbf{F}_q\). We define the trace of+-- \(a\) as the trace of this map. Equivalently, if \(\Sigma\) generates+-- \(\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)\) then the trace of+-- \(a\) is equal to \(\sum_{i=0}^{d-1} \Sigma^i (a)\), where \(d =+-- \log_{p} q\).+foreign import ccall "fq.h fq_trace"+ fq_trace :: Ptr CFmpz -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /_fq_norm/ /rop/ /op/ /len/ /ctx/ +-- +-- Sets @rop@ to the norm of the non-zero element @(op, len)@ in+-- \(\mathbf{F}_{q}\).+foreign import ccall "fq.h _fq_norm"+ _fq_norm :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_norm/ /rop/ /op/ /ctx/ +-- +-- Computes the norm of @op@.+-- +-- For an element \(a \in \mathbf{F}_q\), multiplication by \(a\) defines a+-- \(\mathbf{F}_p\)-linear map on \(\mathbf{F}_q\). We define the norm of+-- \(a\) as the determinant of this map. Equivalently, if \(\Sigma\)+-- generates \(\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)\) then the+-- trace of \(a\) is equal to \(\prod_{i=0}^{d-1} \Sigma^i (a)\), where+-- \(d = \text{dim}_{\mathbf{F}_p}(\mathbf{F}_q)\).+-- +-- Algorithm selection is automatic depending on the input.+foreign import ccall "fq.h fq_norm"+ fq_norm :: Ptr CFmpz -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /_fq_frobenius/ /rop/ /op/ /len/ /e/ /ctx/ +-- +-- Sets @(rop, 2d-1)@ to the image of @(op, len)@ under the Frobenius+-- operator raised to the e-th power, assuming that neither @op@ nor @e@+-- are zero.+foreign import ccall "fq.h _fq_frobenius"+ _fq_frobenius :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_frobenius/ /rop/ /op/ /e/ /ctx/ +-- +-- Evaluates the homomorphism \(\Sigma^e\) at @op@.+-- +-- Recall that \(\mathbf{F}_q / \mathbf{F}_p\) is Galois with Galois group+-- \(\langle \sigma \rangle\), which is also isomorphic to+-- \(\mathbf{Z}/d\mathbf{Z}\), where+-- \(\sigma \in \operatorname{Gal}(\mathbf{F}_q/\mathbf{F}_p)\) is the+-- Frobenius element \(\sigma \colon x \mapsto x^p\).+foreign import ccall "fq.h fq_frobenius"+ fq_frobenius :: Ptr CFq -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_multiplicative_order/ /ord/ /op/ /ctx/ +-- +-- Computes the order of @op@ as an element of the multiplicative group of+-- @ctx@.+-- +-- Returns 0 if @op@ is 0, otherwise it returns 1 if @op@ is a generator of+-- the multiplicative group, and -1 if it is not.+-- +-- This function can also be used to check primitivity of a generator of a+-- finite field whose defining polynomial is not primitive.+foreign import ccall "fq.h fq_multiplicative_order"+ fq_multiplicative_order :: Ptr CFmpz -> Ptr CFq -> Ptr CFqCtx -> IO CInt++-- | /fq_is_primitive/ /op/ /ctx/ +-- +-- Returns whether @op@ is primitive, i.e., whether it is a generator of+-- the multiplicative group of @ctx@.+foreign import ccall "fq.h fq_is_primitive"+ fq_is_primitive :: Ptr CFq -> Ptr CFqCtx -> IO CInt++-- Bit packing -----------------------------------------------------------------++-- | /fq_bit_pack/ /f/ /op/ /bit_size/ /ctx/ +-- +-- Packs @op@ into bitfields of size @bit_size@, writing the result to @f@.+foreign import ccall "fq.h fq_bit_pack"+ fq_bit_pack :: Ptr CFmpz -> Ptr CFq -> CFBitCnt -> Ptr CFqCtx -> IO ()++-- | /fq_bit_unpack/ /rop/ /f/ /bit_size/ /ctx/ +-- +-- Unpacks into @rop@ the element with coefficients packed into fields of+-- size @bit_size@ as represented by the integer @f@.+foreign import ccall "fq.h fq_bit_unpack"+ fq_bit_unpack :: Ptr CFq -> Ptr CFmpz -> CFBitCnt -> Ptr CFqCtx -> IO ()+
+ src/Data/Number/Flint/Fq/Mat.hs view
@@ -0,0 +1,16 @@+{-| +module : Data.Number.Flint.Fq.Mat+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de++An @FqMat@ represents an matrix over a finite field.+This module implements operations on matrices over a finite field.++-}++module Data.Number.Flint.Fq.Mat (+ module Data.Number.Flint.Fq.Mat.FFI,+) where++import Data.Number.Flint.Fq.Mat.FFI
+ src/Data/Number/Flint/Fq/Mat/FFI.hsc view
@@ -0,0 +1,773 @@+{-|+module : Data.Number.Flint.Fq.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Mat.FFI (+ -- * Matrices over finite fields+ FqMat (..)+ , CFqMat (..)+ , newFqMat+ , withFqMat+ , withNewFqMat+ -- * Memory management+ , fq_mat_init+ , fq_mat_init_set+ , fq_mat_clear+ , fq_mat_set+ -- * Basic properties and manipulation+ , fq_mat_entry+ , fq_mat_entry_set+ , fq_mat_nrows+ , fq_mat_ncols+ , fq_mat_swap+ , fq_mat_swap_entrywise+ , fq_mat_zero+ , fq_mat_one+ , fq_mat_swap_rows+ , fq_mat_swap_cols+ , fq_mat_invert_rows+ , fq_mat_invert_cols+ -- * Conversions+ , fq_mat_set_nmod_mat+ , fq_mat_set_fmpz_mod_mat+ -- * Concatenate+ , fq_mat_concat_vertical+ , fq_mat_concat_horizontal+ -- * Printing+ , fq_mat_print_pretty+ , fq_mat_fprint_pretty+ , fq_mat_print+ , fq_mat_fprint+ -- * Window+ , fq_mat_window_init+ , fq_mat_window_clear+ -- * Random matrix generation+ , fq_mat_randtest+ , fq_mat_randpermdiag+ , fq_mat_randrank+ , fq_mat_randops+ , fq_mat_randtril+ , fq_mat_randtriu+ -- * Comparison+ , fq_mat_equal+ , fq_mat_is_zero+ , fq_mat_is_one+ , fq_mat_is_empty+ , fq_mat_is_square+ -- * Addition and subtraction+ , fq_mat_add+ , fq_mat_sub+ , fq_mat_neg+ -- * Matrix multiplication+ , fq_mat_mul+ , fq_mat_mul_classical+ , fq_mat_mul_KS+ , fq_mat_submul+ , fq_mat_mul_vec+ , fq_mat_mul_vec_ptr+ , fq_mat_vec_mul+ , fq_mat_vec_mul_ptr+ -- * Inverse+ , fq_mat_inv+ -- * LU decomposition+ , fq_mat_lu+ , fq_mat_lu_classical+ , fq_mat_lu_recursive+ -- * Reduced row echelon form+ , fq_mat_rref+ , fq_mat_reduce_row+ -- * Triangular solving+ , fq_mat_solve_tril+ , fq_mat_solve_tril_classical+ , fq_mat_solve_tril_recursive+ , fq_mat_solve_triu+ , fq_mat_solve_triu_classical+ , fq_mat_solve_triu_recursive+ -- * Solving+ , fq_mat_solve+ , fq_mat_can_solve+ -- * Transforms+ , fq_mat_similarity+ -- * Characteristic polynomial+ , fq_mat_charpoly_danilevsky+ , fq_mat_charpoly+ -- * Minimal polynomial+ , fq_mat_minpoly+) where++-- Matrices over finite fields -------------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr +import Foreign.Storable+import Foreign.Marshal++import Data.Number.Flint.Flint++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Mod.Mat++import Data.Number.Flint.Fmpq++import Data.Number.Flint.NMod.Mat++import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.Types++import Data.Number.Flint.Support.D.Mat++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/fmpz_mat.h>+#include <flint/fmpz_poly.h>+#include <flint/fmpq.h>+#include <flint/fq.h>+#include <flint/fq_mat.h>++-- fq_mat_t --------------------------------------------------------------------++instance Storable CFqMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_mat_t}+ peek ptr = CFqMat+ <$> #{peek fq_mat_struct, entries} ptr+ <*> #{peek fq_mat_struct, r } ptr+ <*> #{peek fq_mat_struct, c } ptr+ <*> #{peek fq_mat_struct, rows } ptr+ poke = undefined++newFqMat rows cols ctx@(FqCtx fctx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqCtx ctx $ \ctx -> do+ fq_mat_init x rows cols ctx+ addForeignPtrFinalizerEnv p_fq_mat_clear x fctx + return $ FqMat x++{-# INLINE withFqMat #-}+withFqMat (FqMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqMat x,)++withNewFqMat rows cals ctx f = do+ x <- newFqMat rows cals ctx+ withFqMat x f+ +-- Memory management -----------------------------------------------------------++-- | /fq_mat_init/ /mat/ /rows/ /cols/ /ctx/ +--+-- Initialises @mat@ to a @rows@-by-@cols@ matrix with coefficients in+-- \(\mathbf{F}_{q}\) given by @ctx@. All elements are set to zero.+foreign import ccall "fq_mat.h fq_mat_init"+ fq_mat_init :: Ptr CFqMat -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_mat_init_set/ /mat/ /src/ /ctx/ +--+-- Initialises @mat@ and sets its dimensions and elements to those of+-- @src@.+foreign import ccall "fq_mat.h fq_mat_init_set"+ fq_mat_init_set :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_clear/ /mat/ /ctx/ +--+-- Clears the matrix and releases any memory it used. The matrix cannot be+-- used again until it is initialised. This function must be called exactly+-- once when finished using an @fq_mat_t@ object.+foreign import ccall "fq_mat.h fq_mat_clear"+ fq_mat_clear :: Ptr CFqMat -> Ptr CFqCtx -> IO ()++foreign import ccall "fq_mat.h &fq_mat_clear"+ p_fq_mat_clear :: FunPtr (Ptr CFqMat -> Ptr CFqCtx -> IO ())++-- | /fq_mat_set/ /mat/ /src/ /ctx/ +--+-- Sets @mat@ to a copy of @src@. It is assumed that @mat@ and @src@ have+-- identical dimensions.+foreign import ccall "fq_mat.h fq_mat_set"+ fq_mat_set :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- Basic properties and manipulation -------------------------------------------++-- | /fq_mat_entry/ /mat/ /i/ /j/ +--+-- Directly accesses the entry in @mat@ in row \(i\) and column \(j\),+-- indexed from zero. No bounds checking is performed.+fq_mat_entry :: Ptr CFqMat -> CLong -> CLong -> IO (Ptr CFq)+fq_mat_entry mat i j = do+ CFqMat entries r c rows <- peek mat+ return $ entries `advancePtr` (fromIntegral (i*c + j))++-- | /fq_mat_entry_set/ /mat/ /i/ /j/ /x/ /ctx/ +--+-- Sets the entry in @mat@ in row \(i\) and column \(j\) to @x@.+foreign import ccall "fq_mat.h fq_mat_entry_set"+ fq_mat_entry_set :: Ptr CFqMat -> CLong -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_mat_nrows/ /mat/ /ctx/ +--+-- Returns the number of rows in @mat@.+foreign import ccall "fq_mat.h fq_mat_nrows"+ fq_mat_nrows :: Ptr CFqMat -> Ptr CFqCtx -> IO CLong++-- | /fq_mat_ncols/ /mat/ /ctx/ +--+-- Returns the number of columns in @mat@.+foreign import ccall "fq_mat.h fq_mat_ncols"+ fq_mat_ncols :: Ptr CFqMat -> Ptr CFqCtx -> IO CLong++-- | /fq_mat_swap/ /mat1/ /mat2/ /ctx/ +--+-- Swaps two matrices. The dimensions of @mat1@ and @mat2@ are allowed to+-- be different.+foreign import ccall "fq_mat.h fq_mat_swap"+ fq_mat_swap :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_swap_entrywise/ /mat1/ /mat2/ +--+-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "fq_mat.h fq_mat_swap_entrywise"+ fq_mat_swap_entrywise :: Ptr CFqMat -> Ptr CFqMat -> IO ()++-- | /fq_mat_zero/ /mat/ /ctx/ +--+-- Sets all entries of @mat@ to 0.+foreign import ccall "fq_mat.h fq_mat_zero"+ fq_mat_zero :: Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_one/ /mat/ /ctx/ +--+-- Sets all the diagonal entries of @mat@ to 1 and all other entries to 0.+foreign import ccall "fq_mat.h fq_mat_one"+ fq_mat_one :: Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_swap_rows/ /mat/ /perm/ /r/ /s/ +--+-- Swaps rows @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the rows will also be applied to @perm@.+foreign import ccall "fq_mat.h fq_mat_swap_rows"+ fq_mat_swap_rows :: Ptr CFqMat -> Ptr CLong -> CLong -> CLong -> IO ()++-- | /fq_mat_swap_cols/ /mat/ /perm/ /r/ /s/ +--+-- Swaps columns @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the columns will also be applied to @perm@.+foreign import ccall "fq_mat.h fq_mat_swap_cols"+ fq_mat_swap_cols :: Ptr CFqMat -> Ptr CLong -> CLong -> CLong -> IO ()++-- | /fq_mat_invert_rows/ /mat/ /perm/ +--+-- Swaps rows @i@ and @r - i@ of @mat@ for @0 \<= i \< r\/2@, where @r@ is+-- the number of rows of @mat@. If @perm@ is non-@NULL@, the permutation of+-- the rows will also be applied to @perm@.+foreign import ccall "fq_mat.h fq_mat_invert_rows"+ fq_mat_invert_rows :: Ptr CFqMat -> Ptr CLong -> IO ()++-- | /fq_mat_invert_cols/ /mat/ /perm/ +--+-- Swaps columns @i@ and @c - i@ of @mat@ for @0 \<= i \< c\/2@, where @c@+-- is the number of columns of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the columns will also be applied to @perm@.+foreign import ccall "fq_mat.h fq_mat_invert_cols"+ fq_mat_invert_cols :: Ptr CFqMat -> Ptr CLong -> IO ()++-- Conversions -----------------------------------------------------------------++-- | /fq_mat_set_nmod_mat/ /mat1/ /mat2/ /ctx/ +--+-- Sets the matrix @mat1@ to the matrix @mat2@.+foreign import ccall "fq_mat.h fq_mat_set_nmod_mat"+ fq_mat_set_nmod_mat :: Ptr CFqMat -> Ptr CNModMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_set_fmpz_mod_mat/ /mat1/ /mat2/ /ctx/ +--+-- Sets the matrix @mat1@ to the matrix @mat2@.+foreign import ccall "fq_mat.h fq_mat_set_fmpz_mod_mat"+ fq_mat_set_fmpz_mod_mat :: Ptr CFqMat -> Ptr CFmpzModMat -> Ptr CFqCtx -> IO ()++-- Concatenate -----------------------------------------------------------------++-- | /fq_mat_concat_vertical/ /res/ /mat1/ /mat2/ /ctx/ +--+-- Sets @res@ to vertical concatenation of (@mat1@, @mat2@) in that order.+-- Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ : \(k \times n\),+-- @res@ : \((m + k) \times n\).+foreign import ccall "fq_mat.h fq_mat_concat_vertical"+ fq_mat_concat_vertical :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_concat_horizontal/ /res/ /mat1/ /mat2/ /ctx/ +--+-- Sets @res@ to horizontal concatenation of (@mat1@, @mat2@) in that+-- order. Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ :+-- \(m \times k\), @res@ : \(m \times (n + k)\).+foreign import ccall "fq_mat.h fq_mat_concat_horizontal"+ fq_mat_concat_horizontal :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- Printing --------------------------------------------------------------------++-- | /fq_mat_print_pretty/ /mat/ /ctx/ +--+-- Pretty-prints @mat@ to @stdout@. A header is printed followed by the+-- rows enclosed in brackets.+foreign import ccall "fq_mat.h fq_mat_print_pretty"+ fq_mat_print_pretty :: Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_fprint_pretty/ /file/ /mat/ /ctx/ +--+-- Pretty-prints @mat@ to @file@. A header is printed followed by the rows+-- enclosed in brackets.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_mat.h fq_mat_fprint_pretty"+ fq_mat_fprint_pretty :: Ptr CFile -> Ptr CFqMat -> Ptr CFqCtx -> IO CInt++-- | /fq_mat_print/ /mat/ /ctx/ +--+-- Prints @mat@ to @stdout@. A header is printed followed by the rows+-- enclosed in brackets.+foreign import ccall "fq_mat.h fq_mat_print"+ fq_mat_print :: Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_fprint/ /file/ /mat/ /ctx/ +--+-- Prints @mat@ to @file@. A header is printed followed by the rows+-- enclosed in brackets.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_mat.h fq_mat_fprint"+ fq_mat_fprint :: Ptr CFile -> Ptr CFqMat -> Ptr CFqCtx -> IO CInt++-- Window ----------------------------------------------------------------------++-- | /fq_mat_window_init/ /window/ /mat/ /r1/ /c1/ /r2/ /c2/ /ctx/ +--+-- Initializes the matrix @window@ to be an @r2 - r1@ by @c2 - c1@+-- submatrix of @mat@ whose @(0,0)@ entry is the @(r1, c1)@ entry of @mat@.+-- The memory for the elements of @window@ is shared with @mat@.+foreign import ccall "fq_mat.h fq_mat_window_init"+ fq_mat_window_init :: Ptr CFqMat -> Ptr CFqMat -> CLong -> CLong -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_mat_window_clear/ /window/ /ctx/ +--+-- Clears the matrix @window@ and releases any memory that it uses. Note+-- that the memory to the underlying matrix that @window@ points to is not+-- freed.+foreign import ccall "fq_mat.h fq_mat_window_clear"+ fq_mat_window_clear :: Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- Random matrix generation ----------------------------------------------------++-- | /fq_mat_randtest/ /mat/ /state/ /ctx/ +--+-- Sets the elements of @mat@ to random elements of \(\mathbf{F}_{q}\),+-- given by @ctx@.+foreign import ccall "fq_mat.h fq_mat_randtest"+ fq_mat_randtest :: Ptr CFqMat -> Ptr CFRandState -> Ptr CFqCtx -> IO ()++-- | /fq_mat_randpermdiag/ /mat/ /state/ /diag/ /n/ /ctx/ +--+-- Sets @mat@ to a random permutation of the diagonal matrix with \(n\)+-- leading entries given by the vector @diag@. It is assumed that the main+-- diagonal of @mat@ has room for at least \(n\) entries.+-- +-- Returns \(0\) or \(1\), depending on whether the permutation is even or+-- odd respectively.+foreign import ccall "fq_mat.h fq_mat_randpermdiag"+ fq_mat_randpermdiag :: Ptr CFqMat -> Ptr CFRandState -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO CInt++-- | /fq_mat_randrank/ /mat/ /state/ /rank/ /ctx/ +--+-- Sets @mat@ to a random sparse matrix with the given rank, having exactly+-- as many non-zero elements as the rank, with the non-zero elements being+-- uniformly random elements of \(\mathbf{F}_{q}\).+-- +-- The matrix can be transformed into a dense matrix with unchanged rank by+-- subsequently calling @fq_mat_randops@.+foreign import ccall "fq_mat.h fq_mat_randrank"+ fq_mat_randrank :: Ptr CFqMat -> Ptr CFRandState -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_mat_randops/ /mat/ /count/ /state/ /ctx/ +--+-- Randomises @mat@ by performing elementary row or column operations. More+-- precisely, at most @count@ random additions or subtractions of distinct+-- rows and columns will be performed. This leaves the rank (and for square+-- matrices, determinant) unchanged.+foreign import ccall "fq_mat.h fq_mat_randops"+ fq_mat_randops :: Ptr CFqMat -> CLong -> Ptr CFRandState -> Ptr CFqCtx -> IO ()++-- | /fq_mat_randtril/ /mat/ /state/ /unit/ /ctx/ +--+-- Sets @mat@ to a random lower triangular matrix. If @unit@ is 1, it will+-- have ones on the main diagonal, otherwise it will have random nonzero+-- entries on the main diagonal.+foreign import ccall "fq_mat.h fq_mat_randtril"+ fq_mat_randtril :: Ptr CFqMat -> Ptr CFRandState -> CInt -> Ptr CFqCtx -> IO ()++-- | /fq_mat_randtriu/ /mat/ /state/ /unit/ /ctx/ +--+-- Sets @mat@ to a random upper triangular matrix. If @unit@ is 1, it will+-- have ones on the main diagonal, otherwise it will have random nonzero+-- entries on the main diagonal.+foreign import ccall "fq_mat.h fq_mat_randtriu"+ fq_mat_randtriu :: Ptr CFqMat -> Ptr CFRandState -> CInt -> Ptr CFqCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fq_mat_equal/ /mat1/ /mat2/ /ctx/ +--+-- Returns nonzero if mat1 and mat2 have the same dimensions and elements,+-- and zero otherwise.+foreign import ccall "fq_mat.h fq_mat_equal"+ fq_mat_equal :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO CInt++-- | /fq_mat_is_zero/ /mat/ /ctx/ +--+-- Returns a non-zero value if all entries of @mat@ are zero, and otherwise+-- returns zero.+foreign import ccall "fq_mat.h fq_mat_is_zero"+ fq_mat_is_zero :: Ptr CFqMat -> Ptr CFqCtx -> IO CInt++-- | /fq_mat_is_one/ /mat/ /ctx/ +--+-- Returns a non-zero value if all entries @mat@ are zero except the+-- diagonal entries which must be one, otherwise returns zero..+foreign import ccall "fq_mat.h fq_mat_is_one"+ fq_mat_is_one :: Ptr CFqMat -> Ptr CFqCtx -> IO CInt++-- | /fq_mat_is_empty/ /mat/ /ctx/ +--+-- Returns a non-zero value if the number of rows or the number of columns+-- in @mat@ is zero, and otherwise returns zero.+foreign import ccall "fq_mat.h fq_mat_is_empty"+ fq_mat_is_empty :: Ptr CFqMat -> Ptr CFqCtx -> IO CInt++-- | /fq_mat_is_square/ /mat/ /ctx/ +--+-- Returns a non-zero value if the number of rows is equal to the number of+-- columns in @mat@, and otherwise returns zero.+foreign import ccall "fq_mat.h fq_mat_is_square"+ fq_mat_is_square :: Ptr CFqMat -> Ptr CFqCtx -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /fq_mat_add/ /C/ /A/ /B/ /ctx/ +--+-- Computes \(C = A + B\). Dimensions must be identical.+foreign import ccall "fq_mat.h fq_mat_add"+ fq_mat_add :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_sub/ /C/ /A/ /B/ /ctx/ +--+-- Computes \(C = A - B\). Dimensions must be identical.+foreign import ccall "fq_mat.h fq_mat_sub"+ fq_mat_sub :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_neg/ /A/ /B/ /ctx/ +--+-- Sets \(B = -A\). Dimensions must be identical.+foreign import ccall "fq_mat.h fq_mat_neg"+ fq_mat_neg :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- Matrix multiplication -------------------------------------------------------++-- | /fq_mat_mul/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. Aliasing is allowed. This function automatically chooses+-- between classical and KS multiplication.+foreign import ccall "fq_mat.h fq_mat_mul"+ fq_mat_mul :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_mul_classical/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. \(C\) is not allowed to be aliased with \(A\) or \(B\).+-- Uses classical matrix multiplication.+foreign import ccall "fq_mat.h fq_mat_mul_classical"+ fq_mat_mul_classical :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_mul_KS/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. \(C\) is not allowed to be aliased with \(A\) or \(B\).+-- Uses Kronecker substitution to perform the multiplication over the+-- integers.+foreign import ccall "fq_mat.h fq_mat_mul_KS"+ fq_mat_mul_KS :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_submul/ /D/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(D = C + AB\). \(C\) and \(D\) may be aliased with each other but+-- not with \(A\) or \(B\).+foreign import ccall "fq_mat.h fq_mat_submul"+ fq_mat_submul :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_mul_vec/ /c/ /A/ /b/ /blen/ +foreign import ccall "fq_mat.h fq_mat_mul_vec"+ fq_mat_mul_vec :: Ptr (Ptr CFq) -> Ptr CFqMat -> Ptr (Ptr CFq) -> CLong -> IO ()+-- | /fq_mat_mul_vec_ptr/ /c/ /A/ /b/ /blen/ +--+-- Compute a matrix-vector product of @A@ and @(b, blen)@ and store the+-- result in @c@. The vector @(b, blen)@ is either truncated or+-- zero-extended to the number of columns of @A@. The number entries+-- written to @c@ is always equal to the number of rows of @A@.+foreign import ccall "fq_mat.h fq_mat_mul_vec_ptr"+ fq_mat_mul_vec_ptr :: Ptr (Ptr (Ptr CFq)) -> Ptr CFqMat -> Ptr (Ptr (Ptr CFq)) -> CLong -> IO ()++-- | /fq_mat_vec_mul/ /c/ /a/ /alen/ /B/ +foreign import ccall "fq_mat.h fq_mat_vec_mul"+ fq_mat_vec_mul :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqMat -> IO ()+-- | /fq_mat_vec_mul_ptr/ /c/ /a/ /alen/ /B/ +--+-- Compute a vector-matrix product of @(a, alen)@ and @B@ and and store the+-- result in @c@. The vector @(a, alen)@ is either truncated or+-- zero-extended to the number of rows of @B@. The number entries written+-- to @c@ is always equal to the number of columns of @B@.+foreign import ccall "fq_mat.h fq_mat_vec_mul_ptr"+ fq_mat_vec_mul_ptr :: Ptr (Ptr (Ptr CFq)) -> Ptr (Ptr (Ptr CFq)) -> CLong -> Ptr CFqMat -> IO ()++-- Inverse ---------------------------------------------------------------------++-- | /fq_mat_inv/ /B/ /A/ /ctx/ +--+-- Sets \(B = A^{-1}\) and returns \(1\) if \(A\) is invertible. If \(A\)+-- is singular, returns \(0\) and sets the elements of \(B\) to undefined+-- values.+-- +-- \(A\) and \(B\) must be square matrices with the same dimensions.+foreign import ccall "fq_mat.h fq_mat_inv"+ fq_mat_inv :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO CInt++-- LU decomposition ------------------------------------------------------------++-- | /fq_mat_lu/ /P/ /A/ /rank_check/ /ctx/ +--+-- Computes a generalised LU decomposition \(LU = PA\) of a given matrix+-- \(A\), returning the rank of \(A\).+-- +-- If \(A\) is a nonsingular square matrix, it will be overwritten with a+-- unit diagonal lower triangular matrix \(L\) and an upper triangular+-- matrix \(U\) (the diagonal of \(L\) will not be stored explicitly).+-- +-- If \(A\) is an arbitrary matrix of rank \(r\), \(U\) will be in row+-- echelon form having \(r\) nonzero rows, and \(L\) will be lower+-- triangular but truncated to \(r\) columns, having implicit ones on the+-- \(r\) first entries of the main diagonal. All other entries will be+-- zero.+-- +-- If a nonzero value for @rank_check@ is passed, the function will abandon+-- the output matrix in an undefined state and return 0 if \(A\) is+-- detected to be rank-deficient.+-- +-- This function calls @fq_mat_lu_recursive@.+foreign import ccall "fq_mat.h fq_mat_lu"+ fq_mat_lu :: Ptr CLong -> Ptr CFqMat -> CInt -> Ptr CFqCtx -> IO CLong++-- | /fq_mat_lu_classical/ /P/ /A/ /rank_check/ /ctx/ +--+-- Computes a generalised LU decomposition \(LU = PA\) of a given matrix+-- \(A\), returning the rank of \(A\). The behavior of this function is+-- identical to that of @fq_mat_lu@. Uses Gaussian elimination.+foreign import ccall "fq_mat.h fq_mat_lu_classical"+ fq_mat_lu_classical :: Ptr CLong -> Ptr CFqMat -> CInt -> Ptr CFqCtx -> IO CLong++-- | /fq_mat_lu_recursive/ /P/ /A/ /rank_check/ /ctx/ +--+-- Computes a generalised LU decomposition \(LU = PA\) of a given matrix+-- \(A\), returning the rank of \(A\). The behavior of this function is+-- identical to that of @fq_mat_lu@. Uses recursive block decomposition,+-- switching to classical Gaussian elimination for sufficiently small+-- blocks.+foreign import ccall "fq_mat.h fq_mat_lu_recursive"+ fq_mat_lu_recursive :: Ptr CLong -> Ptr CFqMat -> CInt -> Ptr CFqCtx -> IO CLong++-- Reduced row echelon form ----------------------------------------------------++-- | /fq_mat_rref/ /A/ /ctx/ +--+-- Puts \(A\) in reduced row echelon form and returns the rank of \(A\).+-- +-- The rref is computed by first obtaining an unreduced row echelon form+-- via LU decomposition and then solving an additional triangular system.+foreign import ccall "fq_mat.h fq_mat_rref"+ fq_mat_rref :: Ptr CFqMat -> Ptr CFqCtx -> IO CLong++-- | /fq_mat_reduce_row/ /A/ /P/ /L/ /n/ /ctx/ +--+-- Reduce row n of the matrix \(A\), assuming the prior rows are in Gauss+-- form. However those rows may not be in order. The entry \(i\) of the+-- array \(P\) is the row of \(A\) which has a pivot in the \(i\)-th+-- column. If no such row exists, the entry of \(P\) will be \(-1\). The+-- function returns the column in which the \(n\)-th row has a pivot after+-- reduction. This will always be chosen to be the first available column+-- for a pivot from the left. This information is also updated in \(P\).+-- Entry \(i\) of the array \(L\) contains the number of possibly nonzero+-- columns of \(A\) row \(i\). This speeds up reduction in the case that+-- \(A\) is chambered on the right. Otherwise the entries of \(L\) can all+-- be set to the number of columns of \(A\). We require the entries of+-- \(L\) to be monotonic increasing.+foreign import ccall "fq_mat.h fq_mat_reduce_row"+ fq_mat_reduce_row :: Ptr CFqMat -> Ptr CLong -> Ptr CLong -> CLong -> Ptr CFqCtx -> IO CLong++-- Triangular solving ----------------------------------------------------------++-- | /fq_mat_solve_tril/ /X/ /L/ /B/ /unit/ /ctx/ +--+-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- Automatically chooses between the classical and recursive algorithms.+foreign import ccall "fq_mat.h fq_mat_solve_tril"+ fq_mat_solve_tril :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> CInt -> Ptr CFqCtx -> IO ()++-- | /fq_mat_solve_tril_classical/ /X/ /L/ /B/ /unit/ /ctx/ +--+-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed. Uses+-- forward substitution.+foreign import ccall "fq_mat.h fq_mat_solve_tril_classical"+ fq_mat_solve_tril_classical :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> CInt -> Ptr CFqCtx -> IO ()++-- | /fq_mat_solve_tril_recursive/ /X/ /L/ /B/ /unit/ /ctx/ +--+-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- +-- Uses the block inversion formula+-- +-- \[\begin{aligned}+-- `+-- \begin{pmatrix} A & 0 \\ C & D \end{pmatrix}^{-1}+-- \begin{pmatrix} X \\ Y \end{pmatrix} =+-- \begin{pmatrix} A^{-1} X \\ D^{-1} ( Y - C A^{-1} X ) \end{pmatrix}+-- \end{aligned}\]+-- +-- to reduce the problem to matrix multiplication and triangular solving of+-- smaller systems.+foreign import ccall "fq_mat.h fq_mat_solve_tril_recursive"+ fq_mat_solve_tril_recursive :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> CInt -> Ptr CFqCtx -> IO ()++-- | /fq_mat_solve_triu/ /X/ /U/ /B/ /unit/ /ctx/ +--+-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- Automatically chooses between the classical and recursive algorithms.+foreign import ccall "fq_mat.h fq_mat_solve_triu"+ fq_mat_solve_triu :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> CInt -> Ptr CFqCtx -> IO ()++-- | /fq_mat_solve_triu_classical/ /X/ /U/ /B/ /unit/ /ctx/ +--+-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed. Uses+-- forward substitution.+foreign import ccall "fq_mat.h fq_mat_solve_triu_classical"+ fq_mat_solve_triu_classical :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> CInt -> Ptr CFqCtx -> IO ()++-- | /fq_mat_solve_triu_recursive/ /X/ /U/ /B/ /unit/ /ctx/ +--+-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- +-- Uses the block inversion formula+-- +-- \[\begin{aligned}+-- `+-- \begin{pmatrix} A & B \\ 0 & D \end{pmatrix}^{-1}+-- \begin{pmatrix} X \\ Y \end{pmatrix} =+-- \begin{pmatrix} A^{-1} (X - B D^{-1} Y) \\ D^{-1} Y \end{pmatrix}+-- \end{aligned}\]+-- +-- to reduce the problem to matrix multiplication and triangular solving of+-- smaller systems.+foreign import ccall "fq_mat.h fq_mat_solve_triu_recursive"+ fq_mat_solve_triu_recursive :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> CInt -> Ptr CFqCtx -> IO ()++-- Solving ---------------------------------------------------------------------++-- | /fq_mat_solve/ /X/ /A/ /B/ /ctx/ +--+-- Solves the matrix-matrix equation \(AX = B\).+-- +-- Returns \(1\) if \(A\) has full rank; otherwise returns \(0\) and sets+-- the elements of \(X\) to undefined values.+-- +-- The matrix \(A\) must be square.+foreign import ccall "fq_mat.h fq_mat_solve"+ fq_mat_solve :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO CInt++-- | /fq_mat_can_solve/ /X/ /A/ /B/ /ctx/ +--+-- Solves the matrix-matrix equation \(AX = B\) over \(Fq\).+-- +-- Returns \(1\) if a solution exists; otherwise returns \(0\) and sets the+-- elements of \(X\) to zero. If more than one solution exists, one of the+-- valid solutions is given.+-- +-- There are no restrictions on the shape of \(A\) and it may be singular.+foreign import ccall "fq_mat.h fq_mat_can_solve"+ fq_mat_can_solve :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqMat -> Ptr CFqCtx -> IO CInt++-- Transforms ------------------------------------------------------------------++-- | /fq_mat_similarity/ /M/ /r/ /d/ /ctx/ +--+-- Applies a similarity transform to the \(n\times n\) matrix \(M\)+-- in-place.+-- +-- If \(P\) is the \(n\times n\) identity matrix the zero entries of whose+-- row \(r\) (0-indexed) have been replaced by \(d\), this transform is+-- equivalent to \(M = P^{-1}MP\).+-- +-- Similarity transforms preserve the determinant, characteristic+-- polynomial and minimal polynomial.+-- +-- The value \(d\) is required to be reduced modulo the modulus of the+-- entries in the matrix.+foreign import ccall "fq_mat.h fq_mat_similarity"+ fq_mat_similarity :: Ptr CFqMat -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- Characteristic polynomial ---------------------------------------------------++-- | /fq_mat_charpoly_danilevsky/ /p/ /M/ /ctx/ +--+-- Compute the characteristic polynomial \(p\) of the matrix \(M\). The+-- matrix is assumed to be square.+foreign import ccall "fq_mat.h fq_mat_charpoly_danilevsky"+ fq_mat_charpoly_danilevsky :: Ptr CFqPoly -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- | /fq_mat_charpoly/ /p/ /M/ /ctx/ +--+-- Compute the characteristic polynomial \(p\) of the matrix \(M\). The+-- matrix is required to be square, otherwise an exception is raised.+foreign import ccall "fq_mat.h fq_mat_charpoly"+ fq_mat_charpoly :: Ptr CFqPoly -> Ptr CFqMat -> Ptr CFqCtx -> IO ()++-- Minimal polynomial ----------------------------------------------------------++-- | /fq_mat_minpoly/ /p/ /M/ /ctx/ +--+-- Compute the minimal polynomial \(p\) of the matrix \(M\). The matrix is+-- required to be square, otherwise an exception is raised.+foreign import ccall "fq_mat.h fq_mat_minpoly"+ fq_mat_minpoly :: Ptr CFqPoly -> Ptr CFqMat -> Ptr CFqCtx -> IO ()+
+ src/Data/Number/Flint/Fq/NMod.hs view
@@ -0,0 +1,12 @@+{-| +module : Data.Number.Flint.Fq.NMod+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Fq.NMod (+ module Data.Number.Flint.Fq.NMod.FFI,+) where++import Data.Number.Flint.Fq.NMod.FFI
+ src/Data/Number/Flint/Fq/NMod/Embed.hs view
@@ -0,0 +1,12 @@+{- | +module : Data.Number.Flint.Fq.NMod.Embed+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Fq.NMod.Embed (+ module Data.Number.Flint.Fq.NMod.Embed.FFI,+) where++import Data.Number.Flint.Fq.NMod.Embed.FFI
+ src/Data/Number/Flint/Fq/NMod/Embed/FFI.hsc view
@@ -0,0 +1,159 @@+{-|+module : Data.Number.Flint.Fq.NMod.Embed.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.NMod.Embed.FFI (+ -- * Computing isomorphisms and embeddings of finite fields+ fq_nmod_embed_gens+ , _fq_nmod_embed_gens_naive+ , fq_nmod_embed_matrices+ , fq_nmod_embed_trace_matrix+ , fq_nmod_embed_composition_matrix+ , fq_nmod_embed_composition_matrix_sub+ , fq_nmod_embed_mul_matrix+ , fq_nmod_embed_mono_to_dual_matrix+ , fq_nmod_embed_dual_to_mono_matrix+ , fq_nmod_modulus_pow_series_inv+ , fq_nmod_modulus_derivative_inv+) where++-- Computing isomorphisms and embeddings of finite fields ----------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types++import Data.Number.Flint.Flint++import Data.Number.Flint.NMod.Mat+import Data.Number.Flint.NMod.Poly++import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Types++--------------------------------------------------------------------------------++-- | /fq_nmod_embed_gens/ /gen_sub/ /gen_sup/ /minpoly/ /sub_ctx/ /sup_ctx/ +--+-- Given two contexts @sub_ctx@ and @sup_ctx@, such that @degree(sub_ctx)@+-- divides @degree(sup_ctx)@, compute:+-- +-- - an element @gen_sub@ in @sub_ctx@ such that @gen_sub@ generates the+-- finite field defined by @sub_ctx@,+-- - its minimal polynomial @minpoly@,+-- - a root @gen_sup@ of @minpoly@ inside the field defined by @sup_ctx@.+-- +-- These data uniquely define an embedding of @sub_ctx@ into @sup_ctx@.+foreign import ccall "fq_nmod_embed.h fq_nmod_embed_gens"+ fq_nmod_embed_gens :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CNModPoly -> Ptr CFqNModCtx -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_embed_gens_naive/ /gen_sub/ /gen_sup/ /minpoly/ /sub_ctx/ /sup_ctx/ +--+-- Given two contexts @sub_ctx@ and @sup_ctx@, such that @degree(sub_ctx)@+-- divides @degree(sup_ctx)@, compute an embedding of @sub_ctx@ into+-- @sup_ctx@ defined as follows:+-- +-- - @gen_sub@ is the canonical generator of @sup_ctx@ (i.e., the class+-- of \(X\)),+-- - @minpoly@ is the defining polynomial of @sub_ctx@,+-- - @gen_sup@ is a root of @minpoly@ inside the field defined by+-- @sup_ctx@.+foreign import ccall "fq_nmod_embed.h _fq_nmod_embed_gens_naive"+ _fq_nmod_embed_gens_naive :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CNModPoly -> Ptr CFqNModCtx -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_embed_matrices/ /embed/ /project/ /gen_sub/ /sub_ctx/ /gen_sup/ /sup_ctx/ /gen_minpoly/ +--+-- Given:+-- +-- - two contexts @sub_ctx@ and @sup_ctx@, of respective degrees \(m\)+-- and \(n\), such that \(m\) divides \(n\);+-- - a generator @gen_sub@ of @sub_ctx@, its minimal polynomial+-- @gen_minpoly@, and a root @gen_sup@ of @gen_minpoly@ in @sup_ctx@,+-- as returned by @fq_nmod_embed_gens@;+-- +-- Compute:+-- +-- - the \(n\times m\) matrix @embed@ mapping @gen_sub@ to @gen_sup@, and+-- all their powers accordingly;+-- - an \(m\times n\) matrix @project@ such that @project@ \(\times\)+-- @embed@ is the \(m\times m\) identity matrix.+foreign import ccall "fq_nmod_embed.h fq_nmod_embed_matrices"+ fq_nmod_embed_matrices :: Ptr CNModMat -> Ptr CNModMat -> Ptr CFqNMod -> Ptr CFqNModCtx -> Ptr CFqNMod -> Ptr CFqNModCtx -> Ptr CNModPoly -> IO ()++-- | /fq_nmod_embed_trace_matrix/ /res/ /basis/ /sub_ctx/ /sup_ctx/ +--+-- Given:+-- +-- - two contexts @sub_ctx@ and @sup_ctx@, of degrees \(m\) and \(n\),+-- such that \(m\) divides \(n\);+-- - an \(n\times m\) matrix @basis@ that maps @sub_ctx@ to an isomorphic+-- subfield in @sup_ctx@;+-- +-- Compute the \(m\times n\) matrix of the trace from @sup_ctx@ to+-- @sub_ctx@.+-- +-- This matrix is computed as+-- +-- @embed_dual_to_mono_matrix(_, sub_ctx)@ \(\times\) @basis@t \(\times\)+-- @embed_mono_to_dual_matrix(_, sup_ctx)}@.+-- +-- __Note:__ if \(m=n\), @basis@ represents a Frobenius, and the result is+-- its inverse matrix.+foreign import ccall "fq_nmod_embed.h fq_nmod_embed_trace_matrix"+ fq_nmod_embed_trace_matrix :: Ptr CNModMat -> Ptr CNModMat -> Ptr CFqNModCtx -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_embed_composition_matrix/ /matrix/ /gen/ /ctx/ +--+-- Compute the /composition matrix/ of @gen@.+-- +-- For an element \(a\in\mathbf{F}_{p^n}\), its composition matrix is the+-- matrix whose columns are \(a^0, a^1, \ldots, a^{n-1}\).+foreign import ccall "fq_nmod_embed.h fq_nmod_embed_composition_matrix"+ fq_nmod_embed_composition_matrix :: Ptr CNModMat -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_embed_composition_matrix_sub/ /matrix/ /gen/ /ctx/ /trunc/ +--+-- Compute the /composition matrix/ of @gen@, truncated to @trunc@ columns.+foreign import ccall "fq_nmod_embed.h fq_nmod_embed_composition_matrix_sub"+ fq_nmod_embed_composition_matrix_sub :: Ptr CNModMat -> Ptr CFqNMod -> Ptr CFqNModCtx -> CLong -> IO ()++-- | /fq_nmod_embed_mul_matrix/ /matrix/ /gen/ /ctx/ +--+-- Compute the /multiplication matrix/ of @gen@.+-- +-- For an element \(a\) in \(\mathbf{F}_{p^n}=\mathbf{F}_p[x]\), its+-- multiplication matrix is the matrix whose columns are \(a, ax,+-- \dots, ax^{n-1}\).+foreign import ccall "fq_nmod_embed.h fq_nmod_embed_mul_matrix"+ fq_nmod_embed_mul_matrix :: Ptr CNModMat -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_embed_mono_to_dual_matrix/ /res/ /ctx/ +--+-- Compute the change of basis matrix from the monomial basis of @ctx@ to+-- its dual basis.+foreign import ccall "fq_nmod_embed.h fq_nmod_embed_mono_to_dual_matrix"+ fq_nmod_embed_mono_to_dual_matrix :: Ptr CNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_embed_dual_to_mono_matrix/ /res/ /ctx/ +--+-- Compute the change of basis matrix from the dual basis of @ctx@ to its+-- monomial basis.+foreign import ccall "fq_nmod_embed.h fq_nmod_embed_dual_to_mono_matrix"+ fq_nmod_embed_dual_to_mono_matrix :: Ptr CNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_modulus_pow_series_inv/ /res/ /ctx/ /trunc/ +--+-- Compute the power series inverse of the reverse of the modulus of @ctx@+-- up to \(O(x^\texttt{trunc})\).+foreign import ccall "fq_nmod_embed.h fq_nmod_modulus_pow_series_inv"+ fq_nmod_modulus_pow_series_inv :: Ptr CNModPoly -> Ptr CFqNModCtx -> CLong -> IO ()++-- | /fq_nmod_modulus_derivative_inv/ /m_prime/ /m_prime_inv/ /ctx/ +--+-- Compute the derivative @m_prime@ of the modulus of @ctx@ as an element+-- of @ctx@, and its inverse @m_prime_inv@.+foreign import ccall "fq_nmod_embed.h fq_nmod_modulus_derivative_inv"+ fq_nmod_modulus_derivative_inv :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()+
+ src/Data/Number/Flint/Fq/NMod/FFI.hsc view
@@ -0,0 +1,840 @@+{-|+module : Data.Number.Flint.Fq.NMod.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.NMod.FFI (+ -- * Finite fields (word-size characteristic)+ FqNMod (..)+ , CFqNMod (..)+ , newFqNMod+ , withFqNMod+ -- * Context+ , FqNModCtx (..)+ , CFqNModCtx (..)+ , newFqNModCtx+ , newFqNModCtxConway+ , newFqNModCtxModulus+ , withFqNModCtx+ -- * Context Management+ , fq_nmod_ctx_init+ , _fq_nmod_ctx_init_conway+ , fq_nmod_ctx_init_conway+ , fq_nmod_ctx_init_modulus+ , fq_nmod_ctx_clear+ , fq_nmod_ctx_modulus+ , fq_nmod_ctx_degree+ -- , fq_nmod_ctx_prime+ , fq_nmod_ctx_order+ , fq_nmod_ctx_fprint+ , fq_nmod_ctx_print+ , fq_nmod_ctx_randtest+ , fq_nmod_ctx_randtest_reducible+ -- * Memory management+ , fq_nmod_init+ , fq_nmod_init2+ , fq_nmod_clear+ , _fq_nmod_sparse_reduce+ , _fq_nmod_dense_reduce+ , _fq_nmod_reduce+ , fq_nmod_reduce+ -- * Basic arithmetic+ , fq_nmod_add+ , fq_nmod_sub+ , fq_nmod_sub_one+ , fq_nmod_neg+ , fq_nmod_mul+ , fq_nmod_mul_fmpz+ , fq_nmod_mul_si+ , fq_nmod_mul_ui+ , fq_nmod_sqr+ , _fq_nmod_inv+ , fq_nmod_inv+ , fq_nmod_gcdinv+ , _fq_nmod_pow+ , fq_nmod_pow+ , fq_nmod_pow_ui+ -- * Roots+ , fq_nmod_sqrt+ , fq_nmod_pth_root+ , fq_nmod_is_square+ -- * Output+ , fq_nmod_fprint_pretty+ , fq_nmod_print_pretty+ , fq_nmod_fprint+ , fq_nmod_print+ , fq_nmod_get_str+ , fq_nmod_get_str_pretty+ -- * Randomisation+ , fq_nmod_randtest+ , fq_nmod_randtest_not_zero+ , fq_nmod_randtest_dense+ , fq_nmod_rand+ , fq_nmod_rand_not_zero+ -- * Assignments and conversions+ , fq_nmod_set+ , fq_nmod_set_si+ , fq_nmod_set_ui+ , fq_nmod_set_fmpz+ , fq_nmod_swap+ , fq_nmod_zero+ , fq_nmod_one+ , fq_nmod_gen+ , fq_nmod_get_fmpz+ , fq_nmod_get_nmod_poly+ , fq_nmod_set_nmod_poly+ , fq_nmod_get_nmod_mat+ , fq_nmod_set_nmod_mat+ -- * Comparison+ , fq_nmod_is_zero+ , fq_nmod_is_one+ , fq_nmod_equal+ , fq_nmod_is_invertible+ , fq_nmod_is_invertible_f+ , fq_nmod_cmp+ -- * Special functions+ , _fq_nmod_trace+ , fq_nmod_trace+ , _fq_nmod_norm+ , fq_nmod_norm+ , _fq_nmod_frobenius+ , fq_nmod_frobenius+ , fq_nmod_multiplicative_order+ , fq_nmod_is_primitive+ -- * Bit packing+ , fq_nmod_bit_pack+ , fq_nmod_bit_unpack+) where++-- Finite fields (word-size characteristic) ------------------------------------++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr+import Foreign.Storable+import Foreign.Marshal++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.NMod+import Data.Number.Flint.NMod.Types+import Data.Number.Flint.Fq.NMod.Types++#include <flint/flint.h>++#include <flint/fq_nmod.h>++-- fq_nmod_t -------------------------------------------------------------------++instance Storable CFqNMod where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_nmod_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_nmod_t}+ peek = undefined+ poke = undefined++newFqNMod ctx@(FqNModCtx ftx) = do+ x <- mallocForeignPtr+ withForeignPtr x$ \x -> do+ withFqNModCtx ctx $ \ctx -> do+ fq_nmod_init x ctx+ addForeignPtrFinalizerEnv p_fq_nmod_clear x ftx+ return $ FqNMod x++{-# INLINE withFqNMod #-}+withFqNMod (FqNMod x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqNMod x,)++-- fq_nmod_ctx_t ---------------------------------------------------------------++instance Storable CFqNModCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_nmod_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_nmod_ctx_t}+ peek ptr = CFqNModCtx+ <$> (return $ castPtr ptr)+ <*> #{peek fq_nmod_ctx_struct, mod } ptr+ <*> #{peek fq_nmod_ctx_struct, sparse_modulus} ptr+ <*> #{peek fq_nmod_ctx_struct, is_conway } ptr+ <*> #{peek fq_nmod_ctx_struct, a } ptr+ <*> #{peek fq_nmod_ctx_struct, j } ptr+ <*> #{peek fq_nmod_ctx_struct, len } ptr+ <*> #{peek fq_nmod_ctx_struct, modulus } ptr+ <*> #{peek fq_nmod_ctx_struct, inv } ptr+ <*> #{peek fq_nmod_ctx_struct, var } ptr+ poke = undefined++newFqNModCtx p d var = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFmpz p $ \p -> + withCString var $ \var -> + fq_nmod_ctx_init x p d var+ addForeignPtrFinalizer p_fq_nmod_ctx_clear x+ return $ FqNModCtx x++newFqNModCtxConway p d var = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFmpz p $ \p -> + withCString var $ \var -> + fq_nmod_ctx_init_conway x p d var+ addForeignPtrFinalizer p_fq_nmod_ctx_clear x+ return $ FqNModCtx x++newFqNModCtxModulus modulus var = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withCString var $ \var ->+ fq_nmod_ctx_init_modulus x modulus var + addForeignPtrFinalizer p_fq_nmod_ctx_clear x+ return $ FqNModCtx x+ +{-# INLINE withFqNModCtx #-}+withFqNModCtx (FqNModCtx x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqNModCtx x,)++-- Context Management ----------------------------------------------------------++-- | /fq_nmod_ctx_init/ /ctx/ /p/ /d/ /var/ +--+-- Initialises the context for prime \(p\) and extension degree \(d\), with+-- name @var@ for the generator. By default, it will try use a Conway+-- polynomial; if one is not available, a random irreducible polynomial+-- will be used.+-- +-- Assumes that \(p\) is a prime.+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq_nmod.h fq_nmod_ctx_init"+ fq_nmod_ctx_init :: Ptr CFqNModCtx -> Ptr CFmpz -> CLong -> CString -> IO ()++-- | /_fq_nmod_ctx_init_conway/ /ctx/ /p/ /d/ /var/ +--+-- Attempts to initialise the context for prime \(p\) and extension degree+-- \(d\), with name @var@ for the generator using a Conway polynomial for+-- the modulus.+-- +-- Returns \(1\) if the Conway polynomial is in the database for the given+-- size and the initialization is successful; otherwise, returns \(0\).+-- +-- Assumes that \(p\) is a prime.+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq_nmod.h _fq_nmod_ctx_init_conway"+ _fq_nmod_ctx_init_conway :: Ptr CFqNModCtx -> Ptr CFmpz -> CLong -> CString -> IO CInt++-- | /fq_nmod_ctx_init_conway/ /ctx/ /p/ /d/ /var/ +--+-- Initialises the context for prime \(p\) and extension degree \(d\), with+-- name @var@ for the generator using a Conway polynomial for the modulus.+-- +-- Assumes that \(p\) is a prime.+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq_nmod.h fq_nmod_ctx_init_conway"+ fq_nmod_ctx_init_conway :: Ptr CFqNModCtx -> Ptr CFmpz -> CLong -> CString -> IO ()++-- | /fq_nmod_ctx_init_modulus/ /ctx/ /modulus/ /var/ +--+-- Initialises the context for given @modulus@ with name @var@ for the+-- generator.+-- +-- Assumes that @modulus@ is an irreducible polynomial over+-- \(\mathbf{F}_{p}\).+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq_nmod.h fq_nmod_ctx_init_modulus"+ fq_nmod_ctx_init_modulus :: Ptr CFqNModCtx -> Ptr CNModPoly -> CString -> IO ()++-- | /fq_nmod_ctx_clear/ /ctx/ +--+-- Clears all memory that has been allocated as part of the context.+foreign import ccall "fq_nmod.h fq_nmod_ctx_clear"+ fq_nmod_ctx_clear :: Ptr CFqNModCtx -> IO ()++foreign import ccall "fq_nmod.h &fq_nmod_ctx_clear"+ p_fq_nmod_ctx_clear :: FunPtr (Ptr CFqNModCtx -> IO ())++-- | /fq_nmod_ctx_modulus/ /ctx/ +--+-- Returns a pointer to the modulus in the context.+foreign import ccall "fq_nmod.h fq_nmod_ctx_modulus"+ fq_nmod_ctx_modulus :: Ptr CFqNModCtx -> IO (Ptr (Ptr CNModPoly))++-- | /fq_nmod_ctx_degree/ /ctx/ +--+-- Returns the degree of the field extension+-- \([\mathbf{F}_{q} : \mathbf{F}_{p}]\), which is equal to \(\log_{p} q\).+foreign import ccall "fq_nmod.h fq_nmod_ctx_degree"+ fq_nmod_ctx_degree :: Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_ctx_prime/ /ctx/ +--+-- Returns a pointer to the prime \(p\) in the context.+-- foreign import ccall "fq_nmod.h fq_nmod_ctx_prime"+fq_nmod_ctx_prime :: Ptr CFqNModCtx -> IO (Ptr CFmpz)+fq_nmod_ctx_prime ctx = do+ CFqNModCtx p _ _ _ _ _ _ _ _ _ <- peek ctx+ return p+ +-- | /fq_nmod_ctx_order/ /f/ /ctx/ +--+-- Sets \(f\) to be the size of the finite field.+foreign import ccall "fq_nmod.h fq_nmod_ctx_order"+ fq_nmod_ctx_order :: Ptr CFmpz -> Ptr CFqNModCtx -> IO ()++-- Input and Output ------------------------------------------------------------++-- | /fq_nmod_ctx_get_str/ /ctx/ +--+-- Return a string representation of the context information. +foreign import ccall "fq_nmod.h fq_nmod_ctx_get_str"+ fq_nmod_ctx_get_str :: Ptr CFqNModCtx -> IO CString+ +-- | /fq_nmod_ctx_fprint/ /file/ /ctx/ +--+-- Prints the context information to @file@. Returns 1 for a success and a+-- negative number for an error.+foreign import ccall "fq_nmod.h fq_nmod_ctx_fprint"+ fq_nmod_ctx_fprint :: Ptr CFile -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_ctx_print/ /ctx/ +--+-- Prints the context information to @stdout@.+fq_nmod_ctx_print :: Ptr CFqNModCtx -> IO ()+fq_nmod_ctx_print ctx = do+ printCStr fq_nmod_ctx_get_str ctx+ return ()++-- | /fq_nmod_ctx_randtest/ /ctx/ +--+-- Initializes @ctx@ to a random finite field. Assumes that+-- @fq_nmod_ctx_init@ has not been called on @ctx@ already.+foreign import ccall "fq_nmod.h fq_nmod_ctx_randtest"+ fq_nmod_ctx_randtest :: Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_ctx_randtest_reducible/ /ctx/ +--+-- Initializes @ctx@ to a random extension of a word-sized prime field. The+-- modulus may or may not be irreducible. Assumes that @fq_nmod_ctx_init@+-- has not been called on @ctx@ already.+foreign import ccall "fq_nmod.h fq_nmod_ctx_randtest_reducible"+ fq_nmod_ctx_randtest_reducible :: Ptr CFqNModCtx -> IO ()++-- Memory management -----------------------------------------------------------++-- | /fq_nmod_init/ /rop/ /ctx/ +--+-- Initialises the element @rop@, setting its value to \(0\). Currently,+-- the behaviour is identical to @fq_nmod_init2@, as it also ensures @rop@+-- has enough space for it to be an element of @ctx@, this may change in+-- the future.+foreign import ccall "fq_nmod.h fq_nmod_init"+ fq_nmod_init :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_init2/ /rop/ /ctx/ +--+-- Initialises @rop@ with at least enough space for it to be an element of+-- @ctx@ and sets it to \(0\).+foreign import ccall "fq_nmod.h fq_nmod_init2"+ fq_nmod_init2 :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_clear/ /rop/ /ctx/ +--+-- Clears the element @rop@.+foreign import ccall "fq_nmod.h fq_nmod_clear"+ fq_nmod_clear :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++foreign import ccall "fq_nmod.h &fq_nmod_clear"+ p_fq_nmod_clear :: FunPtr (Ptr CFqNMod -> Ptr CFqNModCtx -> IO ())++-- | /_fq_nmod_sparse_reduce/ /R/ /lenR/ /ctx/ +--+-- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of+-- @ctx@.+foreign import ccall "fq_nmod.h _fq_nmod_sparse_reduce"+ _fq_nmod_sparse_reduce :: Ptr CMp -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_dense_reduce/ /R/ /lenR/ /ctx/ +--+-- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of+-- @ctx@ using Newton division.+foreign import ccall "fq_nmod.h _fq_nmod_dense_reduce"+ _fq_nmod_dense_reduce :: Ptr CMp -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_reduce/ /r/ /lenR/ /ctx/ +--+-- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of+-- @ctx@. Does either sparse or dense reduction based on+-- @ctx->sparse_modulus@.+foreign import ccall "fq_nmod.h _fq_nmod_reduce"+ _fq_nmod_reduce :: Ptr CMp -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_reduce/ /rop/ /ctx/ +--+-- Reduces the polynomial @rop@ as an element of+-- \(\mathbf{F}_p[X] / (f(X))\).+foreign import ccall "fq_nmod.h fq_nmod_reduce"+ fq_nmod_reduce :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- Basic arithmetic ------------------------------------------------------------++-- | /fq_nmod_add/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the sum of @op1@ and @op2@.+foreign import ccall "fq_nmod.h fq_nmod_add"+ fq_nmod_add :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_sub/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the difference of @op1@ and @op2@.+foreign import ccall "fq_nmod.h fq_nmod_sub"+ fq_nmod_sub :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_sub_one/ /rop/ /op1/ /ctx/ +--+-- Sets @rop@ to the difference of @op1@ and \(1\).+foreign import ccall "fq_nmod.h fq_nmod_sub_one"+ fq_nmod_sub_one :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_neg/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the negative of @op@.+foreign import ccall "fq_nmod.h fq_nmod_neg"+ fq_nmod_neg :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mul/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@, reducing the output in the+-- given context.+foreign import ccall "fq_nmod.h fq_nmod_mul"+ fq_nmod_mul :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mul_fmpz/ /rop/ /op/ /x/ /ctx/ +--+-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the+-- given context.+foreign import ccall "fq_nmod.h fq_nmod_mul_fmpz"+ fq_nmod_mul_fmpz :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFmpz -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mul_si/ /rop/ /op/ /x/ /ctx/ +--+-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the+-- given context.+foreign import ccall "fq_nmod.h fq_nmod_mul_si"+ fq_nmod_mul_si :: Ptr CFqNMod -> Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mul_ui/ /rop/ /op/ /x/ /ctx/ +--+-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the+-- given context.+foreign import ccall "fq_nmod.h fq_nmod_mul_ui"+ fq_nmod_mul_ui :: Ptr CFqNMod -> Ptr CFqNMod -> CULong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_sqr/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the square of @op@, reducing the output in the given+-- context.+foreign import ccall "fq_nmod.h fq_nmod_sqr"+ fq_nmod_sqr :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_inv/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, d)@ to the inverse of the non-zero element @(op, len)@.+foreign import ccall "fq_nmod.h _fq_nmod_inv"+ _fq_nmod_inv :: Ptr (Ptr CMp) -> Ptr (Ptr CMp) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_inv/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the inverse of the non-zero element @op@.+foreign import ccall "fq_nmod.h fq_nmod_inv"+ fq_nmod_inv :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_gcdinv/ /f/ /inv/ /op/ /ctx/ +--+-- Sets @inv@ to be the inverse of @op@ modulo the modulus of @ctx@. If+-- @op@ is not invertible, then @f@ is set to a factor of the modulus;+-- otherwise, it is set to one.+foreign import ccall "fq_nmod.h fq_nmod_gcdinv"+ fq_nmod_gcdinv :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_pow/ /rop/ /op/ /len/ /e/ /ctx/ +--+-- Sets @(rop, 2*d-1)@ to @(op,len)@ raised to the power \(e\), reduced+-- modulo \(f(X)\), the modulus of @ctx@.+-- +-- Assumes that \(e \geq 0\) and that @len@ is positive and at most \(d\).+-- +-- Although we require that @rop@ provides space for \(2d - 1\)+-- coefficients, the output will be reduced modulo \(f(X)\), which is a+-- polynomial of degree \(d\).+-- +-- Does not support aliasing.+foreign import ccall "fq_nmod.h _fq_nmod_pow"+ _fq_nmod_pow :: Ptr (Ptr CMp) -> Ptr (Ptr CMp) -> CLong -> Ptr CFmpz -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_pow/ /rop/ /op/ /e/ /ctx/ +--+-- Sets @rop@ to @op@ raised to the power \(e\).+-- +-- Currently assumes that \(e \geq 0\).+-- +-- Note that for any input @op@, @rop@ is set to \(1\) whenever \(e = 0\).+foreign import ccall "fq_nmod.h fq_nmod_pow"+ fq_nmod_pow :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFmpz -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_pow_ui/ /rop/ /op/ /e/ /ctx/ +--+-- Sets @rop@ to @op@ raised to the power \(e\).+-- +-- Currently assumes that \(e \geq 0\).+-- +-- Note that for any input @op@, @rop@ is set to \(1\) whenever \(e = 0\).+foreign import ccall "fq_nmod.h fq_nmod_pow_ui"+ fq_nmod_pow_ui :: Ptr CFqNMod -> Ptr CFqNMod -> CULong -> Ptr CFqNModCtx -> IO ()++-- Roots -----------------------------------------------------------------------++-- | /fq_nmod_sqrt/ /rop/ /op1/ /ctx/ +--+-- Sets @rop@ to the square root of @op1@ if it is a square, and return+-- \(1\), otherwise return \(0\).+foreign import ccall "fq_nmod.h fq_nmod_sqrt"+ fq_nmod_sqrt :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_pth_root/ /rop/ /op1/ /ctx/ +--+-- Sets @rop@ to a \(p^{\textrm{th}}\) root of @op1@. Currently, this+-- computes the root by raising @op1@ to \(p^{d-1}\) where \(d\) is the+-- degree of the extension.+foreign import ccall "fq_nmod.h fq_nmod_pth_root"+ fq_nmod_pth_root :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_is_square/ /op/ /ctx/ +--+-- Return @1@ if @op@ is a square.+foreign import ccall "fq_nmod.h fq_nmod_is_square"+ fq_nmod_is_square :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- Output ----------------------------------------------------------------------++-- | /fq_nmod_fprint_pretty/ /file/ /op/ /ctx/ +--+-- Prints a pretty representation of @op@ to @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_nmod.h fq_nmod_fprint_pretty"+ fq_nmod_fprint_pretty :: Ptr CFile -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_print_pretty/ /op/ /ctx/ +--+-- Prints a pretty representation of @op@ to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+fq_nmod_print_pretty :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt+fq_nmod_print_pretty op ctx = do+ printCStr (`fq_nmod_get_str_pretty` ctx) op++-- | /fq_nmod_fprint/ /file/ /op/ /ctx/ +--+-- Prints a representation of @op@ to @file@.+-- +-- For further details on the representation used, see+-- @nmod_poly_fprint()@.+foreign import ccall "fq_nmod.h fq_nmod_fprint"+ fq_nmod_fprint :: Ptr CFile -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_print/ /op/ /ctx/ +--+-- Prints a representation of @op@ to @stdout@.+-- +-- For further details on the representation used, see @nmod_poly_print()@.+fq_nmod_print :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()+fq_nmod_print op ctx = do+ printCStr (`fq_nmod_get_str` ctx) op+ return ()++-- | /fq_nmod_get_str/ /op/ /ctx/ +--+-- Returns the plain FLINT string representation of the element @op@.+foreign import ccall "fq_nmod.h fq_nmod_get_str"+ fq_nmod_get_str :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO CString++-- | /fq_nmod_get_str_pretty/ /op/ /ctx/ +--+-- Returns a pretty representation of the element @op@ using the+-- null-terminated string @x@ as the variable name.+foreign import ccall "fq_nmod.h fq_nmod_get_str_pretty"+ fq_nmod_get_str_pretty :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO CString++-- Randomisation ---------------------------------------------------------------++-- | /fq_nmod_randtest/ /rop/ /state/ /ctx/ +--+-- Generates a random element of \(\mathbf{F}_q\).+foreign import ccall "fq_nmod.h fq_nmod_randtest"+ fq_nmod_randtest :: Ptr CFqNMod -> Ptr CFRandState -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_randtest_not_zero/ /rop/ /state/ /ctx/ +--+-- Generates a random non-zero element of \(\mathbf{F}_q\).+foreign import ccall "fq_nmod.h fq_nmod_randtest_not_zero"+ fq_nmod_randtest_not_zero :: Ptr CFqNMod -> Ptr CFRandState -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_randtest_dense/ /rop/ /state/ /ctx/ +--+-- Generates a random element of \(\mathbf{F}_q\) which has an underlying+-- polynomial with dense coefficients.+foreign import ccall "fq_nmod.h fq_nmod_randtest_dense"+ fq_nmod_randtest_dense :: Ptr CFqNMod -> Ptr CFRandState -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_rand/ /rop/ /state/ /ctx/ +--+-- Generates a high quality random element of \(\mathbf{F}_q\).+foreign import ccall "fq_nmod.h fq_nmod_rand"+ fq_nmod_rand :: Ptr CFqNMod -> Ptr CFRandState -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_rand_not_zero/ /rop/ /state/ /ctx/ +--+-- Generates a high quality non-zero random element of \(\mathbf{F}_q\).+foreign import ccall "fq_nmod.h fq_nmod_rand_not_zero"+ fq_nmod_rand_not_zero :: Ptr CFqNMod -> Ptr CFRandState -> Ptr CFqNModCtx -> IO ()++-- Assignments and conversions -------------------------------------------------++-- | /fq_nmod_set/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to @op@.+foreign import ccall "fq_nmod.h fq_nmod_set"+ fq_nmod_set :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_set_si/ /rop/ /x/ /ctx/ +--+-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).+foreign import ccall "fq_nmod.h fq_nmod_set_si"+ fq_nmod_set_si :: Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_set_ui/ /rop/ /x/ /ctx/ +--+-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).+foreign import ccall "fq_nmod.h fq_nmod_set_ui"+ fq_nmod_set_ui :: Ptr CFqNMod -> CULong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_set_fmpz/ /rop/ /x/ /ctx/ +--+-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).+foreign import ccall "fq_nmod.h fq_nmod_set_fmpz"+ fq_nmod_set_fmpz :: Ptr CFqNMod -> Ptr CFmpz -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_swap/ /op1/ /op2/ /ctx/ +--+-- Swaps the two elements @op1@ and @op2@.+foreign import ccall "fq_nmod.h fq_nmod_swap"+ fq_nmod_swap :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_zero/ /rop/ /ctx/ +--+-- Sets @rop@ to zero.+foreign import ccall "fq_nmod.h fq_nmod_zero"+ fq_nmod_zero :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_one/ /rop/ /ctx/ +--+-- Sets @rop@ to one, reduced in the given context.+foreign import ccall "fq_nmod.h fq_nmod_one"+ fq_nmod_one :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_gen/ /rop/ /ctx/ +--+-- Sets @rop@ to a generator for the finite field. There is no guarantee+-- this is a multiplicative generator of the finite field.+foreign import ccall "fq_nmod.h fq_nmod_gen"+ fq_nmod_gen :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_get_fmpz/ /rop/ /op/ /ctx/ +--+-- If @op@ has a lift to the integers, return \(1\) and set @rop@ to the+-- lift in \([0,p)\). Otherwise, return \(0\) and leave \(rop\) undefined.+foreign import ccall "fq_nmod.h fq_nmod_get_fmpz"+ fq_nmod_get_fmpz :: Ptr CFmpz -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_get_nmod_poly/ /a/ /b/ /ctx/ +--+-- Set @a@ to a representative of @b@ in @ctx@. The representatives are+-- taken in \((\mathbb{Z}/p\mathbb{Z})[x]/h(x)\) where \(h(x)\) is the+-- defining polynomial in @ctx@.+foreign import ccall "fq_nmod.h fq_nmod_get_nmod_poly"+ fq_nmod_get_nmod_poly :: Ptr CNModPoly -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_set_nmod_poly/ /a/ /b/ /ctx/ +--+-- Set @a@ to the element in @ctx@ with representative @b@. The+-- representatives are taken in \((\mathbb{Z}/p\mathbb{Z})[x]/h(x)\) where+-- \(h(x)\) is the defining polynomial in @ctx@.+foreign import ccall "fq_nmod.h fq_nmod_set_nmod_poly"+ fq_nmod_set_nmod_poly :: Ptr CFqNMod -> Ptr CNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_get_nmod_mat/ /col/ /a/ /ctx/ +--+-- Convert @a@ to a column vector of length @degree(ctx)@.+foreign import ccall "fq_nmod.h fq_nmod_get_nmod_mat"+ fq_nmod_get_nmod_mat :: Ptr CNModMat -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_set_nmod_mat/ /a/ /col/ /ctx/ +--+-- Convert a column vector @col@ of length @degree(ctx)@ to an element of+-- @ctx@.+foreign import ccall "fq_nmod.h fq_nmod_set_nmod_mat"+ fq_nmod_set_nmod_mat :: Ptr CFqNMod -> Ptr CNModMat -> Ptr CFqNModCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fq_nmod_is_zero/ /op/ /ctx/ +--+-- Returns whether @op@ is equal to zero.+foreign import ccall "fq_nmod.h fq_nmod_is_zero"+ fq_nmod_is_zero :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_is_one/ /op/ /ctx/ +--+-- Returns whether @op@ is equal to one.+foreign import ccall "fq_nmod.h fq_nmod_is_one"+ fq_nmod_is_one :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_equal/ /op1/ /op2/ /ctx/ +--+-- Returns whether @op1@ and @op2@ are equal.+foreign import ccall "fq_nmod.h fq_nmod_equal"+ fq_nmod_equal :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_is_invertible/ /op/ /ctx/ +--+-- Returns whether @op@ is an invertible element.+foreign import ccall "fq_nmod.h fq_nmod_is_invertible"+ fq_nmod_is_invertible :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_is_invertible_f/ /f/ /op/ /ctx/ +--+-- Returns whether @op@ is an invertible element. If it is not, then @f@ is+-- set to a factor of the modulus.+foreign import ccall "fq_nmod.h fq_nmod_is_invertible_f"+ fq_nmod_is_invertible_f :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_cmp/ /a/ /b/ /ctx/ +--+-- Return @1@ (resp. @-1@, or @0@) if @a@ is after (resp. before, same as)+-- @b@ in some arbitrary but fixed total ordering of the elements.+foreign import ccall "fq_nmod.h fq_nmod_cmp"+ fq_nmod_cmp :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- Special functions -----------------------------------------------------------++-- | /_fq_nmod_trace/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @rop@ to the trace of the non-zero element @(op, len)@ in+-- \(\mathbf{F}_{q}\).+foreign import ccall "fq_nmod.h _fq_nmod_trace"+ _fq_nmod_trace :: Ptr CFmpz -> Ptr (Ptr CMp) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_trace/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the trace of @op@.+-- +-- For an element \(a \in \mathbf{F}_q\), multiplication by \(a\) defines a+-- \(\mathbf{F}_p\)-linear map on \(\mathbf{F}_q\). We define the trace of+-- \(a\) as the trace of this map. Equivalently, if \(\Sigma\) generates+-- \(\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)\) then the trace of+-- \(a\) is equal to \(\sum_{i=0}^{d-1} \Sigma^i (a)\), where \(d =+-- \log_{p} q\).+foreign import ccall "fq_nmod.h fq_nmod_trace"+ fq_nmod_trace :: Ptr CFmpz -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_norm/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @rop@ to the norm of the non-zero element @(op, len)@ in+-- \(\mathbf{F}_{q}\).+foreign import ccall "fq_nmod.h _fq_nmod_norm"+ _fq_nmod_norm :: Ptr CFmpz -> Ptr (Ptr CMp) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_norm/ /rop/ /op/ /ctx/ +--+-- Computes the norm of @op@.+-- +-- For an element \(a \in \mathbf{F}_q\), multiplication by \(a\) defines a+-- \(\mathbf{F}_p\)-linear map on \(\mathbf{F}_q\). We define the norm of+-- \(a\) as the determinant of this map. Equivalently, if \(\Sigma\)+-- generates \(\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)\) then the+-- trace of \(a\) is equal to \(\prod_{i=0}^{d-1} \Sigma^i (a)\), where+-- \(d = \text{dim}_{\mathbf{F}_p}(\mathbf{F}_q)\).+-- +-- Algorithm selection is automatic depending on the input.+foreign import ccall "fq_nmod.h fq_nmod_norm"+ fq_nmod_norm :: Ptr CFmpz -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_frobenius/ /rop/ /op/ /len/ /e/ /ctx/ +--+-- Sets @(rop, 2d-1)@ to the image of @(op, len)@ under the Frobenius+-- operator raised to the e-th power, assuming that neither @op@ nor @e@+-- are zero.+foreign import ccall "fq_nmod.h _fq_nmod_frobenius"+ _fq_nmod_frobenius :: Ptr (Ptr CMp) -> Ptr (Ptr CMp) -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_frobenius/ /rop/ /op/ /e/ /ctx/ +--+-- Evaluates the homomorphism \(\Sigma^e\) at @op@.+-- +-- Recall that \(\mathbf{F}_q / \mathbf{F}_p\) is Galois with Galois group+-- \(\langle \sigma \rangle\), which is also isomorphic to+-- \(\mathbf{Z}/d\mathbf{Z}\), where+-- \(\sigma \in \operatorname{Gal}(\mathbf{F}_q/\mathbf{F}_p)\) is the+-- Frobenius element \(\sigma \colon x \mapsto x^p\).+foreign import ccall "fq_nmod.h fq_nmod_frobenius"+ fq_nmod_frobenius :: Ptr CFqNMod -> Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_multiplicative_order/ /ord/ /op/ /ctx/ +--+-- Computes the order of @op@ as an element of the multiplicative group of+-- @ctx@.+-- +-- Returns 0 if @op@ is 0, otherwise it returns 1 if @op@ is a generator of+-- the multiplicative group, and -1 if it is not.+-- +-- This function can also be used to check primitivity of a generator of a+-- finite field whose defining polynomial is not primitive.+foreign import ccall "fq_nmod.h fq_nmod_multiplicative_order"+ fq_nmod_multiplicative_order :: Ptr CFmpz -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_is_primitive/ /op/ /ctx/ +--+-- Returns whether @op@ is primitive, i.e., whether it is a generator of+-- the multiplicative group of @ctx@.+foreign import ccall "fq_nmod.h fq_nmod_is_primitive"+ fq_nmod_is_primitive :: Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- Bit packing -----------------------------------------------------------------++-- | /fq_nmod_bit_pack/ /f/ /op/ /bit_size/ /ctx/ +--+-- Packs @op@ into bitfields of size @bit_size@, writing the result to @f@.+foreign import ccall "fq_nmod.h fq_nmod_bit_pack"+ fq_nmod_bit_pack :: Ptr CFmpz -> Ptr CFqNMod -> CFBitCnt -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_bit_unpack/ /rop/ /f/ /bit_size/ /ctx/ +--+-- Unpacks into @rop@ the element with coefficients packed into fields of+-- size @bit_size@ as represented by the integer @f@.+foreign import ccall "fq_nmod.h fq_nmod_bit_unpack"+ fq_nmod_bit_unpack :: Ptr CFqNMod -> Ptr CFmpz -> CFBitCnt -> Ptr CFqNModCtx -> IO ()+
+ src/Data/Number/Flint/Fq/NMod/MPoly.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fq.NMod.MPoly (+ module Data.Number.Flint.Fq.NMod.MPoly.FFI+ ) where++import Data.Number.Flint.Fq.NMod.MPoly.FFI
+ src/Data/Number/Flint/Fq/NMod/MPoly/FFI.hsc view
@@ -0,0 +1,1028 @@+{-|+module : Data.Number.Flint.Fq.NMod.MPoly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.NMod.MPoly.FFI (+ -- * Multivariate polynomials over finite fields of word-sized characteristic+ FqNModMPoly (..)+ , CFqNModMPoly (..)+ , newFqNModMPoly+ , withFqNModMPoly+ -- * Context object+ , FqNModMPolyCtx (..)+ , CFqNModMPolyCtx (..)+ , newFqNModMPolyCtx+ , withFqNModMPolyCtx+ -- *+ , fq_nmod_mpoly_ctx_init+ , fq_nmod_mpoly_ctx_nvars+ , fq_nmod_mpoly_ctx_ord+ , fq_nmod_mpoly_ctx_clear+ -- * Memory management+ , fq_nmod_mpoly_init+ , fq_nmod_mpoly_init2+ , fq_nmod_mpoly_init3+ , fq_nmod_mpoly_fit_length+ , fq_nmod_mpoly_realloc+ , fq_nmod_mpoly_clear+ -- * Input\/Output+ , fq_nmod_mpoly_get_str_pretty+ , fq_nmod_mpoly_fprint_pretty+ , fq_nmod_mpoly_print_pretty+ , fq_nmod_mpoly_set_str_pretty+ -- * Basic manipulation+ , fq_nmod_mpoly_gen+ , fq_nmod_mpoly_is_gen+ , fq_nmod_mpoly_set+ , fq_nmod_mpoly_equal+ , fq_nmod_mpoly_swap+ -- * Constants+ , fq_nmod_mpoly_is_fq_nmod+ , fq_nmod_mpoly_get_fq_nmod+ , fq_nmod_mpoly_set_fq_nmod+ , fq_nmod_mpoly_set_ui+ , fq_nmod_mpoly_set_fq_nmod_gen+ , fq_nmod_mpoly_zero+ , fq_nmod_mpoly_one+ , fq_nmod_mpoly_equal_fq_nmod+ , fq_nmod_mpoly_is_zero+ , fq_nmod_mpoly_is_one+ -- * Degrees+ , fq_nmod_mpoly_degrees_fit_si+ , fq_nmod_mpoly_degrees_fmpz+ , fq_nmod_mpoly_degrees_si+ , fq_nmod_mpoly_degree_fmpz+ , fq_nmod_mpoly_degree_si+ , fq_nmod_mpoly_total_degree_fits_si+ , fq_nmod_mpoly_total_degree_fmpz+ , fq_nmod_mpoly_total_degree_si+ , fq_nmod_mpoly_used_vars+ -- * Coefficients+ , fq_nmod_mpoly_get_coeff_fq_nmod_monomial+ , fq_nmod_mpoly_set_coeff_fq_nmod_monomial+ , fq_nmod_mpoly_get_coeff_fq_nmod_fmpz+ , fq_nmod_mpoly_get_coeff_fq_nmod_ui+ , fq_nmod_mpoly_set_coeff_fq_nmod_fmpz+ , fq_nmod_mpoly_set_coeff_fq_nmod_ui+ , fq_nmod_mpoly_get_coeff_vars_ui+ -- * Comparison+ , fq_nmod_mpoly_cmp+ -- * Container operations+ , fq_nmod_mpoly_is_canonical+ , fq_nmod_mpoly_length+ , fq_nmod_mpoly_resize+ , fq_nmod_mpoly_get_term_coeff_fq_nmod+ --, fq_nmod_mpoly_set_term_coeff_ui+ , fq_nmod_mpoly_term_exp_fits_si+ , fq_nmod_mpoly_term_exp_fits_ui+ , fq_nmod_mpoly_get_term_exp_fmpz+ , fq_nmod_mpoly_get_term_exp_ui+ , fq_nmod_mpoly_get_term_exp_si+ , fq_nmod_mpoly_get_term_var_exp_ui+ , fq_nmod_mpoly_get_term_var_exp_si+ , fq_nmod_mpoly_set_term_exp_fmpz+ , fq_nmod_mpoly_set_term_exp_ui+ , fq_nmod_mpoly_get_term+ , fq_nmod_mpoly_get_term_monomial+ , fq_nmod_mpoly_push_term_fq_nmod_fmpz+ , fq_nmod_mpoly_push_term_fq_nmod_ui+ , fq_nmod_mpoly_sort_terms+ , fq_nmod_mpoly_combine_like_terms+ , fq_nmod_mpoly_reverse+ -- * Random generation+ , fq_nmod_mpoly_randtest_bound+ , fq_nmod_mpoly_randtest_bounds+ , fq_nmod_mpoly_randtest_bits+ -- * Addition\/Subtraction+ , fq_nmod_mpoly_add_fq_nmod+ , fq_nmod_mpoly_sub_fq_nmod+ , fq_nmod_mpoly_add+ , fq_nmod_mpoly_sub+ -- * Scalar operations+ , fq_nmod_mpoly_neg+ , fq_nmod_mpoly_scalar_mul_fq_nmod+ , fq_nmod_mpoly_make_monic+ -- * Differentiation+ , fq_nmod_mpoly_derivative+ -- * Evaluation+ , fq_nmod_mpoly_evaluate_all_fq_nmod+ , fq_nmod_mpoly_evaluate_one_fq_nmod+ , fq_nmod_mpoly_compose_fq_nmod_poly+ , fq_nmod_mpoly_compose_fq_nmod_mpoly+ , fq_nmod_mpoly_compose_fq_nmod_mpoly_gen+ -- * Multiplication+ , fq_nmod_mpoly_mul+ -- * Powering+ , fq_nmod_mpoly_pow_fmpz+ , fq_nmod_mpoly_pow_ui+ -- * Division+ , fq_nmod_mpoly_divides+ , fq_nmod_mpoly_div+ , fq_nmod_mpoly_divrem+ , fq_nmod_mpoly_divrem_ideal+ -- * Greatest Common Divisor+ , fq_nmod_mpoly_term_content+ , fq_nmod_mpoly_content_vars+ , fq_nmod_mpoly_gcd+ , fq_nmod_mpoly_gcd_cofactors+ , fq_nmod_mpoly_gcd_brown+ , fq_nmod_mpoly_gcd_hensel+ , fq_nmod_mpoly_gcd_zippel+ , fq_nmod_mpoly_resultant+ , fq_nmod_mpoly_discriminant+ -- * Square Root+ , fq_nmod_mpoly_sqrt+ , fq_nmod_mpoly_is_square+ , fq_nmod_mpoly_quadratic_root+ -- * Univariate Functions+ , fq_nmod_mpoly_univar_init+ , fq_nmod_mpoly_univar_clear+ , fq_nmod_mpoly_univar_swap+ , fq_nmod_mpoly_to_univar+ , fq_nmod_mpoly_from_univar+ , fq_nmod_mpoly_univar_degree_fits_si+ , fq_nmod_mpoly_univar_length+ , fq_nmod_mpoly_univar_get_term_exp_si+ , fq_nmod_mpoly_univar_get_term_coeff+ , fq_nmod_mpoly_univar_swap_term_coeff+) where++-- Multivariate polynomials over finite fields of word-size characteristic -----++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.MPoly+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mod.Poly+import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.NMod.MPoly+import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.Poly+import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Types++#include <flint/flint.h>+#include <flint/fq.h>+#include <flint/fq_nmod.h>+#include <flint/fq_nmod_poly.h>+#include <flint/fq_nmod_mpoly.h>++-- fq_nmod_mpoly_t -------------------------------------------------------------++instance Storable CFqNModMPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_nmod_mpoly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_nmod_mpoly_t}+ peek = undefined+ poke = undefined++newFqNModMPoly ctx@(FqNModMPolyCtx ftx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqNModMPolyCtx ctx $ \ctx -> do+ fq_nmod_mpoly_init x ctx+ addForeignPtrFinalizerEnv p_fq_nmod_mpoly_clear x ftx+ return $ FqNModMPoly x++{-# INLINE withFqNModMPoly #-}+withFqNModMPoly (FqNModMPoly x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqNModMPoly x,)++-- fq_nmod_mpoly_univar_t ------------------------------------------------------++data FqNModMPolyUnivar = FqNModMPolyUnivar {-# UNPACK #-} !(ForeignPtr CFqNModMPolyUnivar)+data CFqNModMPolyUnivar = CFqNModMPolyUnivar ++instance Storable CFqNModMPolyUnivar where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_nmod_mpoly_univar_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_nmod_mpoly_univar_t}+ peek = error "CFqNModMPolyUnivar.peek: Not defined"+ poke = error "CFqNModMPolyUnivar.poke: Not defined"++-- | Create a new `FqNModMPolyUnivar`+newFqNModMPolyUnivar ctx@(FqNModMPolyCtx pctx) = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withFqNModMPolyCtx ctx $ \ctx -> do + fq_nmod_mpoly_univar_init p ctx+ addForeignPtrFinalizerEnv p_fq_nmod_mpoly_univar_clear p pctx+ return $ FqNModMPolyUnivar p++{-# INLINE withFqNModMPolyUnivar #-}+withFqNModMPolyUnivar (FqNModMPolyUnivar p) f = do+ withForeignPtr p $ \fp -> (FqNModMPolyUnivar p,) <$> f fp+ +-- fq_nmod_mpoly_ctx_t ---------------------------------------------------------+++data FqNModMPolyCtx = FqNModMPolyCtx {-# UNPACK #-} !(ForeignPtr CFqNModMPolyCtx)+data CFqNModMPolyCtx++instance Storable CFqNModMPolyCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_nmod_mpoly_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_nmod_mpoly_ctx_t}+ peek = error "CFqNModMPolyCtx.peek: Not defined"+ poke = error "CFqNModMPolyCtx.poke: Not defined"++-- | Create a new `FqNModMPolyCtx`+newFqNModMPolyCtx nvars ord fqctx = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withFqNModCtx fqctx $ \fqctx -> do+ fq_nmod_mpoly_ctx_init p nvars ord fqctx+ addForeignPtrFinalizer p_fq_nmod_mpoly_ctx_clear p+ return $ FqNModMPolyCtx p++-- | Use a `FqNModMPolyCtx`+{-# INLINE withFqNModMPolyCtx #-}+withFqNModMPolyCtx (FqNModMPolyCtx p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FqNModMPolyCtx p,)++-- Context object --------------------------------------------------------------++-- | /fq_nmod_mpoly_ctx_init/ /ctx/ /nvars/ /ord/ /fqctx/ +--+-- Initialise a context object for a polynomial ring with the given number+-- of variables and the given ordering. It will have coefficients in the+-- finite field /fqctx/. The possibilities for the ordering are @ORD_LEX@,+-- @ORD_DEGLEX@ and @ORD_DEGREVLEX@.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_ctx_init"+ fq_nmod_mpoly_ctx_init :: Ptr CFqNModMPolyCtx -> CLong -> Ptr COrdering -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mpoly_ctx_nvars/ /ctx/ +--+-- Return the number of variables used to initialize the context.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_ctx_nvars"+ fq_nmod_mpoly_ctx_nvars :: Ptr CFqNModMPolyCtx -> IO CLong++-- | /fq_nmod_mpoly_ctx_ord/ /ctx/ +--+-- Return the ordering used to initialize the context.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_ctx_ord"+ fq_nmod_mpoly_ctx_ord :: Ptr CFqNModMPolyCtx -> IO (Ptr COrdering)++-- | /fq_nmod_mpoly_ctx_clear/ /ctx/ +--+-- Release any space allocated by an /ctx/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_ctx_clear"+ fq_nmod_mpoly_ctx_clear :: Ptr CFqNModMPolyCtx -> IO ()++foreign import ccall "fq_nmod_mpoly.h &fq_nmod_mpoly_ctx_clear"+ p_fq_nmod_mpoly_ctx_clear :: FunPtr (Ptr CFqNModMPolyCtx -> IO ())++-- Memory management -----------------------------------------------------------++-- | /fq_nmod_mpoly_init/ /A/ /ctx/ +--+-- Initialise /A/ for use with the given an initialised context object. Its+-- value is set to zero.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_init"+ fq_nmod_mpoly_init :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_init2/ /A/ /alloc/ /ctx/ +--+-- Initialise /A/ for use with the given an initialised context object. Its+-- value is set to zero. It is allocated with space for /alloc/ terms and+-- at least @MPOLY_MIN_BITS@ bits for the exponents.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_init2"+ fq_nmod_mpoly_init2 :: Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_init3/ /A/ /alloc/ /bits/ /ctx/ +--+-- Initialise /A/ for use with the given an initialised context object. Its+-- value is set to zero. It is allocated with space for /alloc/ terms and+-- /bits/ bits for the exponents.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_init3"+ fq_nmod_mpoly_init3 :: Ptr CFqNModMPoly -> CLong -> CFBitCnt -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_fit_length/ /A/ /len/ /ctx/ +--+-- Ensure that /A/ has space for at least /len/ terms.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_fit_length"+ fq_nmod_mpoly_fit_length :: Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_realloc/ /A/ /alloc/ /ctx/ +--+-- Reallocate /A/ to have space for /alloc/ terms. Assumes the current+-- length of the polynomial is not greater than /alloc/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_realloc"+ fq_nmod_mpoly_realloc :: Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_clear/ /A/ /ctx/ +--+-- Release any space allocated for /A/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_clear"+ fq_nmod_mpoly_clear :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++foreign import ccall "fq_nmod_mpoly.h &fq_nmod_mpoly_clear"+ p_fq_nmod_mpoly_clear :: FunPtr (Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ())++-- Input\/Output ---------------------------------------------------------------++-- | /fq_nmod_mpoly_get_str_pretty/ /A/ /x/ /ctx/ +--+-- Return a string, which the user is responsible for cleaning up,+-- representing /A/, given an array of variable strings /x/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_str_pretty"+ fq_nmod_mpoly_get_str_pretty :: Ptr CFqNModMPoly -> Ptr CString -> Ptr CFqNModMPolyCtx -> IO CString++-- | /fq_nmod_mpoly_fprint_pretty/ /file/ /A/ /x/ /ctx/ +--+-- Print a string representing /A/ to /file/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_fprint_pretty"+ fq_nmod_mpoly_fprint_pretty :: Ptr CFile -> Ptr CFqNModMPoly -> Ptr CString -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_print_pretty/ /A/ /x/ /ctx/ +--+-- Print a string representing /A/ to @stdout@.+fq_nmod_mpoly_print_pretty :: Ptr CFqNModMPoly -> Ptr CString -> Ptr CFqNModMPolyCtx -> IO CInt+fq_nmod_mpoly_print_pretty a x ctx =+ printCStr (\a -> fq_nmod_mpoly_get_str_pretty a x ctx) a++-- | /fq_nmod_mpoly_set_str_pretty/ /A/ /str/ /x/ /ctx/ +--+-- Set /A/ to the polynomial in the null-terminates string /str/ given an+-- array /x/ of variable strings. If parsing /str/ fails, /A/ is set to+-- zero, and \(-1\) is returned. Otherwise, \(0\) is returned. The+-- operations @+@, @-@, @*@, and @\/@ are permitted along with integers and+-- the variables in /x/. The character @^@ must be immediately followed by+-- the (integer) exponent. If any division is not exact, parsing fails.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_set_str_pretty"+ fq_nmod_mpoly_set_str_pretty :: Ptr CFqNModMPoly -> CString -> Ptr CString -> Ptr CFqNModMPolyCtx -> IO CInt++-- Basic manipulation ----------------------------------------------------------++-- | /fq_nmod_mpoly_gen/ /A/ /var/ /ctx/ +--+-- Set /A/ to the variable of index /var/, where \(var = 0\) corresponds to+-- the variable with the most significance with respect to the ordering.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_gen"+ fq_nmod_mpoly_gen :: Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_is_gen/ /A/ /var/ /ctx/ +--+-- If \(var \ge 0\), return \(1\) if /A/ is equal to the \(var\)-th+-- generator, otherwise return \(0\). If \(var < 0\), return \(1\) if the+-- polynomial is equal to any generator, otherwise return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_is_gen"+ fq_nmod_mpoly_is_gen :: Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_set/ /A/ /B/ /ctx/ +--+-- Set /A/ to /B/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_set"+ fq_nmod_mpoly_set :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_equal/ /A/ /B/ /ctx/ +--+-- Return \(1\) if /A/ is equal to /B/, else return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_equal"+ fq_nmod_mpoly_equal :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_swap/ /A/ /B/ /ctx/ +--+-- Efficiently swap /A/ and /B/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_swap"+ fq_nmod_mpoly_swap :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- Constants -------------------------------------------------------------------++-- | /fq_nmod_mpoly_is_fq_nmod/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is a constant, else return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_is_fq_nmod"+ fq_nmod_mpoly_is_fq_nmod :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_get_fq_nmod/ /c/ /A/ /ctx/ +--+-- Assuming that /A/ is a constant, set /c/ to this constant. This function+-- throws if /A/ is not a constant.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_fq_nmod"+ fq_nmod_mpoly_get_fq_nmod :: Ptr CFqNMod -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_set_fq_nmod/ /A/ /c/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_set_fq_nmod"+ fq_nmod_mpoly_set_fq_nmod :: Ptr CFqNModMPoly -> Ptr CFqNMod -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_set_ui/ /A/ /c/ /ctx/ +--+-- Set /A/ to the constant /c/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_set_ui"+ fq_nmod_mpoly_set_ui :: Ptr CFqNModMPoly -> CULong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_set_fq_nmod_gen/ /A/ /ctx/ +--+-- Set /A/ to the constant given by @fq_nmod_gen@.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_set_fq_nmod_gen"+ fq_nmod_mpoly_set_fq_nmod_gen :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_zero/ /A/ /ctx/ +--+-- Set /A/ to the constant \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_zero"+ fq_nmod_mpoly_zero :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_one/ /A/ /ctx/ +--+-- Set /A/ to the constant \(1\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_one"+ fq_nmod_mpoly_one :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_equal_fq_nmod/ /A/ /c/ /ctx/ +--+-- Return \(1\) if /A/ is equal to the constant /c/, else return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_equal_fq_nmod"+ fq_nmod_mpoly_equal_fq_nmod :: Ptr CFqNModMPoly -> Ptr CFqNMod -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_is_zero/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is the constant \(0\), else return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_is_zero"+ fq_nmod_mpoly_is_zero :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_is_one/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is the constant \(1\), else return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_is_one"+ fq_nmod_mpoly_is_one :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- Degrees ---------------------------------------------------------------------++-- | /fq_nmod_mpoly_degrees_fit_si/ /A/ /ctx/ +--+-- Return \(1\) if the degrees of /A/ with respect to each variable fit+-- into an @slong@, otherwise return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_degrees_fit_si"+ fq_nmod_mpoly_degrees_fit_si :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_degrees_fmpz/ /degs/ /A/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_degrees_fmpz"+ fq_nmod_mpoly_degrees_fmpz :: Ptr (Ptr CFmpz) -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_degrees_si/ /degs/ /A/ /ctx/ +--+-- Set /degs/ to the degrees of /A/ with respect to each variable. If /A/+-- is zero, all degrees are set to \(-1\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_degrees_si"+ fq_nmod_mpoly_degrees_si :: Ptr CLong -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_degree_fmpz/ /deg/ /A/ /var/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_degree_fmpz"+ fq_nmod_mpoly_degree_fmpz :: Ptr CFmpz -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_degree_si/ /A/ /var/ /ctx/ +--+-- Either return or set /deg/ to the degree of /A/ with respect to the+-- variable of index /var/. If /A/ is zero, the degree is defined to be+-- \(-1\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_degree_si"+ fq_nmod_mpoly_degree_si :: Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO CLong++-- | /fq_nmod_mpoly_total_degree_fits_si/ /A/ /ctx/ +--+-- Return \(1\) if the total degree of /A/ fits into an @slong@, otherwise+-- return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_total_degree_fits_si"+ fq_nmod_mpoly_total_degree_fits_si :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_total_degree_fmpz/ /tdeg/ /A/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_total_degree_fmpz"+ fq_nmod_mpoly_total_degree_fmpz :: Ptr CFmpz -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_total_degree_si/ /A/ /ctx/ +--+-- Either return or set /tdeg/ to the total degree of /A/. If /A/ is zero,+-- the total degree is defined to be \(-1\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_total_degree_si"+ fq_nmod_mpoly_total_degree_si :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CLong++-- | /fq_nmod_mpoly_used_vars/ /used/ /A/ /ctx/ +--+-- For each variable index \(i\), set @used[i]@ to nonzero if the variable+-- of index \(i\) appears in /A/ and to zero otherwise.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_used_vars"+ fq_nmod_mpoly_used_vars :: Ptr CInt -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- Coefficients ----------------------------------------------------------------++-- | /fq_nmod_mpoly_get_coeff_fq_nmod_monomial/ /c/ /A/ /M/ /ctx/ +--+-- Assuming that /M/ is a monomial, set /c/ to the coefficient of the+-- corresponding monomial in /A/. This function throws if /M/ is not a+-- monomial.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_coeff_fq_nmod_monomial"+ fq_nmod_mpoly_get_coeff_fq_nmod_monomial :: Ptr CFqNMod -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_set_coeff_fq_nmod_monomial/ /A/ /c/ /M/ /ctx/ +--+-- Assuming that /M/ is a monomial, set the coefficient of the+-- corresponding monomial in /A/ to /c/. This function throws if /M/ is not+-- a monomial.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_set_coeff_fq_nmod_monomial"+ fq_nmod_mpoly_set_coeff_fq_nmod_monomial :: Ptr CFqNModMPoly -> Ptr CFqNMod -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_get_coeff_fq_nmod_fmpz/ /c/ /A/ /exp/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_coeff_fq_nmod_fmpz"+ fq_nmod_mpoly_get_coeff_fq_nmod_fmpz :: Ptr CFqNMod -> Ptr CFqNModMPoly -> Ptr (Ptr CFmpz) -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_get_coeff_fq_nmod_ui/ /c/ /A/ /exp/ /ctx/ +--+-- Set /c/ to the coefficient of the monomial with exponent vector /exp/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_coeff_fq_nmod_ui"+ fq_nmod_mpoly_get_coeff_fq_nmod_ui :: Ptr CFqNMod -> Ptr CFqNModMPoly -> Ptr CULong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_set_coeff_fq_nmod_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_set_coeff_fq_nmod_fmpz"+ fq_nmod_mpoly_set_coeff_fq_nmod_fmpz :: Ptr CFqNModMPoly -> Ptr CFqNMod -> Ptr (Ptr CFmpz) -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_set_coeff_fq_nmod_ui/ /A/ /c/ /exp/ /ctx/ +--+-- Set the coefficient of the monomial with exponent /exp/ to /c/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_set_coeff_fq_nmod_ui"+ fq_nmod_mpoly_set_coeff_fq_nmod_ui :: Ptr CFqNModMPoly -> Ptr CFqNMod -> Ptr CULong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_get_coeff_vars_ui/ /C/ /A/ /vars/ /exps/ /length/ /ctx/ +--+-- Set /C/ to the coefficient of /A/ with respect to the variables in+-- /vars/ with powers in the corresponding array /exps/. Both /vars/ and+-- /exps/ point to array of length /length/. It is assumed that+-- \(0 < length \le nvars(A)\) and that the variables in /vars/ are+-- distinct.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_coeff_vars_ui"+ fq_nmod_mpoly_get_coeff_vars_ui :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CLong -> Ptr CULong -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fq_nmod_mpoly_cmp/ /A/ /B/ /ctx/ +--+-- Return \(1\) (resp. \(-1\), or \(0\)) if /A/ is after (resp. before,+-- same as) /B/ in some arbitrary but fixed total ordering of the+-- polynomials. This ordering agrees with the usual ordering of monomials+-- when /A/ and /B/ are both monomials.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_cmp"+ fq_nmod_mpoly_cmp :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- Container operations --------------------------------------------------------++-- | /fq_nmod_mpoly_is_canonical/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is in canonical form. Otherwise, return \(0\). To be+-- in canonical form, all of the terms must have nonzero coefficients, and+-- the terms must be sorted from greatest to least.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_is_canonical"+ fq_nmod_mpoly_is_canonical :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_length/ /A/ /ctx/ +--+-- Return the number of terms in /A/. If the polynomial is in canonical+-- form, this will be the number of nonzero coefficients.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_length"+ fq_nmod_mpoly_length :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CLong++-- | /fq_nmod_mpoly_resize/ /A/ /new_length/ /ctx/ +--+-- Set the length of /A/ to @new_length@. Terms are either deleted from the+-- end, or new zero terms are appended.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_resize"+ fq_nmod_mpoly_resize :: Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_get_term_coeff_fq_nmod/ /c/ /A/ /i/ /ctx/ +--+-- Set /c/ to the coefficient of the term of index /i/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_term_coeff_fq_nmod"+ fq_nmod_mpoly_get_term_coeff_fq_nmod :: Ptr CFqNMod -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- -- | /fq_nmod_mpoly_set_term_coeff_ui/ /A/ /i/ /c/ /ctx/ +-- --+-- -- Set the coefficient of the term of index /i/ to /c/.+-- foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_set_term_coeff_ui"+-- fq_nmod_mpoly_set_term_coeff_ui :: Ptr CFqNModMPoly -> CLong -> CULong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_term_exp_fits_si/ /A/ /i/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_term_exp_fits_si"+ fq_nmod_mpoly_term_exp_fits_si :: Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO CInt+-- | /fq_nmod_mpoly_term_exp_fits_ui/ /A/ /i/ /ctx/ +--+-- Return \(1\) if all entries of the exponent vector of the term of index+-- \(i\) fit into an @slong@ (resp. a @ulong@). Otherwise, return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_term_exp_fits_ui"+ fq_nmod_mpoly_term_exp_fits_ui :: Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_get_term_exp_fmpz/ /exp/ /A/ /i/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_term_exp_fmpz"+ fq_nmod_mpoly_get_term_exp_fmpz :: Ptr (Ptr CFmpz) -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_get_term_exp_ui/ /exp/ /A/ /i/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_term_exp_ui"+ fq_nmod_mpoly_get_term_exp_ui :: Ptr CULong -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_get_term_exp_si/ /exp/ /A/ /i/ /ctx/ +--+-- Set /exp/ to the exponent vector of the term of index /i/. The @_ui@+-- (resp. @_si@) version throws if any entry does not fit into a @ulong@+-- (resp. @slong@).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_term_exp_si"+ fq_nmod_mpoly_get_term_exp_si :: Ptr CLong -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_get_term_var_exp_ui/ /A/ /i/ /var/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_term_var_exp_ui"+ fq_nmod_mpoly_get_term_var_exp_ui :: Ptr CFqNModMPoly -> CLong -> CLong -> Ptr CFqNModMPolyCtx -> IO CULong+-- | /fq_nmod_mpoly_get_term_var_exp_si/ /A/ /i/ /var/ /ctx/ +--+-- Return the exponent of the variable /var/ of the term of index /i/. This+-- function throws if the exponent does not fit into a @ulong@ (resp.+-- @slong@).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_term_var_exp_si"+ fq_nmod_mpoly_get_term_var_exp_si :: Ptr CFqNModMPoly -> CLong -> CLong -> Ptr CFqNModMPolyCtx -> IO CLong++-- | /fq_nmod_mpoly_set_term_exp_fmpz/ /A/ /i/ /exp/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_set_term_exp_fmpz"+ fq_nmod_mpoly_set_term_exp_fmpz :: Ptr CFqNModMPoly -> CLong -> Ptr (Ptr CFmpz) -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_set_term_exp_ui/ /A/ /i/ /exp/ /ctx/ +--+-- Set the exponent of the term of index /i/ to /exp/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_set_term_exp_ui"+ fq_nmod_mpoly_set_term_exp_ui :: Ptr CFqNModMPoly -> CLong -> Ptr CULong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_get_term/ /M/ /A/ /i/ /ctx/ +--+-- Set /M/ to the term of index /i/ in /A/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_term"+ fq_nmod_mpoly_get_term :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_get_term_monomial/ /M/ /A/ /i/ /ctx/ +--+-- Set /M/ to the monomial of the term of index /i/ in /A/. The coefficient+-- of /M/ will be one.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_get_term_monomial"+ fq_nmod_mpoly_get_term_monomial :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_push_term_fq_nmod_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_push_term_fq_nmod_fmpz"+ fq_nmod_mpoly_push_term_fq_nmod_fmpz :: Ptr CFqNModMPoly -> Ptr CFqNMod -> Ptr (Ptr CFmpz) -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_push_term_fq_nmod_ui/ /A/ /c/ /exp/ /ctx/ +--+-- Append a term to /A/ with coefficient /c/ and exponent vector /exp/.+-- This function runs in constant average time.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_push_term_fq_nmod_ui"+ fq_nmod_mpoly_push_term_fq_nmod_ui :: Ptr CFqNModMPoly -> Ptr CFqNMod -> Ptr CULong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_sort_terms/ /A/ /ctx/ +--+-- Sort the terms of /A/ into the canonical ordering dictated by the+-- ordering in /ctx/. This function simply reorders the terms: It does not+-- combine like terms, nor does it delete terms with coefficient zero. This+-- function runs in linear time in the bit size of /A/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_sort_terms"+ fq_nmod_mpoly_sort_terms :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_combine_like_terms/ /A/ /ctx/ +--+-- Combine adjacent like terms in /A/ and delete terms with coefficient+-- zero. If the terms of /A/ were sorted to begin with, the result will be+-- in canonical form. This function runs in linear time in the bit size of+-- /A/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_combine_like_terms"+ fq_nmod_mpoly_combine_like_terms :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_reverse/ /A/ /B/ /ctx/ +--+-- Set /A/ to the reversal of /B/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_reverse"+ fq_nmod_mpoly_reverse :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- Random generation -----------------------------------------------------------++-- | /fq_nmod_mpoly_randtest_bound/ /A/ /state/ /length/ /exp_bound/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents in+-- the range @[0, exp_bound - 1]@. The exponents of each variable are+-- generated by calls to @n_randint(state, exp_bound)@.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_randtest_bound"+ fq_nmod_mpoly_randtest_bound :: Ptr CFqNModMPoly -> Ptr CFRandState -> CLong -> CULong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_randtest_bounds/ /A/ /state/ /length/ /exp_bounds/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents in+-- the range @[0, exp_bounds[i] - 1]@. The exponents of the variable of+-- index /i/ are generated by calls to @n_randint(state, exp_bounds[i])@.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_randtest_bounds"+ fq_nmod_mpoly_randtest_bounds :: Ptr CFqNModMPoly -> Ptr CFRandState -> CLong -> CULong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_randtest_bits/ /A/ /state/ /length/ /exp_bits/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents+-- whose packed form does not exceed the given bit count.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_randtest_bits"+ fq_nmod_mpoly_randtest_bits :: Ptr CFqNModMPoly -> Ptr CFRandState -> CLong -> CMpLimb -> Ptr CFqNModMPolyCtx -> IO ()++-- Addition\/Subtraction -------------------------------------------------------++-- | /fq_nmod_mpoly_add_fq_nmod/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B + c\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_add_fq_nmod"+ fq_nmod_mpoly_add_fq_nmod :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNMod -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_sub_fq_nmod/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B - c\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_sub_fq_nmod"+ fq_nmod_mpoly_sub_fq_nmod :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNMod -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_add/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B + C\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_add"+ fq_nmod_mpoly_add :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_sub/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B - C\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_sub"+ fq_nmod_mpoly_sub :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- Scalar operations -----------------------------------------------------------++-- | /fq_nmod_mpoly_neg/ /A/ /B/ /ctx/ +--+-- Set /A/ to \(-B\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_neg"+ fq_nmod_mpoly_neg :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_scalar_mul_fq_nmod/ /A/ /B/ /c/ /ctx/ +--+-- Set /A/ to \(B \times c\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_scalar_mul_fq_nmod"+ fq_nmod_mpoly_scalar_mul_fq_nmod :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNMod -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_make_monic/ /A/ /B/ /ctx/ +--+-- Set /A/ to /B/ divided by the leading coefficient of /B/. This throws if+-- /B/ is zero.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_make_monic"+ fq_nmod_mpoly_make_monic :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- Differentiation -------------------------------------------------------------++-- | /fq_nmod_mpoly_derivative/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to the derivative of /B/ with respect to the variable of index+-- /var/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_derivative"+ fq_nmod_mpoly_derivative :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- Evaluation ------------------------------------------------------------------++-- | /fq_nmod_mpoly_evaluate_all_fq_nmod/ /ev/ /A/ /vals/ /ctx/ +--+-- Set /ev/ the evaluation of /A/ where the variables are replaced by the+-- corresponding elements of the array /vals/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_evaluate_all_fq_nmod"+ fq_nmod_mpoly_evaluate_all_fq_nmod :: Ptr CFqNMod -> Ptr CFqNModMPoly -> Ptr (Ptr (Ptr CFqNMod)) -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_evaluate_one_fq_nmod/ /A/ /B/ /var/ /val/ /ctx/ +--+-- Set /A/ to the evaluation of /B/ where the variable of index /var/ is+-- replaced by /val/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_evaluate_one_fq_nmod"+ fq_nmod_mpoly_evaluate_one_fq_nmod :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNMod -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_compose_fq_nmod_poly/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to the evaluation of /B/ where the variables are replaced by the+-- corresponding elements of the array /C/. The context object of /B/ is+-- /ctxB/. Return \(1\) for success and \(0\) for failure.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_compose_fq_nmod_poly"+ fq_nmod_mpoly_compose_fq_nmod_poly :: Ptr CFqNModPoly -> Ptr CFqNModMPoly -> Ptr (Ptr (Ptr CFqNModPoly)) -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_compose_fq_nmod_mpoly/ /A/ /B/ /C/ /ctxB/ /ctxAC/ +--+-- Set /A/ to the evaluation of /B/ where the variables are replaced by the+-- corresponding elements of the array /C/. Both /A/ and the elements of+-- /C/ have context object /ctxAC/, while /B/ has context object /ctxB/.+-- Neither /A/ nor /B/ is allowed to alias any other polynomial. Return+-- \(1\) for success and \(0\) for failure.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_compose_fq_nmod_mpoly"+ fq_nmod_mpoly_compose_fq_nmod_mpoly :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr (Ptr (Ptr CFqNModMPoly)) -> Ptr CFqNModMPolyCtx -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_compose_fq_nmod_mpoly_gen/ /A/ /B/ /c/ /ctxB/ /ctxAC/ +--+-- Set /A/ to the evaluation of /B/ where the variable of index /i/ in+-- /ctxB/ is replaced by the variable of index @c[i]@ in /ctxAC/. The+-- length of the array /C/ is the number of variables in /ctxB/. If any+-- @c[i]@ is negative, the corresponding variable of /B/ is replaced by+-- zero. Otherwise, it is expected that @c[i]@ is less than the number of+-- variables in /ctxAC/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_compose_fq_nmod_mpoly_gen"+ fq_nmod_mpoly_compose_fq_nmod_mpoly_gen :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CLong -> Ptr CFqNModMPolyCtx -> Ptr CFqNModMPolyCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /fq_nmod_mpoly_mul/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to /B/ times /C/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_mul"+ fq_nmod_mpoly_mul :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- Powering --------------------------------------------------------------------++-- | /fq_nmod_mpoly_pow_fmpz/ /A/ /B/ /k/ /ctx/ +--+-- Set /A/ to \(B\) raised to the /k/-th power. Return \(1\) for success+-- and \(0\) for failure.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_pow_fmpz"+ fq_nmod_mpoly_pow_fmpz :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFmpz -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_pow_ui/ /A/ /B/ /k/ /ctx/ +--+-- Set /A/ to \(B\) raised to the /k/-th power. Return \(1\) for success+-- and \(0\) for failure.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_pow_ui"+ fq_nmod_mpoly_pow_ui :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> CULong -> Ptr CFqNModMPolyCtx -> IO CInt++-- Division --------------------------------------------------------------------++-- | /fq_nmod_mpoly_divides/ /Q/ /A/ /B/ /ctx/ +--+-- If /A/ is divisible by /B/, set /Q/ to the exact quotient and return+-- \(1\). Otherwise, set /Q/ to zero and return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_divides"+ fq_nmod_mpoly_divides :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_div/ /Q/ /A/ /B/ /ctx/ +--+-- Set /Q/ to the quotient of /A/ by /B/, discarding the remainder.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_div"+ fq_nmod_mpoly_div :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_divrem/ /Q/ /R/ /A/ /B/ /ctx/ +--+-- Set /Q/ and /R/ to the quotient and remainder of /A/ divided by /B/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_divrem"+ fq_nmod_mpoly_divrem :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_divrem_ideal/ /Q/ /R/ /A/ /B/ /len/ /ctx/ +--+-- This function is as per @fq_nmod_mpoly_divrem@ except that it takes an+-- array of divisor polynomials /B/ and it returns an array of quotient+-- polynomials /Q/. The number of divisor (and hence quotient) polynomials,+-- is given by /len/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_divrem_ideal"+ fq_nmod_mpoly_divrem_ideal :: Ptr (Ptr (Ptr CFqNModMPoly)) -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr (Ptr (Ptr CFqNModMPoly)) -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- Greatest Common Divisor -----------------------------------------------------++-- | /fq_nmod_mpoly_term_content/ /M/ /A/ /ctx/ +--+-- Set /M/ to the GCD of the terms of /A/. If /A/ is zero, /M/ will be+-- zero. Otherwise, /M/ will be a monomial with coefficient one.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_term_content"+ fq_nmod_mpoly_term_content :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_content_vars/ /g/ /A/ /vars/ /vars_length/ /ctx/ +--+-- Set /g/ to the GCD of the coefficients of /A/ when viewed as a+-- polynomial in the variables /vars/. Return \(1\) for success and \(0\)+-- for failure. Upon success, /g/ will be independent of the variables+-- /vars/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_content_vars"+ fq_nmod_mpoly_content_vars :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CLong -> CLong -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_gcd/ /G/ /A/ /B/ /ctx/ +--+-- Try to set /G/ to the monic GCD of /A/ and /B/. The GCD of zero and zero+-- is defined to be zero. If the return is \(1\) the function was+-- successful. Otherwise the return is \(0\) and /G/ is left untouched.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_gcd"+ fq_nmod_mpoly_gcd :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_gcd_cofactors/ /G/ /Abar/ /Bbar/ /A/ /B/ /ctx/ +--+-- Do the operation of @fq_nmod_mpoly_gcd@ and also compute \(Abar = A/G\)+-- and \(Bbar = B/G\) if successful.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_gcd_cofactors"+ fq_nmod_mpoly_gcd_cofactors :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_gcd_brown/ /G/ /A/ /B/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_gcd_brown"+ fq_nmod_mpoly_gcd_brown :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt+-- | /fq_nmod_mpoly_gcd_hensel/ /G/ /A/ /B/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_gcd_hensel"+ fq_nmod_mpoly_gcd_hensel :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt+-- | /fq_nmod_mpoly_gcd_zippel/ /G/ /A/ /B/ /ctx/ +--+-- Try to set /G/ to the GCD of /A/ and /B/ using various algorithms.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_gcd_zippel"+ fq_nmod_mpoly_gcd_zippel :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_resultant/ /R/ /A/ /B/ /var/ /ctx/ +--+-- Try to set /R/ to the resultant of /A/ and /B/ with respect to the+-- variable of index /var/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_resultant"+ fq_nmod_mpoly_resultant :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_discriminant/ /D/ /A/ /var/ /ctx/ +--+-- Try to set /D/ to the discriminant of /A/ with respect to the variable+-- of index /var/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_discriminant"+ fq_nmod_mpoly_discriminant :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO CInt++-- Square Root -----------------------------------------------------------------++-- | /fq_nmod_mpoly_sqrt/ /Q/ /A/ /ctx/ +--+-- If \(Q^2=A\) has a solution, set \(Q\) to a solution and return \(1\),+-- otherwise return \(0\) and set \(Q\) to zero.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_sqrt"+ fq_nmod_mpoly_sqrt :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_is_square/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is a perfect square, otherwise return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_is_square"+ fq_nmod_mpoly_is_square :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_quadratic_root/ /Q/ /A/ /B/ /ctx/ +--+-- If \(Q^2+AQ=B\) has a solution, set \(Q\) to a solution and return+-- \(1\), otherwise return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_quadratic_root"+ fq_nmod_mpoly_quadratic_root :: Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- Univariate Functions --------------------------------------------------------++-- | /fq_nmod_mpoly_univar_init/ /A/ /ctx/ +--+-- Initialize /A/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_univar_init"+ fq_nmod_mpoly_univar_init :: Ptr CFqNModMPolyUnivar -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_univar_clear/ /A/ /ctx/ +--+-- Clear /A/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_univar_clear"+ fq_nmod_mpoly_univar_clear :: Ptr CFqNModMPolyUnivar -> Ptr CFqNModMPolyCtx -> IO ()++foreign import ccall "fq_nmod_mpoly.h &fq_nmod_mpoly_univar_clear"+ p_fq_nmod_mpoly_univar_clear :: FunPtr (Ptr CFqNModMPolyUnivar -> Ptr CFqNModMPolyCtx -> IO ())++-- | /fq_nmod_mpoly_univar_swap/ /A/ /B/ /ctx/ +--+-- Swap /A/ and \(B\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_univar_swap"+ fq_nmod_mpoly_univar_swap :: Ptr CFqNModMPolyUnivar -> Ptr CFqNModMPolyUnivar -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_to_univar/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to a univariate form of /B/ by pulling out the variable of index+-- /var/. The coefficients of /A/ will still belong to the content /ctx/+-- but will not depend on the variable of index /var/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_to_univar"+ fq_nmod_mpoly_to_univar :: Ptr CFqNModMPolyUnivar -> Ptr CFqNModMPoly -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_from_univar/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to the normal form of /B/ by putting in the variable of index+-- /var/. This function is undefined if the coefficients of /B/ depend on+-- the variable of index /var/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_from_univar"+ fq_nmod_mpoly_from_univar :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyUnivar -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_univar_degree_fits_si/ /A/ /ctx/ +--+-- Return \(1\) if the degree of /A/ with respect to the main variable fits+-- an @slong@. Otherwise, return \(0\).+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_univar_degree_fits_si"+ fq_nmod_mpoly_univar_degree_fits_si :: Ptr CFqNModMPolyUnivar -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_univar_length/ /A/ /ctx/ +--+-- Return the number of terms in /A/ with respect to the main variable.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_univar_length"+ fq_nmod_mpoly_univar_length :: Ptr CFqNModMPolyUnivar -> Ptr CFqNModMPolyCtx -> IO CLong++-- | /fq_nmod_mpoly_univar_get_term_exp_si/ /A/ /i/ /ctx/ +--+-- Return the exponent of the term of index /i/ of /A/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_univar_get_term_exp_si"+ fq_nmod_mpoly_univar_get_term_exp_si :: Ptr CFqNModMPolyUnivar -> CLong -> Ptr CFqNModMPolyCtx -> IO CLong++-- | /fq_nmod_mpoly_univar_get_term_coeff/ /c/ /A/ /i/ /ctx/ +foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_univar_get_term_coeff"+ fq_nmod_mpoly_univar_get_term_coeff :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyUnivar -> CLong -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_univar_swap_term_coeff/ /c/ /A/ /i/ /ctx/ +--+-- Set (resp. swap) /c/ to (resp. with) the coefficient of the term of+-- index /i/ of /A/.+foreign import ccall "fq_nmod_mpoly.h fq_nmod_mpoly_univar_swap_term_coeff"+ fq_nmod_mpoly_univar_swap_term_coeff :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyUnivar -> CLong -> Ptr CFqNModMPolyCtx -> IO ()+
+ src/Data/Number/Flint/Fq/NMod/MPoly/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fq.NMod.MPoly.Factor (+ module Data.Number.Flint.Fq.NMod.MPoly.Factor.FFI+ ) where++import Data.Number.Flint.Fq.NMod.MPoly.Factor.FFI
+ src/Data/Number/Flint/Fq/NMod/MPoly/Factor/FFI.hsc view
@@ -0,0 +1,167 @@+{-|+module : Data.Number.Flint.Fq.NMod.MPoly.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.NMod.MPoly.Factor.FFI (+ -- * Factorisation of multivariate polynomials over finite fields of+ -- word-sized characteristic+ FqNModMPolyFactor (..)+ , CFqNModMPolyFactor (..)+ , newFqNModMPolyFactor+ , withFqNModMPolyFactor + -- * Memory management+ , fq_nmod_mpoly_factor_init+ , fq_nmod_mpoly_factor_clear+ -- * Basic manipulation+ , fq_nmod_mpoly_factor_swap+ , fq_nmod_mpoly_factor_length+ , fq_nmod_mpoly_factor_get_constant_fq_nmod+ , fq_nmod_mpoly_factor_get_base+ , fq_nmod_mpoly_factor_swap_base+ , fq_nmod_mpoly_factor_get_exp_si+ , fq_nmod_mpoly_factor_sort+ -- * Factorisation+ , fq_nmod_mpoly_factor_squarefree+ , fq_nmod_mpoly_factor+) where++-- Factorisation of multivariate polynomials over finite fields of+-- word-sized characteristic++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.MPoly+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mod.Poly+import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.NMod.MPoly+import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.Poly+import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.MPoly+import Data.Number.Flint.Fq.NMod.Types++#include <flint/flint.h>+#include <flint/fq.h>+#include <flint/fq_nmod.h>+#include <flint/fq_nmod_poly.h>+#include <flint/fq_nmod_mpoly_factor.h>++-- fq_nmod_mpoly_factor_t ------------------------------------------------------++data FqNModMPolyFactor =+ FqNModMPolyFactor {-# UNPACK #-} !(ForeignPtr CFqNModMPolyFactor)+data CFqNModMPolyFactor =+ CFqNModMPolyFactor (Ptr CFqNMod) (Ptr CFqNModMPoly) (Ptr CFmpz) CLong CLong++instance Storable CFqNModMPolyFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_nmod_mpoly_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_nmod_mpoly_factor_t}+ peek ptr = CFqNModMPolyFactor+ <$> #{peek fq_nmod_mpoly_factor_struct, constant} ptr+ <*> #{peek fq_nmod_mpoly_factor_struct, poly } ptr+ <*> #{peek fq_nmod_mpoly_factor_struct, exp } ptr+ <*> #{peek fq_nmod_mpoly_factor_struct, num } ptr+ <*> #{peek fq_nmod_mpoly_factor_struct, alloc } ptr+ poke = error "CFqNModMPolyFactor.poke: Not defined"++newFqNModMPolyFactor ctx@(FqNModMPolyCtx fctx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqNModMPolyCtx ctx $ \ctx -> do+ fq_nmod_mpoly_factor_init x ctx+ addForeignPtrFinalizerEnv p_fq_nmod_mpoly_factor_clear x fctx+ return $ FqNModMPolyFactor x++withFqNModMPolyFactor (FqNModMPolyFactor p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (FqNModMPolyFactor p,)+ +-- Memory management -----------------------------------------------------------++-- | /fq_nmod_mpoly_factor_init/ /f/ /ctx/ +--+-- Initialise /f/.+foreign import ccall "fq_nmod_mpoly_factor.h fq_nmod_mpoly_factor_init"+ fq_nmod_mpoly_factor_init :: Ptr CFqNModMPolyFactor -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_factor_clear/ /f/ /ctx/ +--+-- Clear /f/.+foreign import ccall "fq_nmod_mpoly_factor.h fq_nmod_mpoly_factor_clear"+ fq_nmod_mpoly_factor_clear :: Ptr CFqNModMPolyFactor -> Ptr CFqNModMPolyCtx -> IO ()++foreign import ccall "fq_nmod_mpoly_factor.h &fq_nmod_mpoly_factor_clear"+ p_fq_nmod_mpoly_factor_clear :: FunPtr (Ptr CFqNModMPolyFactor -> Ptr CFqNModMPolyCtx -> IO ())++-- Basic manipulation ----------------------------------------------------------++-- | /fq_nmod_mpoly_factor_swap/ /f/ /g/ /ctx/ +--+-- Efficiently swap /f/ and /g/.+foreign import ccall "fq_nmod_mpoly_factor.h fq_nmod_mpoly_factor_swap"+ fq_nmod_mpoly_factor_swap :: Ptr CFqNModMPolyFactor -> Ptr CFqNModMPolyFactor -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_factor_length/ /f/ /ctx/ +--+-- Return the length of the product in /f/.+foreign import ccall "fq_nmod_mpoly_factor.h fq_nmod_mpoly_factor_length"+ fq_nmod_mpoly_factor_length :: Ptr CFqNModMPolyFactor -> Ptr CFqNModMPolyCtx -> IO CLong++-- | /fq_nmod_mpoly_factor_get_constant_fq_nmod/ /c/ /f/ /ctx/ +--+-- Set \(c\) to the constant of /f/.+foreign import ccall "fq_nmod_mpoly_factor.h fq_nmod_mpoly_factor_get_constant_fq_nmod"+ fq_nmod_mpoly_factor_get_constant_fq_nmod :: Ptr CFqNMod -> Ptr CFqNModMPolyFactor -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_factor_get_base/ /p/ /f/ /i/ /ctx/ +foreign import ccall "fq_nmod_mpoly_factor.h fq_nmod_mpoly_factor_get_base"+ fq_nmod_mpoly_factor_get_base :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyFactor -> CLong -> Ptr CFqNModMPolyCtx -> IO ()+-- | /fq_nmod_mpoly_factor_swap_base/ /p/ /f/ /i/ /ctx/ +--+-- Set (resp. swap) /B/ to (resp. with) the base of the term of index /i/+-- in /A/.+foreign import ccall "fq_nmod_mpoly_factor.h fq_nmod_mpoly_factor_swap_base"+ fq_nmod_mpoly_factor_swap_base :: Ptr CFqNModMPoly -> Ptr CFqNModMPolyFactor -> CLong -> Ptr CFqNModMPolyCtx -> IO ()++-- | /fq_nmod_mpoly_factor_get_exp_si/ /f/ /i/ /ctx/ +--+-- Return the exponent of the term of index /i/ in /A/. It is assumed to+-- fit an @slong@.+foreign import ccall "fq_nmod_mpoly_factor.h fq_nmod_mpoly_factor_get_exp_si"+ fq_nmod_mpoly_factor_get_exp_si :: Ptr CFqNModMPolyFactor -> CLong -> Ptr CFqNModMPolyCtx -> IO CLong++-- | /fq_nmod_mpoly_factor_sort/ /f/ /ctx/ +--+-- Sort the product of /f/ first by exponent and then by base.+foreign import ccall "fq_nmod_mpoly_factor.h fq_nmod_mpoly_factor_sort"+ fq_nmod_mpoly_factor_sort :: Ptr CFqNModMPolyFactor -> Ptr CFqNModMPolyCtx -> IO ()++-- Factorisation ---------------------------------------------------------------++-- | /fq_nmod_mpoly_factor_squarefree/ /f/ /A/ /ctx/ +--+-- Set /f/ to a factorization of /A/ where the bases are primitive and+-- pairwise relatively prime. If the product of all irreducible factors+-- with a given exponent is desired, it is recommended to call+-- @fq_nmod_mpoly_factor_sort@ and then multiply the bases with the desired+-- exponent.+foreign import ccall "fq_nmod_mpoly_factor.h fq_nmod_mpoly_factor_squarefree"+ fq_nmod_mpoly_factor_squarefree :: Ptr CFqNModMPolyFactor -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt++-- | /fq_nmod_mpoly_factor/ /f/ /A/ /ctx/ +--+-- Set /f/ to a factorization of /A/ where the bases are irreducible.+foreign import ccall "fq_nmod_mpoly_factor.h fq_nmod_mpoly_factor"+ fq_nmod_mpoly_factor :: Ptr CFqNModMPolyFactor -> Ptr CFqNModMPoly -> Ptr CFqNModMPolyCtx -> IO CInt+
+ src/Data/Number/Flint/Fq/NMod/Mat.hs view
@@ -0,0 +1,16 @@+{- | +module : Data.Number.Flint.Fq.Mat+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de++An @FqNModMat@ represents an matrix over a finite field (word-size+characteristic). This module implements operations on matrices over a+finite field. +-}++module Data.Number.Flint.Fq.NMod.Mat (+ module Data.Number.Flint.Fq.NMod.Mat.FFI,+) where++import Data.Number.Flint.Fq.NMod.Mat.FFI
+ src/Data/Number/Flint/Fq/NMod/Mat/FFI.hsc view
@@ -0,0 +1,757 @@+{-|+module : Data.Number.Flint.Fq.NMod.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.NMod.Mat.FFI (+ -- * Matrices over finite fields (word-size characteristic)+ FqNModMat (..)+ , CFqNModMat (..)+ , newFqNModMat+ , withFqNModMat+ -- * Memory management+ , fq_nmod_mat_init+ , fq_nmod_mat_init_set+ , fq_nmod_mat_clear+ , fq_nmod_mat_set+ -- * Basic properties and manipulation+ , fq_nmod_mat_entry+ , fq_nmod_mat_entry_set+ , fq_nmod_mat_nrows+ , fq_nmod_mat_ncols+ , fq_nmod_mat_swap+ , fq_nmod_mat_swap_entrywise+ , fq_nmod_mat_zero+ , fq_nmod_mat_one+ , fq_nmod_mat_swap_rows+ , fq_nmod_mat_swap_cols+ , fq_nmod_mat_invert_rows+ , fq_nmod_mat_invert_cols+ -- * Conversions+ , fq_nmod_mat_set_nmod_mat+ , fq_nmod_mat_set_fmpz_mod_mat+ -- * Concatenate+ , fq_nmod_mat_concat_vertical+ , fq_nmod_mat_concat_horizontal+ -- * Printing+ , fq_nmod_mat_print_pretty+ , fq_nmod_mat_fprint_pretty+ , fq_nmod_mat_print+ , fq_nmod_mat_fprint+ -- * Window+ , fq_nmod_mat_window_init+ , fq_nmod_mat_window_clear+ -- * Random matrix generation+ , fq_nmod_mat_randtest+ , fq_nmod_mat_randpermdiag+ , fq_nmod_mat_randrank+ , fq_nmod_mat_randops+ , fq_nmod_mat_randtril+ , fq_nmod_mat_randtriu+ -- * Comparison+ , fq_nmod_mat_equal+ , fq_nmod_mat_is_zero+ , fq_nmod_mat_is_one+ , fq_nmod_mat_is_empty+ , fq_nmod_mat_is_square+ -- * Addition and subtraction+ , fq_nmod_mat_add+ , fq_nmod_mat_sub+ , fq_nmod_mat_neg+ -- * Matrix multiplication+ , fq_nmod_mat_mul+ , fq_nmod_mat_mul_classical+ , fq_nmod_mat_mul_KS+ , fq_nmod_mat_submul+ , fq_nmod_mat_mul_vec+ , fq_nmod_mat_mul_vec_ptr+ , fq_nmod_mat_vec_mul+ , fq_nmod_mat_vec_mul_ptr+ -- * Inverse+ , fq_nmod_mat_inv+ -- * LU decomposition+ , fq_nmod_mat_lu+ , fq_nmod_mat_lu_classical+ , fq_nmod_mat_lu_recursive+ -- * Reduced row echelon form+ , fq_nmod_mat_rref+ , fq_nmod_mat_reduce_row+ -- * Triangular solving+ , fq_nmod_mat_solve_tril+ , fq_nmod_mat_solve_tril_classical+ , fq_nmod_mat_solve_tril_recursive+ , fq_nmod_mat_solve_triu+ , fq_nmod_mat_solve_triu_classical+ , fq_nmod_mat_solve_triu_recursive+ -- * Solving+ , fq_nmod_mat_solve+ , fq_nmod_mat_can_solve+ -- * Transforms+ , fq_nmod_mat_similarity+ -- * Characteristic polynomial+ , fq_nmod_mat_charpoly_danilevsky+ , fq_nmod_mat_charpoly+ -- * Minimal polynomial+ , fq_nmod_mat_minpoly+) where ++-- Matrices over finite fields (word-size characteristic) ----------------------++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr+import Foreign.Storable+import Foreign.Marshal+import Foreign.Marshal.Array++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz.Mod.Mat+import Data.Number.Flint.NMod.Types+import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Types++#include <flint/flint.h>+#include <flint/fq_nmod_mat.h>++-- fq_nmod_mat_t ---------------------------------------------------------------++instance Storable CFqNModMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_nmod_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_nmod_mat_t}+ peek ptr = CFqNModMat+ <$> #{peek fq_nmod_mat_struct, entries} ptr+ <*> #{peek fq_nmod_mat_struct, r } ptr+ <*> #{peek fq_nmod_mat_struct, c } ptr+ <*> #{peek fq_nmod_mat_struct, rows } ptr+ poke = undefined++newFqNModMat rows cols ctx@(FqNModCtx ftx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqNModCtx ctx $ \ctx -> do+ fq_nmod_mat_init x rows cols ctx+ addForeignPtrFinalizerEnv p_fq_nmod_mat_clear x ftx+ return $ FqNModMat x++{-# INLINE withFqNModMat #-}+withFqNModMat (FqNModMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqNModMat x,)+ +-- Memory management -----------------------------------------------------------++-- | /fq_nmod_mat_init/ /mat/ /rows/ /cols/ /ctx/ +--+-- Initialises @mat@ to a @rows@-by-@cols@ matrix with coefficients in+-- \(\mathbf{F}_{q}\) given by @ctx@. All elements are set to zero.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_init"+ fq_nmod_mat_init :: Ptr CFqNModMat -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_init_set/ /mat/ /src/ /ctx/ +--+-- Initialises @mat@ and sets its dimensions and elements to those of+-- @src@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_init_set"+ fq_nmod_mat_init_set :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_clear/ /mat/ /ctx/ +--+-- Clears the matrix and releases any memory it used. The matrix cannot be+-- used again until it is initialised. This function must be called exactly+-- once when finished using an @fq_nmod_mat_t@ object.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_clear"+ fq_nmod_mat_clear :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++foreign import ccall "fq_nmod_mat.h &fq_nmod_mat_clear"+ p_fq_nmod_mat_clear :: FunPtr (Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ())++-- | /fq_nmod_mat_set/ /mat/ /src/ /ctx/ +--+-- Sets @mat@ to a copy of @src@. It is assumed that @mat@ and @src@ have+-- identical dimensions.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_set"+ fq_nmod_mat_set :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- Basic properties and manipulation -------------------------------------------++-- | /fq_nmod_mat_entry/ /mat/ /i/ /j/ +--+-- Directly accesses the entry in @mat@ in row \(i\) and column \(j\),+-- indexed from zero. No bounds checking is performed.+fq_nmod_mat_entry :: Ptr CFqNModMat -> CLong -> CLong -> IO (Ptr CFqNMod)+fq_nmod_mat_entry mat i j = do+ CFqNModMat entries r c rows <- peek mat+ return $ entries `advancePtr` (fromIntegral (i*c + j))++-- | /fq_nmod_mat_entry_set/ /mat/ /i/ /j/ /x/ /ctx/ +--+-- Sets the entry in @mat@ in row \(i\) and column \(j\) to @x@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_entry_set"+ fq_nmod_mat_entry_set :: Ptr CFqNModMat -> CLong -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_nrows/ /mat/ /ctx/ +--+-- Returns the number of rows in @mat@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_nrows"+ fq_nmod_mat_nrows :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_mat_ncols/ /mat/ /ctx/ +--+-- Returns the number of columns in @mat@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_ncols"+ fq_nmod_mat_ncols :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_mat_swap/ /mat1/ /mat2/ /ctx/ +--+-- Swaps two matrices. The dimensions of @mat1@ and @mat2@ are allowed to+-- be different.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_swap"+ fq_nmod_mat_swap :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_swap_entrywise/ /mat1/ /mat2/ +--+-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_swap_entrywise"+ fq_nmod_mat_swap_entrywise :: Ptr CFqNModMat -> Ptr CFqNModMat -> IO ()++-- | /fq_nmod_mat_zero/ /mat/ /ctx/ +--+-- Sets all entries of @mat@ to 0.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_zero"+ fq_nmod_mat_zero :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_one/ /mat/ /ctx/ +--+-- Sets all diagonal entries of @mat@ to 1 and all other entries to 0.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_one"+ fq_nmod_mat_one :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_swap_rows/ /mat/ /perm/ /r/ /s/ +--+-- Swaps rows @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the rows will also be applied to @perm@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_swap_rows"+ fq_nmod_mat_swap_rows :: Ptr CFqNModMat -> Ptr CLong -> CLong -> CLong -> IO ()++-- | /fq_nmod_mat_swap_cols/ /mat/ /perm/ /r/ /s/ +--+-- Swaps columns @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the columns will also be applied to @perm@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_swap_cols"+ fq_nmod_mat_swap_cols :: Ptr CFqNModMat -> Ptr CLong -> CLong -> CLong -> IO ()++-- | /fq_nmod_mat_invert_rows/ /mat/ /perm/ +--+-- Swaps rows @i@ and @r - i@ of @mat@ for @0 \<= i \< r\/2@, where @r@ is+-- the number of rows of @mat@. If @perm@ is non-@NULL@, the permutation of+-- the rows will also be applied to @perm@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_invert_rows"+ fq_nmod_mat_invert_rows :: Ptr CFqNModMat -> Ptr CLong -> IO ()++-- | /fq_nmod_mat_invert_cols/ /mat/ /perm/ +--+-- Swaps columns @i@ and @c - i@ of @mat@ for @0 \<= i \< c\/2@, where @c@+-- is the number of columns of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the columns will also be applied to @perm@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_invert_cols"+ fq_nmod_mat_invert_cols :: Ptr CFqNModMat -> Ptr CLong -> IO ()++-- Conversions -----------------------------------------------------------------++-- | /fq_nmod_mat_set_nmod_mat/ /mat1/ /mat2/ /ctx/ +--+-- Sets the matrix @mat1@ to the matrix @mat2@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_set_nmod_mat"+ fq_nmod_mat_set_nmod_mat :: Ptr CFqNModMat -> Ptr CNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_set_fmpz_mod_mat/ /mat1/ /mat2/ /ctx/ +--+-- Sets the matrix @mat1@ to the matrix @mat2@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_set_fmpz_mod_mat"+ fq_nmod_mat_set_fmpz_mod_mat :: Ptr CFqNModMat -> Ptr CFmpzModMat -> Ptr CFqNModCtx -> IO ()++-- Concatenate -----------------------------------------------------------------++-- | /fq_nmod_mat_concat_vertical/ /res/ /mat1/ /mat2/ /ctx/ +--+-- Sets @res@ to vertical concatenation of (@mat1@, @mat2@) in that order.+-- Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ : \(k \times n\),+-- @res@ : \((m + k) \times n\).+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_concat_vertical"+ fq_nmod_mat_concat_vertical :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_concat_horizontal/ /res/ /mat1/ /mat2/ /ctx/ +--+-- Sets @res@ to horizontal concatenation of (@mat1@, @mat2@) in that+-- order. Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ :+-- \(m \times k\), @res@ : \(m \times (n + k)\).+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_concat_horizontal"+ fq_nmod_mat_concat_horizontal :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- Printing --------------------------------------------------------------------++-- | /fq_nmod_mat_print_pretty/ /mat/ /ctx/ +--+-- Pretty-prints @mat@ to @stdout@. A header is printed followed by the+-- rows enclosed in brackets.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_print_pretty"+ fq_nmod_mat_print_pretty :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_fprint_pretty/ /file/ /mat/ /ctx/ +--+-- Pretty-prints @mat@ to @file@. A header is printed followed by the rows+-- enclosed in brackets.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_fprint_pretty"+ fq_nmod_mat_fprint_pretty :: Ptr CFile -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_mat_print/ /mat/ /ctx/ +--+-- Prints @mat@ to @stdout@. A header is printed followed by the rows+-- enclosed in brackets.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_print"+ fq_nmod_mat_print :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_fprint/ /file/ /mat/ /ctx/ +--+-- Prints @mat@ to @file@. A header is printed followed by the rows+-- enclosed in brackets.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_fprint"+ fq_nmod_mat_fprint :: Ptr CFile -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CInt++-- Window ----------------------------------------------------------------------++-- | /fq_nmod_mat_window_init/ /window/ /mat/ /r1/ /c1/ /r2/ /c2/ /ctx/ +--+-- Initializes the matrix @window@ to be an @r2 - r1@ by @c2 - c1@+-- submatrix of @mat@ whose @(0,0)@ entry is the @(r1, c1)@ entry of @mat@.+-- The memory for the elements of @window@ is shared with @mat@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_window_init"+ fq_nmod_mat_window_init :: Ptr CFqNModMat -> Ptr CFqNModMat -> CLong -> CLong -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_window_clear/ /window/ /ctx/ +--+-- Clears the matrix @window@ and releases any memory that it uses. Note+-- that the memory to the underlying matrix that @window@ points to is not+-- freed.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_window_clear"+ fq_nmod_mat_window_clear :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- Random matrix generation ----------------------------------------------------++-- | /fq_nmod_mat_randtest/ /mat/ /state/ /ctx/ +--+-- Sets the elements of @mat@ to random elements of \(\mathbf{F}_{q}\),+-- given by @ctx@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_randtest"+ fq_nmod_mat_randtest :: Ptr CFqNModMat -> Ptr CFRandState -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_randpermdiag/ /mat/ /state/ /diag/ /n/ /ctx/ +--+-- Sets @mat@ to a random permutation of the diagonal matrix with \(n\)+-- leading entries given by the vector @diag@. It is assumed that the main+-- diagonal of @mat@ has room for at least \(n\) entries.+-- +-- Returns \(0\) or \(1\), depending on whether the permutation is even or+-- odd respectively.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_randpermdiag"+ fq_nmod_mat_randpermdiag :: Ptr CFqNModMat -> Ptr CFRandState -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_mat_randrank/ /mat/ /state/ /rank/ /ctx/ +--+-- Sets @mat@ to a random sparse matrix with the given rank, having exactly+-- as many non-zero elements as the rank, with the non-zero elements being+-- uniformly random elements of \(\mathbf{F}_{q}\).+-- +-- The matrix can be transformed into a dense matrix with unchanged rank by+-- subsequently calling @fq_nmod_mat_randops@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_randrank"+ fq_nmod_mat_randrank :: Ptr CFqNModMat -> Ptr CFRandState -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_randops/ /mat/ /count/ /state/ /ctx/ +--+-- Randomises @mat@ by performing elementary row or column operations. More+-- precisely, at most @count@ random additions or subtractions of distinct+-- rows and columns will be performed. This leaves the rank (and for square+-- matrices, determinant) unchanged.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_randops"+ fq_nmod_mat_randops :: Ptr CFqNModMat -> CLong -> Ptr CFRandState -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_randtril/ /mat/ /state/ /unit/ /ctx/ +--+-- Sets @mat@ to a random lower triangular matrix. If @unit@ is 1, it will+-- have ones on the main diagonal, otherwise it will have random nonzero+-- entries on the main diagonal.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_randtril"+ fq_nmod_mat_randtril :: Ptr CFqNModMat -> Ptr CFRandState -> CInt -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_randtriu/ /mat/ /state/ /unit/ /ctx/ +--+-- Sets @mat@ to a random upper triangular matrix. If @unit@ is 1, it will+-- have ones on the main diagonal, otherwise it will have random nonzero+-- entries on the main diagonal.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_randtriu"+ fq_nmod_mat_randtriu :: Ptr CFqNModMat -> Ptr CFRandState -> CInt -> Ptr CFqNModCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fq_nmod_mat_equal/ /mat1/ /mat2/ /ctx/ +--+-- Returns nonzero if mat1 and mat2 have the same dimensions and elements,+-- and zero otherwise.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_equal"+ fq_nmod_mat_equal :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_mat_is_zero/ /mat/ /ctx/ +--+-- Returns a non-zero value if all entries @mat@ are zero, and otherwise+-- returns zero.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_is_zero"+ fq_nmod_mat_is_zero :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_mat_is_one/ /mat/ /ctx/ +--+-- Returns a non-zero value if all entries @mat@ are zero except the+-- diagonal entries which must be one, otherwise returns zero.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_is_one"+ fq_nmod_mat_is_one :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_mat_is_empty/ /mat/ /ctx/ +--+-- Returns a non-zero value if the number of rows or the number of columns+-- in @mat@ is zero, and otherwise returns zero.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_is_empty"+ fq_nmod_mat_is_empty :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_mat_is_square/ /mat/ /ctx/ +--+-- Returns a non-zero value if the number of rows is equal to the number of+-- columns in @mat@, and otherwise returns zero.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_is_square"+ fq_nmod_mat_is_square :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /fq_nmod_mat_add/ /C/ /A/ /B/ /ctx/ +--+-- Computes \(C = A + B\). Dimensions must be identical.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_add"+ fq_nmod_mat_add :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_sub/ /C/ /A/ /B/ /ctx/ +--+-- Computes \(C = A - B\). Dimensions must be identical.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_sub"+ fq_nmod_mat_sub :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_neg/ /A/ /B/ /ctx/ +--+-- Sets \(B = -A\). Dimensions must be identical.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_neg"+ fq_nmod_mat_neg :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- Matrix multiplication -------------------------------------------------------++-- | /fq_nmod_mat_mul/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. Aliasing is allowed. This function automatically chooses+-- between classical and KS multiplication.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_mul"+ fq_nmod_mat_mul :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_mul_classical/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. \(C\) is not allowed to be aliased with \(A\) or \(B\).+-- Uses classical matrix multiplication.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_mul_classical"+ fq_nmod_mat_mul_classical :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_mul_KS/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. \(C\) is not allowed to be aliased with \(A\) or \(B\).+-- Uses Kronecker substitution to perform the multiplication over the+-- integers.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_mul_KS"+ fq_nmod_mat_mul_KS :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_submul/ /D/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(D = C + AB\). \(C\) and \(D\) may be aliased with each other but+-- not with \(A\) or \(B\).+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_submul"+ fq_nmod_mat_submul :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_mul_vec/ /c/ /A/ /b/ /blen/ +foreign import ccall "fq_nmod_mat.h fq_nmod_mat_mul_vec"+ fq_nmod_mat_mul_vec :: Ptr (Ptr CFqNMod) -> Ptr CFqNModMat -> Ptr (Ptr CFqNMod) -> CLong -> IO ()+-- | /fq_nmod_mat_mul_vec_ptr/ /c/ /A/ /b/ /blen/ +--+-- Compute a matrix-vector product of @A@ and @(b, blen)@ and store the+-- result in @c@. The vector @(b, blen)@ is either truncated or+-- zero-extended to the number of columns of @A@. The number entries+-- written to @c@ is always equal to the number of rows of @A@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_mul_vec_ptr"+ fq_nmod_mat_mul_vec_ptr :: Ptr (Ptr (Ptr CFqNMod)) -> Ptr CFqNModMat -> Ptr (Ptr (Ptr CFqNMod)) -> CLong -> IO ()++-- | /fq_nmod_mat_vec_mul/ /c/ /a/ /alen/ /B/ +foreign import ccall "fq_nmod_mat.h fq_nmod_mat_vec_mul"+ fq_nmod_mat_vec_mul :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModMat -> IO ()+-- | /fq_nmod_mat_vec_mul_ptr/ /c/ /a/ /alen/ /B/ +--+-- Compute a vector-matrix product of @(a, alen)@ and @B@ and and store the+-- result in @c@. The vector @(a, alen)@ is either truncated or+-- zero-extended to the number of rows of @B@. The number entries written+-- to @c@ is always equal to the number of columns of @B@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_vec_mul_ptr"+ fq_nmod_mat_vec_mul_ptr :: Ptr (Ptr (Ptr CFqNMod)) -> Ptr (Ptr (Ptr CFqNMod)) -> CLong -> Ptr CFqNModMat -> IO ()++-- Inverse ---------------------------------------------------------------------++-- | /fq_nmod_mat_inv/ /B/ /A/ /ctx/ +--+-- Sets \(B = A^{-1}\) and returns \(1\) if \(A\) is invertible. If \(A\)+-- is singular, returns \(0\) and sets the elements of \(B\) to undefined+-- values.+-- +-- \(A\) and \(B\) must be square matrices with the same dimensions.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_inv"+ fq_nmod_mat_inv :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqCtx -> IO CInt++-- LU decomposition ------------------------------------------------------------++-- | /fq_nmod_mat_lu/ /P/ /A/ /rank_check/ /ctx/ +--+-- Computes a generalised LU decomposition \(LU = PA\) of a given matrix+-- \(A\), returning the rank of \(A\).+-- +-- If \(A\) is a nonsingular square matrix, it will be overwritten with a+-- unit diagonal lower triangular matrix \(L\) and an upper triangular+-- matrix \(U\) (the diagonal of \(L\) will not be stored explicitly).+-- +-- If \(A\) is an arbitrary matrix of rank \(r\), \(U\) will be in row+-- echelon form having \(r\) nonzero rows, and \(L\) will be lower+-- triangular but truncated to \(r\) columns, having implicit ones on the+-- \(r\) first entries of the main diagonal. All other entries will be+-- zero.+-- +-- If a nonzero value for @rank_check@ is passed, the function will abandon+-- the output matrix in an undefined state and return 0 if \(A\) is+-- detected to be rank-deficient.+-- +-- This function calls @fq_nmod_mat_lu_recursive@.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_lu"+ fq_nmod_mat_lu :: Ptr CLong -> Ptr CFqNModMat -> CInt -> Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_mat_lu_classical/ /P/ /A/ /rank_check/ /ctx/ +--+-- Computes a generalised LU decomposition \(LU = PA\) of a given matrix+-- \(A\), returning the rank of \(A\). The behavior of this function is+-- identical to that of @fq_nmod_mat_lu@. Uses Gaussian elimination.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_lu_classical"+ fq_nmod_mat_lu_classical :: Ptr CLong -> Ptr CFqNModMat -> CInt -> Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_mat_lu_recursive/ /P/ /A/ /rank_check/ /ctx/ +--+-- Computes a generalised LU decomposition \(LU = PA\) of a given matrix+-- \(A\), returning the rank of \(A\). The behavior of this function is+-- identical to that of @fq_nmod_mat_lu@. Uses recursive block+-- decomposition, switching to classical Gaussian elimination for+-- sufficiently small blocks.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_lu_recursive"+ fq_nmod_mat_lu_recursive :: Ptr CLong -> Ptr CFqNModMat -> CInt -> Ptr CFqNModCtx -> IO CLong++-- Reduced row echelon form ----------------------------------------------------++-- | /fq_nmod_mat_rref/ /A/ /ctx/ +--+-- Puts \(A\) in reduced row echelon form and returns the rank of \(A\).+-- +-- The rref is computed by first obtaining an unreduced row echelon form+-- via LU decomposition and then solving an additional triangular system.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_rref"+ fq_nmod_mat_rref :: Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_mat_reduce_row/ /A/ /P/ /L/ /n/ /ctx/ +--+-- Reduce row n of the matrix \(A\), assuming the prior rows are in Gauss+-- form. However those rows may not be in order. The entry \(i\) of the+-- array \(P\) is the row of \(A\) which has a pivot in the \(i\)-th+-- column. If no such row exists, the entry of \(P\) will be \(-1\). The+-- function returns the column in which the \(n\)-th row has a pivot after+-- reduction. This will always be chosen to be the first available column+-- for a pivot from the left. This information is also updated in \(P\).+-- Entry \(i\) of the array \(L\) contains the number of possibly nonzero+-- columns of \(A\) row \(i\). This speeds up reduction in the case that+-- \(A\) is chambered on the right. Otherwise the entries of \(L\) can all+-- be set to the number of columns of \(A\). We require the entries of+-- \(L\) to be monotonic increasing.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_reduce_row"+ fq_nmod_mat_reduce_row :: Ptr CFqNModMat -> Ptr CLong -> Ptr CLong -> CLong -> Ptr CFqNModCtx -> IO CLong++-- Triangular solving ----------------------------------------------------------++-- | /fq_nmod_mat_solve_tril/ /X/ /L/ /B/ /unit/ /ctx/ +--+-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- Automatically chooses between the classical and recursive algorithms.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_solve_tril"+ fq_nmod_mat_solve_tril :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> CInt -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_solve_tril_classical/ /X/ /L/ /B/ /unit/ /ctx/ +--+-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed. Uses+-- forward substitution.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_solve_tril_classical"+ fq_nmod_mat_solve_tril_classical :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> CInt -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_solve_tril_recursive/ /X/ /L/ /B/ /unit/ /ctx/ +--+-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- +-- Uses the block inversion formula+-- +-- \[\begin{aligned}+-- `+-- \begin{pmatrix} A & 0 \\ C & D \end{pmatrix}^{-1}+-- \begin{pmatrix} X \\ Y \end{pmatrix} =+-- \begin{pmatrix} A^{-1} X \\ D^{-1} ( Y - C A^{-1} X ) \end{pmatrix}+-- \end{aligned}\]+-- +-- to reduce the problem to matrix multiplication and triangular solving of+-- smaller systems.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_solve_tril_recursive"+ fq_nmod_mat_solve_tril_recursive :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> CInt -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_solve_triu/ /X/ /U/ /B/ /unit/ /ctx/ +--+-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- Automatically chooses between the classical and recursive algorithms.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_solve_triu"+ fq_nmod_mat_solve_triu :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> CInt -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_solve_triu_classical/ /X/ /U/ /B/ /unit/ /ctx/ +--+-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed. Uses+-- forward substitution.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_solve_triu_classical"+ fq_nmod_mat_solve_triu_classical :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> CInt -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_solve_triu_recursive/ /X/ /U/ /B/ /unit/ /ctx/ +--+-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- +-- Uses the block inversion formula+-- +-- \[\begin{aligned}+-- `+-- \begin{pmatrix} A & B \\ 0 & D \end{pmatrix}^{-1}+-- \begin{pmatrix} X \\ Y \end{pmatrix} =+-- \begin{pmatrix} A^{-1} (X - B D^{-1} Y) \\ D^{-1} Y \end{pmatrix}+-- \end{aligned}\]+-- +-- to reduce the problem to matrix multiplication and triangular solving of+-- smaller systems.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_solve_triu_recursive"+ fq_nmod_mat_solve_triu_recursive :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> CInt -> Ptr CFqNModCtx -> IO ()++-- Solving ---------------------------------------------------------------------++-- | /fq_nmod_mat_solve/ /X/ /A/ /B/ /ctx/ +--+-- Solves the matrix-matrix equation \(AX = B\).+-- +-- Returns \(1\) if \(A\) has full rank; otherwise returns \(0\) and sets+-- the elements of \(X\) to undefined values.+-- +-- The matrix \(A\) must be square.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_solve"+ fq_nmod_mat_solve :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_mat_can_solve/ /X/ /A/ /B/ /ctx/ +--+-- Solves the matrix-matrix equation \(AX = B\) over \(Fq\).+-- +-- Returns \(1\) if a solution exists; otherwise returns \(0\) and sets the+-- elements of \(X\) to zero. If more than one solution exists, one of the+-- valid solutions is given.+-- +-- There are no restrictions on the shape of \(A\) and it may be singular.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_can_solve"+ fq_nmod_mat_can_solve :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO CInt++-- Transforms ------------------------------------------------------------------++-- | /fq_nmod_mat_similarity/ /M/ /r/ /d/ /ctx/ +--+-- Applies a similarity transform to the \(n\times n\) matrix \(M\)+-- in-place.+-- +-- If \(P\) is the \(n\times n\) identity matrix the zero entries of whose+-- row \(r\) (0-indexed) have been replaced by \(d\), this transform is+-- equivalent to \(M = P^{-1}MP\).+-- +-- Similarity transforms preserve the determinant, characteristic+-- polynomial and minimal polynomial.+-- +-- The value \(d\) is required to be reduced modulo the modulus of the+-- entries in the matrix.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_similarity"+ fq_nmod_mat_similarity :: Ptr CFqNModMat -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- Characteristic polynomial ---------------------------------------------------++-- | /fq_nmod_mat_charpoly_danilevsky/ /p/ /M/ /ctx/ +--+-- Compute the characteristic polynomial \(p\) of the matrix \(M\). The+-- matrix is assumed to be square.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_charpoly_danilevsky"+ fq_nmod_mat_charpoly_danilevsky :: Ptr CFqNModPoly -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_mat_charpoly/ /p/ /M/ /ctx/ +--+-- Compute the characteristic polynomial \(p\) of the matrix \(M\). The+-- matrix is required to be square, otherwise an exception is raised.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_charpoly"+ fq_nmod_mat_charpoly :: Ptr CFqNModPoly -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()++-- Minimal polynomial ----------------------------------------------------------++-- | /fq_nmod_mat_minpoly/ /p/ /M/ /ctx/ +--+-- Compute the minimal polynomial \(p\) of the matrix \(M\). The matrix is+-- required to be square, otherwise an exception is raised.+foreign import ccall "fq_nmod_mat.h fq_nmod_mat_minpoly"+ fq_nmod_mat_minpoly :: Ptr CFqNModPoly -> Ptr CFqNModMat -> Ptr CFqNModCtx -> IO ()+
+ src/Data/Number/Flint/Fq/NMod/Poly.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fq.NMod.Poly (+ module Data.Number.Flint.Fq.NMod.Poly.FFI+) where++import Data.Number.Flint.Fq.NMod.Poly.FFI
+ src/Data/Number/Flint/Fq/NMod/Poly/FFI.hsc view
@@ -0,0 +1,1951 @@+{-|+module : Data.Number.Flint.Fq.NMod.Poly.FFi+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.NMod.Poly.FFI (+ -- * Univariate polynomials over finite fields (word-size characteristic)+ FqNModPoly (..)+ , CFqNModPoly (..)+ , newFqNModPoly+ , withFqNModPoly+ -- * Memory management+ , fq_nmod_poly_init+ , fq_nmod_poly_init2+ , fq_nmod_poly_realloc+ , fq_nmod_poly_fit_length+ , _fq_nmod_poly_set_length+ , fq_nmod_poly_clear+ , _fq_nmod_poly_normalise+ , _fq_nmod_poly_normalise2+ , fq_nmod_poly_truncate+ , fq_nmod_poly_set_trunc+ , _fq_nmod_poly_reverse+ , fq_nmod_poly_reverse+ -- * Polynomial parameters+ , fq_nmod_poly_degree+ , fq_nmod_poly_length+ , fq_nmod_poly_lead+ -- * Randomisation+ , fq_nmod_poly_randtest+ , fq_nmod_poly_randtest_not_zero+ , fq_nmod_poly_randtest_monic+ , fq_nmod_poly_randtest_irreducible+ -- * Assignment and basic manipulation+ , _fq_nmod_poly_set+ , fq_nmod_poly_set+ , fq_nmod_poly_set_fq_nmod+ , fq_nmod_poly_set_fmpz_mod_poly+ , fq_nmod_poly_set_nmod_poly+ , fq_nmod_poly_swap+ , _fq_nmod_poly_zero+ , fq_nmod_poly_zero+ , fq_nmod_poly_one+ , fq_nmod_poly_gen+ , fq_nmod_poly_make_monic+ , _fq_nmod_poly_make_monic+ -- * Getting and setting coefficients+ , fq_nmod_poly_get_coeff+ , fq_nmod_poly_set_coeff+ , fq_nmod_poly_set_coeff_fmpz+ -- * Comparison+ , fq_nmod_poly_equal+ , fq_nmod_poly_equal_trunc+ , fq_nmod_poly_is_zero+ , fq_nmod_poly_is_one+ , fq_nmod_poly_is_gen+ , fq_nmod_poly_is_unit+ , fq_nmod_poly_equal_fq_nmod+ -- * Addition and subtraction+ , _fq_nmod_poly_add+ , fq_nmod_poly_add+ , fq_nmod_poly_add_si+ , fq_nmod_poly_add_series+ , _fq_nmod_poly_sub+ , fq_nmod_poly_sub+ , fq_nmod_poly_sub_series+ , _fq_nmod_poly_neg+ , fq_nmod_poly_neg+ -- * Scalar multiplication and division+ , _fq_nmod_poly_scalar_mul_fq_nmod+ , fq_nmod_poly_scalar_mul_fq_nmod+ , _fq_nmod_poly_scalar_addmul_fq_nmod+ , fq_nmod_poly_scalar_addmul_fq_nmod+ , _fq_nmod_poly_scalar_submul_fq_nmod+ , fq_nmod_poly_scalar_submul_fq_nmod+ --, _fq_nmod_poly_scalar_div_fq+ --, fq_nmod_poly_scalar_div_fq+ -- * Multiplication+ , _fq_nmod_poly_mul_classical+ , fq_nmod_poly_mul_classical+ --, _fq_nmod_poly_mul_reorder+ --, fq_nmod_poly_mul_reorder+ , _fq_nmod_poly_mul_univariate+ , fq_nmod_poly_mul_univariate+ , _fq_nmod_poly_mul_KS+ , fq_nmod_poly_mul_KS+ , _fq_nmod_poly_mul+ , fq_nmod_poly_mul+ , _fq_nmod_poly_mullow_classical+ , fq_nmod_poly_mullow_classical+ , _fq_nmod_poly_mullow_univariate+ , fq_nmod_poly_mullow_univariate+ , _fq_nmod_poly_mullow_KS+ , fq_nmod_poly_mullow_KS+ , _fq_nmod_poly_mullow+ , fq_nmod_poly_mullow+ , _fq_nmod_poly_mulhigh_classical+ , fq_nmod_poly_mulhigh_classical+ , _fq_nmod_poly_mulhigh+ , fq_nmod_poly_mulhigh+ , _fq_nmod_poly_mulmod+ , fq_nmod_poly_mulmod+ , _fq_nmod_poly_mulmod_preinv+ , fq_nmod_poly_mulmod_preinv+ -- * Squaring+ , _fq_nmod_poly_sqr_classical+ , fq_nmod_poly_sqr_classical+ , _fq_nmod_poly_sqr_KS+ , fq_nmod_poly_sqr_KS+ , _fq_nmod_poly_sqr+ , fq_nmod_poly_sqr+ -- * Powering+ , _fq_nmod_poly_pow+ , fq_nmod_poly_pow+ , _fq_nmod_poly_powmod_ui_binexp+ , fq_nmod_poly_powmod_ui_binexp+ , _fq_nmod_poly_powmod_ui_binexp_preinv+ , fq_nmod_poly_powmod_ui_binexp_preinv+ , _fq_nmod_poly_powmod_fmpz_binexp+ , fq_nmod_poly_powmod_fmpz_binexp+ , _fq_nmod_poly_powmod_fmpz_binexp_preinv+ , fq_nmod_poly_powmod_fmpz_binexp_preinv+ , _fq_nmod_poly_powmod_fmpz_sliding_preinv+ , fq_nmod_poly_powmod_fmpz_sliding_preinv+ , _fq_nmod_poly_powmod_x_fmpz_preinv+ , fq_nmod_poly_powmod_x_fmpz_preinv+ , _fq_nmod_poly_pow_trunc_binexp+ , fq_nmod_poly_pow_trunc_binexp+ , _fq_nmod_poly_pow_trunc+ , fq_nmod_poly_pow_trunc+ -- * Shifting+ , _fq_nmod_poly_shift_left+ , fq_nmod_poly_shift_left+ , _fq_nmod_poly_shift_right+ , fq_nmod_poly_shift_right+ -- * Norms+ , _fq_nmod_poly_hamming_weight+ , fq_nmod_poly_hamming_weight+ -- * Euclidean division+ , _fq_nmod_poly_divrem+ , fq_nmod_poly_divrem+ , fq_nmod_poly_divrem_f+ , _fq_nmod_poly_rem+ , fq_nmod_poly_rem+ , _fq_nmod_poly_div+ , fq_nmod_poly_div+ , _fq_nmod_poly_div_newton_n_preinv+ , fq_nmod_poly_div_newton_n_preinv+ , _fq_nmod_poly_divrem_newton_n_preinv+ , fq_nmod_poly_divrem_newton_n_preinv+ , _fq_nmod_poly_inv_series_newton+ , fq_nmod_poly_inv_series_newton+ , _fq_nmod_poly_inv_series+ , fq_nmod_poly_inv_series+ , _fq_nmod_poly_div_series+ , fq_nmod_poly_div_series+ -- * Greatest common divisor+ , fq_nmod_poly_gcd+ , _fq_nmod_poly_gcd+ , _fq_nmod_poly_gcd_euclidean_f+ , fq_nmod_poly_gcd_euclidean_f+ , _fq_nmod_poly_xgcd+ , fq_nmod_poly_xgcd+ , _fq_nmod_poly_xgcd_euclidean_f+ , fq_nmod_poly_xgcd_euclidean_f+ -- * Divisibility testing+ , _fq_nmod_poly_divides+ , fq_nmod_poly_divides+ -- * Derivative+ , _fq_nmod_poly_derivative+ , fq_nmod_poly_derivative+ -- * Square root+ , _fq_nmod_poly_invsqrt_series+ , fq_nmod_poly_invsqrt_series+ , _fq_nmod_poly_sqrt_series+ , fq_nmod_poly_sqrt_series+ , _fq_nmod_poly_sqrt+ , fq_nmod_poly_sqrt+ -- * Evaluation+ , _fq_nmod_poly_evaluate_fq_nmod+ , fq_nmod_poly_evaluate_fq_nmod+ -- * Composition+ , _fq_nmod_poly_compose+ , fq_nmod_poly_compose+ , _fq_nmod_poly_compose_mod_horner+ , fq_nmod_poly_compose_mod_horner+ , _fq_nmod_poly_compose_mod_horner_preinv+ , fq_nmod_poly_compose_mod_horner_preinv+ , _fq_nmod_poly_compose_mod_brent_kung+ , fq_nmod_poly_compose_mod_brent_kung+ , _fq_nmod_poly_compose_mod_brent_kung_preinv+ , fq_nmod_poly_compose_mod_brent_kung_preinv+ , _fq_nmod_poly_compose_mod+ , fq_nmod_poly_compose_mod+ , _fq_nmod_poly_compose_mod_preinv+ , fq_nmod_poly_compose_mod_preinv+ , _fq_nmod_poly_reduce_matrix_mod_poly+ , _fq_nmod_poly_precompute_matrix+ , fq_nmod_poly_precompute_matrix+ , _fq_nmod_poly_compose_mod_brent_kung_precomp_preinv+ , fq_nmod_poly_compose_mod_brent_kung_precomp_preinv+ -- * Output+ , _fq_nmod_poly_fprint_pretty+ , fq_nmod_poly_fprint_pretty+ , _fq_nmod_poly_print_pretty+ , fq_nmod_poly_print_pretty+ , _fq_nmod_poly_fprint+ , fq_nmod_poly_fprint+ , _fq_nmod_poly_print+ , fq_nmod_poly_print+ , _fq_nmod_poly_get_str+ , fq_nmod_poly_get_str+ , _fq_nmod_poly_get_str_pretty+ , fq_nmod_poly_get_str_pretty+ -- * Inflation and deflation+ , fq_nmod_poly_inflate+ , fq_nmod_poly_deflate+ , fq_nmod_poly_deflation+) where +-- univariate polynomials over finite fields (word-size characteristic) --------++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mod.Poly+import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.Poly+import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Types++#include <flint/flint.h>+#include <flint/fq.h>+#include <flint/fq_nmod.h>+#include <flint/fq_nmod_poly.h>++-- fq_nmod_poly_t --------------------------------------------------------------++instance Storable CFqNModPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_nmod_poly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_nmod_poly_t}+ peek = undefined+ poke = undefined++newFqNModPoly ctx@(FqNModCtx ftx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqNModCtx ctx $ \ctx -> do+ fq_nmod_poly_init x ctx+ addForeignPtrFinalizerEnv p_fq_nmod_poly_clear x ftx+ return $ FqNModPoly x++{-# INLINE withFqNModPoly #-}+withFqNModPoly (FqNModPoly x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqNModPoly x,)++-- Memory management -----------------------------------------------------------++-- | /fq_nmod_poly_init/ /poly/ /ctx/ +--+-- Initialises @poly@ for use, with context ctx, and setting its length to+-- zero. A corresponding call to @fq_nmod_poly_clear@ must be made after+-- finishing with the @fq_nmod_poly_t@ to free the memory used by the+-- polynomial.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_init"+ fq_nmod_poly_init :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_init2/ /poly/ /alloc/ /ctx/ +--+-- Initialises @poly@ with space for at least @alloc@ coefficients and sets+-- the length to zero. The allocated coefficients are all set to zero. A+-- corresponding call to @fq_nmod_poly_clear@ must be made after finishing+-- with the @fq_nmod_poly_t@ to free the memory used by the polynomial.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_init2"+ fq_nmod_poly_init2 :: Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_realloc/ /poly/ /alloc/ /ctx/ +--+-- Reallocates the given polynomial to have space for @alloc@ coefficients.+-- If @alloc@ is zero the polynomial is cleared and then reinitialised. If+-- the current length is greater than @alloc@ the polynomial is first+-- truncated to length @alloc@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_realloc"+ fq_nmod_poly_realloc :: Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_fit_length/ /poly/ /len/ /ctx/ +--+-- If @len@ is greater than the number of coefficients currently allocated,+-- then the polynomial is reallocated to have space for at least @len@+-- coefficients. No data is lost when calling this function.+-- +-- The function efficiently deals with the case where @fit_length@ is+-- called many times in small increments by at least doubling the number of+-- allocated coefficients when length is larger than the number of+-- coefficients currently allocated.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_fit_length"+ fq_nmod_poly_fit_length :: Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_set_length/ /poly/ /newlen/ /ctx/ +--+-- Sets the coefficients of @poly@ beyond @len@ to zero and sets the length+-- of @poly@ to @len@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_set_length"+ _fq_nmod_poly_set_length :: Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_clear/ /poly/ /ctx/ +--+-- Clears the given polynomial, releasing any memory used. It must be+-- reinitialised in order to be used again.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_clear"+ fq_nmod_poly_clear :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++foreign import ccall "fq_nmod_poly.h &fq_nmod_poly_clear"+ p_fq_nmod_poly_clear :: FunPtr (Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ())++-- | /_fq_nmod_poly_normalise/ /poly/ /ctx/ +--+-- Sets the length of @poly@ so that the top coefficient is non-zero. If+-- all coefficients are zero, the length is set to zero. This function is+-- mainly used internally, as all functions guarantee normalisation.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_normalise"+ _fq_nmod_poly_normalise :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_normalise2/ /poly/ /length/ /ctx/ +--+-- Sets the length @length@ of @(poly,length)@ so that the top coefficient+-- is non-zero. If all coefficients are zero, the length is set to zero.+-- This function is mainly used internally, as all functions guarantee+-- normalisation.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_normalise2"+ _fq_nmod_poly_normalise2 :: Ptr (Ptr CFqNMod) -> Ptr CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_truncate/ /poly/ /newlen/ /ctx/ +--+-- Truncates the polynomial to length at most @n@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_truncate"+ fq_nmod_poly_truncate :: Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_set_trunc/ /poly1/ /poly2/ /newlen/ /ctx/ +--+-- Sets @poly1@ to @poly2@ truncated to length \(n\).+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_set_trunc"+ fq_nmod_poly_set_trunc :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_nmod_poly_reverse/ /output/ /input/ /len/ /m/ /ctx/ +--+-- Sets @output@ to the reverse of @input@, which is of length @len@, but+-- thinking of it as a polynomial of length @m@, notionally zero-padded if+-- necessary. The length @m@ must be non-negative, but there are no other+-- restrictions. The polynomial @output@ must have space for @m@+-- coefficients.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_reverse"+ _fq_nmod_poly_reverse :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_reverse/ /output/ /input/ /m/ /ctx/ +--+-- Sets @output@ to the reverse of @input@, thinking of it as a polynomial+-- of length @m@, notionally zero-padded if necessary). The length @m@ must+-- be non-negative, but there are no other restrictions. The output+-- polynomial will be set to length @m@ and then normalised.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_reverse"+ fq_nmod_poly_reverse :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- Polynomial parameters -------------------------------------------------------++-- | /fq_nmod_poly_degree/ /poly/ /ctx/ +--+-- Returns the degree of the polynomial @poly@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_degree"+ fq_nmod_poly_degree :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_poly_length/ /poly/ /ctx/ +--+-- Returns the length of the polynomial @poly@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_length"+ fq_nmod_poly_length :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_poly_lead/ /poly/ /ctx/ +--+-- Returns a pointer to the leading coefficient of @poly@, or @NULL@ if+-- @poly@ is the zero polynomial.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_lead"+ fq_nmod_poly_lead :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO (Ptr (Ptr CFqNMod))++-- Randomisation ---------------------------------------------------------------++-- | /fq_nmod_poly_randtest/ /f/ /state/ /len/ /ctx/ +--+-- Sets \(f\) to a random polynomial of length at most @len@ with entries+-- in the field described by @ctx@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_randtest"+ fq_nmod_poly_randtest :: Ptr CFqNModPoly -> Ptr CFRandState -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_randtest_not_zero/ /f/ /state/ /len/ /ctx/ +--+-- Same as @fq_nmod_poly_randtest@ but guarantees that the polynomial is+-- not zero.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_randtest_not_zero"+ fq_nmod_poly_randtest_not_zero :: Ptr CFqNModPoly -> Ptr CFRandState -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_randtest_monic/ /f/ /state/ /len/ /ctx/ +--+-- Sets \(f\) to a random monic polynomial of length @len@ with entries in+-- the field described by @ctx@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_randtest_monic"+ fq_nmod_poly_randtest_monic :: Ptr CFqNModPoly -> Ptr CFRandState -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_randtest_irreducible/ /f/ /state/ /len/ /ctx/ +--+-- Sets \(f\) to a random monic, irreducible polynomial of length @len@+-- with entries in the field described by @ctx@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_randtest_irreducible"+ fq_nmod_poly_randtest_irreducible :: Ptr CFqNModPoly -> Ptr CFRandState -> CLong -> Ptr CFqNModCtx -> IO ()++-- Assignment and basic manipulation -------------------------------------------++-- | /_fq_nmod_poly_set/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, len@) to @(op, len)@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_set"+ _fq_nmod_poly_set :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_set/ /poly1/ /poly2/ /ctx/ +--+-- Sets the polynomial @poly1@ to the polynomial @poly2@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_set"+ fq_nmod_poly_set :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_set_fq_nmod/ /poly/ /c/ /ctx/ +--+-- Sets the polynomial @poly@ to @c@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_set_fq_nmod"+ fq_nmod_poly_set_fq_nmod :: Ptr CFqNModPoly -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_set_fmpz_mod_poly/ /rop/ /op/ /ctx/ +--+-- Sets the polynomial @rop@ to the polynomial @op@+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_set_fmpz_mod_poly"+ fq_nmod_poly_set_fmpz_mod_poly :: Ptr CFqNModPoly -> Ptr CFmpzModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_set_nmod_poly/ /rop/ /op/ /ctx/ +--+-- Sets the polynomial @rop@ to the polynomial @op@+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_set_nmod_poly"+ fq_nmod_poly_set_nmod_poly :: Ptr CFqNModPoly -> Ptr CNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_swap/ /op1/ /op2/ /ctx/ +--+-- Swaps the two polynomials @op1@ and @op2@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_swap"+ fq_nmod_poly_swap :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_zero/ /rop/ /len/ /ctx/ +--+-- Sets @(rop, len)@ to the zero polynomial.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_zero"+ _fq_nmod_poly_zero :: Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_zero/ /poly/ /ctx/ +--+-- Sets @poly@ to the zero polynomial.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_zero"+ fq_nmod_poly_zero :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_one/ /poly/ /ctx/ +--+-- Sets @poly@ to the constant polynomial \(1\).+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_one"+ fq_nmod_poly_one :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_gen/ /poly/ /ctx/ +--+-- Sets @poly@ to the polynomial \(x\).+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_gen"+ fq_nmod_poly_gen :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_make_monic/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to @op@, normed to have leading coefficient 1.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_make_monic"+ fq_nmod_poly_make_monic :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_make_monic/ /rop/ /op/ /length/ /ctx/ +--+-- Sets @rop@ to @(op,length)@, normed to have leading coefficient 1.+-- Assumes that @rop@ has enough space for the polynomial, assumes that+-- @op@ is not zero (and thus has an invertible leading coefficient).+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_make_monic"+ _fq_nmod_poly_make_monic :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- Getting and setting coefficients --------------------------------------------++-- | /fq_nmod_poly_get_coeff/ /x/ /poly/ /n/ /ctx/ +--+-- Sets \(x\) to the coefficient of \(X^n\) in @poly@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_get_coeff"+ fq_nmod_poly_get_coeff :: Ptr CFqNMod -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_set_coeff/ /poly/ /n/ /x/ /ctx/ +--+-- Sets the coefficient of \(X^n\) in @poly@ to \(x\).+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_set_coeff"+ fq_nmod_poly_set_coeff :: Ptr CFqNModPoly -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_set_coeff_fmpz/ /poly/ /n/ /x/ /ctx/ +--+-- Sets the coefficient of \(X^n\) in the polynomial to \(x\), assuming+-- \(n \geq 0\).+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_set_coeff_fmpz"+ fq_nmod_poly_set_coeff_fmpz :: Ptr CFqNModPoly -> CLong -> Ptr CFmpz -> Ptr CFqNModCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fq_nmod_poly_equal/ /poly1/ /poly2/ /ctx/ +--+-- Returns nonzero if the two polynomials @poly1@ and @poly2@ are equal,+-- otherwise return zero.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_equal"+ fq_nmod_poly_equal :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_equal_trunc/ /poly1/ /poly2/ /n/ /ctx/ +--+-- Notionally truncate @poly1@ and @poly2@ to length \(n\) and return+-- nonzero if they are equal, otherwise return zero.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_equal_trunc"+ fq_nmod_poly_equal_trunc :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO CInt++-- | /fq_nmod_poly_is_zero/ /poly/ /ctx/ +--+-- Returns whether the polynomial @poly@ is the zero polynomial.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_is_zero"+ fq_nmod_poly_is_zero :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_is_one/ /op/ +--+-- Returns whether the polynomial @poly@ is equal to the constant+-- polynomial \(1\).+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_is_one"+ fq_nmod_poly_is_one :: Ptr CFqNModPoly -> IO CInt++-- | /fq_nmod_poly_is_gen/ /op/ /ctx/ +--+-- Returns whether the polynomial @poly@ is equal to the polynomial \(x\).+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_is_gen"+ fq_nmod_poly_is_gen :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_is_unit/ /op/ /ctx/ +--+-- Returns whether the polynomial @poly@ is a unit in the polynomial ring+-- \(\mathbf{F}_q[X]\), i.e. if it has degree \(0\) and is non-zero.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_is_unit"+ fq_nmod_poly_is_unit :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_equal_fq_nmod/ /poly/ /c/ /ctx/ +--+-- Returns whether the polynomial @poly@ is equal the (constant)+-- \(\mathbf{F}_q\) element @c@+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_equal_fq_nmod"+ fq_nmod_poly_equal_fq_nmod :: Ptr CFqNModPoly -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /_fq_nmod_poly_add/ /res/ /poly1/ /len1/ /poly2/ /len2/ /ctx/ +--+-- Sets @res@ to the sum of @(poly1,len1)@ and @(poly2,len2)@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_add"+ _fq_nmod_poly_add :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_add/ /res/ /poly1/ /poly2/ /ctx/ +--+-- Sets @res@ to the sum of @poly1@ and @poly2@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_add"+ fq_nmod_poly_add :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_add_si/ /res/ /poly1/ /c/ /ctx/ +--+-- Sets @res@ to the sum of @poly1@ and @c@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_add_si"+ fq_nmod_poly_add_si :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_add_series/ /res/ /poly1/ /poly2/ /n/ /ctx/ +--+-- Notionally truncate @poly1@ and @poly2@ to length @n@ and set @res@ to+-- the sum.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_add_series"+ fq_nmod_poly_add_series :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_nmod_poly_sub/ /res/ /poly1/ /len1/ /poly2/ /len2/ /ctx/ +--+-- Sets @res@ to the difference of @(poly1,len1)@ and @(poly2,len2)@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_sub"+ _fq_nmod_poly_sub :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_sub/ /res/ /poly1/ /poly2/ /ctx/ +--+-- Sets @res@ to the difference of @poly1@ and @poly2@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_sub"+ fq_nmod_poly_sub :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_sub_series/ /res/ /poly1/ /poly2/ /n/ /ctx/ +--+-- Notionally truncate @poly1@ and @poly2@ to length @n@ and set @res@ to+-- the difference.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_sub_series"+ fq_nmod_poly_sub_series :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_nmod_poly_neg/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @rop@ to the additive inverse of @(poly,len)@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_neg"+ _fq_nmod_poly_neg :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_neg/ /res/ /poly/ /ctx/ +--+-- Sets @res@ to the additive inverse of @poly@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_neg"+ fq_nmod_poly_neg :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- Scalar multiplication and division ------------------------------------------++-- | /_fq_nmod_poly_scalar_mul_fq_nmod/ /rop/ /op/ /len/ /x/ /ctx/ +--+-- Sets @(rop,len)@ to the product of @(op,len)@ by the scalar @x@, in the+-- context defined by @ctx@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_scalar_mul_fq_nmod"+ _fq_nmod_poly_scalar_mul_fq_nmod :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_scalar_mul_fq_nmod/ /rop/ /op/ /x/ /ctx/ +--+-- Sets @rop@ to the product of @op@ by the scalar @x@, in the context+-- defined by @ctx@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_scalar_mul_fq_nmod"+ fq_nmod_poly_scalar_mul_fq_nmod :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_scalar_addmul_fq_nmod/ /rop/ /op/ /len/ /x/ /ctx/ +--+-- Adds to @(rop,len)@ the product of @(op,len)@ by the scalar @x@, in the+-- context defined by @ctx@. In particular, assumes the same length for+-- @op@ and @rop@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_scalar_addmul_fq_nmod"+ _fq_nmod_poly_scalar_addmul_fq_nmod :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_scalar_addmul_fq_nmod/ /rop/ /op/ /x/ /ctx/ +--+-- Adds to @rop@ the product of @op@ by the scalar @x@, in the context+-- defined by @ctx@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_scalar_addmul_fq_nmod"+ fq_nmod_poly_scalar_addmul_fq_nmod :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_scalar_submul_fq_nmod/ /rop/ /op/ /len/ /x/ /ctx/ +--+-- Subtracts from @(rop,len)@ the product of @(op,len)@ by the scalar @x@,+-- in the context defined by @ctx@. In particular, assumes the same length+-- for @op@ and @rop@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_scalar_submul_fq_nmod"+ _fq_nmod_poly_scalar_submul_fq_nmod :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_scalar_submul_fq_nmod/ /rop/ /op/ /x/ /ctx/ +--+-- Subtracts from @rop@ the product of @op@ by the scalar @x@, in the+-- context defined by @ctx@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_scalar_submul_fq_nmod"+ fq_nmod_poly_scalar_submul_fq_nmod :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- -- | /_fq_nmod_poly_scalar_div_fq/ /rop/ /op/ /len/ /x/ /ctx/ +-- --+-- -- Sets @(rop,len)@ to the quotient of @(op,len)@ by the scalar @x@, in the+-- -- context defined by @ctx@. An exception is raised if @x@ is zero.+-- foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_scalar_div_fq"+-- _fq_nmod_poly_scalar_div_fq :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- -- | /fq_nmod_poly_scalar_div_fq/ /rop/ /op/ /x/ /ctx/ +-- --+-- -- Sets @rop@ to the quotient of @op@ by the scalar @x@, in the context+-- -- defined by @ctx@. An exception is raised if @x@ is zero.+-- foreign import ccall "fq_nmod_poly.h fq_nmod_poly_scalar_div_fq"+-- fq_nmod_poly_scalar_div_fq :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /_fq_nmod_poly_mul_classical/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@, assuming that @len1@ is at least @len2@ and neither is+-- zero.+-- +-- Permits zero padding. Does not support aliasing of @rop@ with either+-- @op1@ or @op2@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mul_classical"+ _fq_nmod_poly_mul_classical :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mul_classical/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@ using classical polynomial+-- multiplication.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mul_classical"+ fq_nmod_poly_mul_classical :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- -- | /_fq_nmod_poly_mul_reorder/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +-- --+-- -- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- -- @(op2, len2)@, assuming that @len1@ and @len2@ are non-zero.+-- -- +-- -- Permits zero padding. Supports aliasing.+-- foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mul_reorder"+-- _fq_nmod_poly_mul_reorder :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- -- | /fq_nmod_poly_mul_reorder/ /rop/ /op1/ /op2/ /ctx/ +-- --+-- -- Sets @rop@ to the product of @op1@ and @op2@, reordering the two+-- -- indeterminates \(X\) and \(Y\) when viewing the polynomials as elements+-- -- of \(\mathbf{F}_p[X,Y]\).+-- -- +-- -- Suppose \(\mathbf{F}_q = \mathbf{F}_p[X]/ (f(X))\) and recall that+-- -- elements of \(\mathbf{F}_q\) are internally represented by elements of+-- -- type @fmpz_poly@. For small degree extensions but polynomials in+-- -- \(\mathbf{F}_q[Y]\) of large degree \(n\), we change the representation+-- -- to+-- -- +-- -- \[`\]+-- -- \[\begin{aligned}+-- -- \begin{split}+-- -- g(Y) & = \sum_{i=0}^{n} a_i(X) Y^i \\+-- -- & = \sum_{j=0}^{d} \sum_{i=0}^{n} \text{Coeff}(a_i(X), j) Y^i.+-- -- \end{split}+-- -- \end{aligned}\]+-- -- +-- -- This allows us to use a poor algorithm (such as classical+-- -- multiplication) in the \(X\)-direction and leverage the existing fast+-- -- integer multiplication routines in the \(Y\)-direction where the+-- -- polynomial degree \(n\) is large.+-- foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mul_reorder"+-- fq_nmod_poly_mul_reorder :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_mul_univariate/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@.+-- +-- Permits zero padding and makes no assumptions on @len1@ and @len2@.+-- Supports aliasing.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mul_univariate"+ _fq_nmod_poly_mul_univariate :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mul_univariate/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@ using a bivariate to+-- univariate transformation and reducing this problem to multiplying two+-- univariate polynomials.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mul_univariate"+ fq_nmod_poly_mul_univariate :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_mul_KS/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@.+-- +-- Permits zero padding and places no assumptions on the lengths @len1@ and+-- @len2@. Supports aliasing.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mul_KS"+ _fq_nmod_poly_mul_KS :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mul_KS/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@ using Kronecker+-- substitution, that is, by encoding each coefficient in+-- \(\mathbf{F}_{q}\) as an integer and reducing this problem to+-- multiplying two polynomials over the integers.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mul_KS"+ fq_nmod_poly_mul_KS :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_mul/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@, choosing an appropriate algorithm.+-- +-- Permits zero padding. Does not support aliasing.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mul"+ _fq_nmod_poly_mul :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mul/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@, choosing an appropriate+-- algorithm.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mul"+ fq_nmod_poly_mul :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_mullow_classical/ /rop/ /op1/ /len1/ /op2/ /len2/ /n/ /ctx/ +--+-- Sets @(rop, n)@ to the first \(n\) coefficients of @(op1, len1)@+-- multiplied by @(op2, len2)@.+-- +-- Assumes @0 \< n \<= len1 + len2 - 1@. Assumes neither @len1@ nor @len2@+-- is zero.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mullow_classical"+ _fq_nmod_poly_mullow_classical :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mullow_classical/ /rop/ /op1/ /op2/ /n/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@, computed using the+-- classical or schoolbook method.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mullow_classical"+ fq_nmod_poly_mullow_classical :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_mullow_univariate/ /rop/ /op1/ /len1/ /op2/ /len2/ /n/ /ctx/ +--+-- Sets @(rop, n)@ to the lowest \(n\) coefficients of the product of+-- @(op1, len1)@ and @(op2, len2)@, computed using a bivariate to+-- univariate transformation.+-- +-- Assumes that @len1@ and @len2@ are positive, but does allow for the+-- polynomials to be zero-padded. The polynomials may be zero, too. Assumes+-- \(n\) is positive. Supports aliasing between @rop@, @op1@ and @op2@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mullow_univariate"+ _fq_nmod_poly_mullow_univariate :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mullow_univariate/ /rop/ /op1/ /op2/ /n/ /ctx/ +--+-- Sets @rop@ to the lowest \(n\) coefficients of the product of @poly1@+-- and @poly2@, computed using a bivariate to univariate transformation.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mullow_univariate"+ fq_nmod_poly_mullow_univariate :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_mullow_KS/ /rop/ /op1/ /len1/ /op2/ /len2/ /n/ /ctx/ +--+-- Sets @(rop, n)@ to the lowest \(n\) coefficients of the product of+-- @(op1, len1)@ and @(op2, len2)@.+-- +-- Assumes that @len1@ and @len2@ are positive, but does allow for the+-- polynomials to be zero-padded. The polynomials may be zero, too. Assumes+-- \(n\) is positive. Supports aliasing between @rop@, @op1@ and @op2@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mullow_KS"+ _fq_nmod_poly_mullow_KS :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mullow_KS/ /rop/ /op1/ /op2/ /n/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mullow_KS"+ fq_nmod_poly_mullow_KS :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_mullow/ /rop/ /op1/ /len1/ /op2/ /len2/ /n/ /ctx/ +--+-- Sets @(rop, n)@ to the lowest \(n\) coefficients of the product of+-- @(op1, len1)@ and @(op2, len2)@.+-- +-- Assumes @0 \< n \<= len1 + len2 - 1@. Allows for zero-padding in the+-- inputs. Does not support aliasing between the inputs and the output.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mullow"+ _fq_nmod_poly_mullow :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mullow/ /rop/ /op1/ /op2/ /n/ /ctx/ +--+-- Sets @rop@ to the lowest \(n\) coefficients of the product of @op1@ and+-- @op2@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mullow"+ fq_nmod_poly_mullow :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_mulhigh_classical/ /res/ /poly1/ /len1/ /poly2/ /len2/ /start/ /ctx/ +--+-- Computes the product of @(poly1, len1)@ and @(poly2, len2)@ and writes+-- the coefficients from @start@ onwards into the high coefficients of+-- @res@, the remaining coefficients being arbitrary but reduced. Assumes+-- that @len1 >= len2 > 0@. Aliasing of inputs and output is not permitted.+-- Algorithm is classical multiplication.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mulhigh_classical"+ _fq_nmod_poly_mulhigh_classical :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mulhigh_classical/ /res/ /poly1/ /poly2/ /start/ /ctx/ +--+-- Computes the product of @poly1@ and @poly2@ and writes the coefficients+-- from @start@ onwards into the high coefficients of @res@, the remaining+-- coefficients being arbitrary but reduced. Algorithm is classical+-- multiplication.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mulhigh_classical"+ fq_nmod_poly_mulhigh_classical :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_mulhigh/ /res/ /poly1/ /len1/ /poly2/ /len2/ /start/ /ctx/ +--+-- Computes the product of @(poly1, len1)@ and @(poly2, len2)@ and writes+-- the coefficients from @start@ onwards into the high coefficients of+-- @res@, the remaining coefficients being arbitrary but reduced. Assumes+-- that @len1 >= len2 > 0@. Aliasing of inputs and output is not permitted.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mulhigh"+ _fq_nmod_poly_mulhigh :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mulhigh/ /res/ /poly1/ /poly2/ /start/ /ctx/ +--+-- Computes the product of @poly1@ and @poly2@ and writes the coefficients+-- from @start@ onwards into the high coefficients of @res@, the remaining+-- coefficients being arbitrary but reduced.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mulhigh"+ fq_nmod_poly_mulhigh :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_mulmod/ /res/ /poly1/ /len1/ /poly2/ /len2/ /f/ /lenf/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+-- +-- It is required that @len1 + len2 - lenf > 0@, which is equivalent to+-- requiring that the result will actually be reduced. Otherwise, simply+-- use @_fq_nmod_poly_mul@ instead.+-- +-- Aliasing of @f@ and @res@ is not permitted.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mulmod"+ _fq_nmod_poly_mulmod :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mulmod/ /res/ /poly1/ /poly2/ /f/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mulmod"+ fq_nmod_poly_mulmod :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_mulmod_preinv/ /res/ /poly1/ /len1/ /poly2/ /len2/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+-- +-- It is required that @finv@ is the inverse of the reverse of @f@ mod+-- @x^lenf@.+-- +-- Aliasing of @res@ with any of the inputs is not permitted.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_mulmod_preinv"+ _fq_nmod_poly_mulmod_preinv :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_mulmod_preinv/ /res/ /poly1/ /poly2/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@. @finv@ is the inverse of the reverse of @f@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_mulmod_preinv"+ fq_nmod_poly_mulmod_preinv :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- Squaring --------------------------------------------------------------------++-- | /_fq_nmod_poly_sqr_classical/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, 2*len - 1)@ to the square of @(op, len)@, assuming that+-- @(op,len)@ is not zero and using classical polynomial multiplication.+-- +-- Permits zero padding. Does not support aliasing of @rop@ with either+-- @op1@ or @op2@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_sqr_classical"+ _fq_nmod_poly_sqr_classical :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_sqr_classical/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the square of @op@ using classical polynomial+-- multiplication.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_sqr_classical"+ fq_nmod_poly_sqr_classical :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_sqr_KS/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, 2*len - 1)@ to the square of @(op, len)@.+-- +-- Permits zero padding and places no assumptions on the lengths @len1@ and+-- @len2@. Supports aliasing.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_sqr_KS"+ _fq_nmod_poly_sqr_KS :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_sqr_KS/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the square @op@ using Kronecker substitution, that is, by+-- encoding each coefficient in \(\mathbf{F}_{q}\) as an integer and+-- reducing this problem to multiplying two polynomials over the integers.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_sqr_KS"+ fq_nmod_poly_sqr_KS :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_sqr/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, 2* len - 1)@ to the square of @(op, len)@, choosing an+-- appropriate algorithm.+-- +-- Permits zero padding. Does not support aliasing.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_sqr"+ _fq_nmod_poly_sqr :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_sqr/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the square of @op@, choosing an appropriate algorithm.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_sqr"+ fq_nmod_poly_sqr :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- Powering --------------------------------------------------------------------++-- | /_fq_nmod_poly_pow/ /rop/ /op/ /len/ /e/ /ctx/ +--+-- Sets @rop = op^e@, assuming that @e, len > 0@ and that @rop@ has space+-- for @e*(len - 1) + 1@ coefficients. Does not support aliasing.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_pow"+ _fq_nmod_poly_pow :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> CULong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_pow/ /rop/ /op/ /e/ /ctx/ +--+-- Computes @rop = op^e@. If \(e\) is zero, returns one, so that in+-- particular @0^0 = 1@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_pow"+ fq_nmod_poly_pow :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CULong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_powmod_ui_binexp/ /res/ /poly/ /e/ /f/ /lenf/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_powmod_ui_binexp"+ _fq_nmod_poly_powmod_ui_binexp :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CULong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_powmod_ui_binexp/ /res/ /poly/ /e/ /f/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_powmod_ui_binexp"+ fq_nmod_poly_powmod_ui_binexp :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CULong -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_powmod_ui_binexp_preinv/ /res/ /poly/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_powmod_ui_binexp_preinv"+ _fq_nmod_poly_powmod_ui_binexp_preinv :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CULong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_powmod_ui_binexp_preinv/ /res/ /poly/ /e/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_powmod_ui_binexp_preinv"+ fq_nmod_poly_powmod_ui_binexp_preinv :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CULong -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_powmod_fmpz_binexp/ /res/ /poly/ /e/ /f/ /lenf/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_powmod_fmpz_binexp"+ _fq_nmod_poly_powmod_fmpz_binexp :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> Ptr CFmpz -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_powmod_fmpz_binexp/ /res/ /poly/ /e/ /f/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_powmod_fmpz_binexp"+ fq_nmod_poly_powmod_fmpz_binexp :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFmpz -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_powmod_fmpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_powmod_fmpz_binexp_preinv"+ _fq_nmod_poly_powmod_fmpz_binexp_preinv :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> Ptr CFmpz -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_powmod_fmpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_powmod_fmpz_binexp_preinv"+ fq_nmod_poly_powmod_fmpz_binexp_preinv :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFmpz -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_powmod_fmpz_sliding_preinv/ /res/ /poly/ /e/ /k/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using+-- sliding-window exponentiation with window size @k@. We require @e > 0@.+-- We require @finv@ to be the inverse of the reverse of @f@. If @k@ is set+-- to zero, then an \"optimum\" size will be selected automatically base on+-- @e@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_powmod_fmpz_sliding_preinv"+ _fq_nmod_poly_powmod_fmpz_sliding_preinv :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> Ptr CFmpz -> CULong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_powmod_fmpz_sliding_preinv/ /res/ /poly/ /e/ /k/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using+-- sliding-window exponentiation with window size @k@. We require @e >= 0@.+-- We require @finv@ to be the inverse of the reverse of @f@. If @k@ is set+-- to zero, then an \"optimum\" size will be selected automatically base on+-- @e@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_powmod_fmpz_sliding_preinv"+ fq_nmod_poly_powmod_fmpz_sliding_preinv :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFmpz -> CULong -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_powmod_x_fmpz_preinv/ /res/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e > 0@. We require @finv@ to be the+-- inverse of the reverse of @f@.+-- +-- We require @lenf > 2@. The output @res@ must have room for @lenf - 1@+-- coefficients.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_powmod_x_fmpz_preinv"+ _fq_nmod_poly_powmod_x_fmpz_preinv :: Ptr (Ptr CFqNMod) -> Ptr CFmpz -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_powmod_x_fmpz_preinv/ /res/ /e/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e >= 0@. We require @finv@ to be the+-- inverse of the reverse of @f@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_powmod_x_fmpz_preinv"+ fq_nmod_poly_powmod_x_fmpz_preinv :: Ptr CFqNModPoly -> Ptr CFmpz -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_pow_trunc_binexp/ /res/ /poly/ /e/ /trunc/ /ctx/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ (assumed to be zero+-- padded if necessary to length @trunc@) to the power @e@. This is+-- equivalent to doing a powering followed by a truncation. We require that+-- @res@ has enough space for @trunc@ coefficients, that @trunc > 0@ and+-- that @e > 1@. Aliasing is not permitted. Uses the binary exponentiation+-- method.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_pow_trunc_binexp"+ _fq_nmod_poly_pow_trunc_binexp :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CULong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_pow_trunc_binexp/ /res/ /poly/ /e/ /trunc/ /ctx/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ to the power @e@.+-- This is equivalent to doing a powering followed by a truncation. Uses+-- the binary exponentiation method.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_pow_trunc_binexp"+ fq_nmod_poly_pow_trunc_binexp :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CULong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_pow_trunc/ /res/ /poly/ /e/ /trunc/ /mod/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ (assumed to be zero+-- padded if necessary to length @trunc@) to the power @e@. This is+-- equivalent to doing a powering followed by a truncation. We require that+-- @res@ has enough space for @trunc@ coefficients, that @trunc > 0@ and+-- that @e > 1@. Aliasing is not permitted.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_pow_trunc"+ _fq_nmod_poly_pow_trunc :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CULong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_pow_trunc/ /res/ /poly/ /e/ /trunc/ /ctx/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ to the power @e@.+-- This is equivalent to doing a powering followed by a truncation.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_pow_trunc"+ fq_nmod_poly_pow_trunc :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CULong -> CLong -> Ptr CFqNModCtx -> IO ()++-- Shifting --------------------------------------------------------------------++-- | /_fq_nmod_poly_shift_left/ /rop/ /op/ /len/ /n/ /ctx/ +--+-- Sets @(rop, len + n)@ to @(op, len)@ shifted left by \(n\) coefficients.+-- +-- Inserts zero coefficients at the lower end. Assumes that @len@ and \(n\)+-- are positive, and that @rop@ fits @len + n@ elements. Supports aliasing+-- between @rop@ and @op@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_shift_left"+ _fq_nmod_poly_shift_left :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_shift_left/ /rop/ /op/ /n/ /ctx/ +--+-- Sets @rop@ to @op@ shifted left by \(n\) coeffs. Zero coefficients are+-- inserted.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_shift_left"+ fq_nmod_poly_shift_left :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_shift_right/ /rop/ /op/ /len/ /n/ /ctx/ +--+-- Sets @(rop, len - n)@ to @(op, len)@ shifted right by \(n\)+-- coefficients.+-- +-- Assumes that @len@ and \(n\) are positive, that @len > n@, and that+-- @rop@ fits @len - n@ elements. Supports aliasing between @rop@ and @op@,+-- although in this case the top coefficients of @op@ are not set to zero.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_shift_right"+ _fq_nmod_poly_shift_right :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_shift_right/ /rop/ /op/ /n/ /ctx/ +--+-- Sets @rop@ to @op@ shifted right by \(n\) coefficients. If \(n\) is+-- equal to or greater than the current length of @op@, @rop@ is set to the+-- zero polynomial.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_shift_right"+ fq_nmod_poly_shift_right :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- Norms -----------------------------------------------------------------------++-- | /_fq_nmod_poly_hamming_weight/ /op/ /len/ /ctx/ +--+-- Returns the number of non-zero entries in @(op, len)@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_hamming_weight"+ _fq_nmod_poly_hamming_weight :: Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_poly_hamming_weight/ /op/ /ctx/ +--+-- Returns the number of non-zero entries in the polynomial @op@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_hamming_weight"+ fq_nmod_poly_hamming_weight :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CLong++-- Euclidean division ----------------------------------------------------------++-- | /_fq_nmod_poly_divrem/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Computes @(Q, lenA - lenB + 1)@, @(R, lenA)@ such that \(A = B Q + R\)+-- with \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- Assumes that the leading coefficient of \(B\) is invertible and that+-- @invB@ is its inverse.+-- +-- Assumes that \(\operatorname{len}(A), \operatorname{len}(B) > 0\).+-- Allows zero-padding in @(A, lenA)@. \(R\) and \(A\) may be aliased, but+-- apart from this no aliasing of input and output operands is allowed.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_divrem"+ _fq_nmod_poly_divrem :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_divrem/ /Q/ /R/ /A/ /B/ /ctx/ +--+-- Computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- Assumes that the leading coefficient of \(B\) is invertible. This can be+-- taken for granted the context is for a finite field, that is, when \(p\)+-- is prime and \(f(X)\) is irreducible.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_divrem"+ fq_nmod_poly_divrem :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_divrem_f/ /f/ /Q/ /R/ /A/ /B/ /ctx/ +--+-- Either finds a non-trivial factor \(f\) of the modulus of @ctx@, or+-- computes \(Q\), \(R\) such that \(A = B Q + R\) and+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- If the leading coefficient of \(B\) is invertible, the division with+-- remainder operation is carried out, \(Q\) and \(R\) are computed+-- correctly, and \(f\) is set to \(1\). Otherwise, \(f\) is set to a+-- non-trivial factor of the modulus and \(Q\) and \(R\) are not touched.+-- +-- Assumes that \(B\) is non-zero.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_divrem_f"+ fq_nmod_poly_divrem_f :: Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_rem/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Sets @R@ to the remainder of the division of @(A,lenA)@ by @(B,lenB)@.+-- Assumes that the leading coefficient of @(B,lenB)@ is invertible and+-- that @invB@ is its inverse.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_rem"+ _fq_nmod_poly_rem :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_rem/ /R/ /A/ /B/ /ctx/ +--+-- Sets @R@ to the remainder of the division of @A@ by @B@ in the context+-- described by @ctx@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_rem"+ fq_nmod_poly_rem :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_div/ /Q/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) with \(0+-- \leq \operatorname{len}(R) < \operatorname{len}(B)\) but only sets+-- @(Q, lenA - lenB + 1)@.+-- +-- Allows zero-padding in \(A\) but not in \(B\). Assumes that the leading+-- coefficient of \(B\) is a unit.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_div"+ _fq_nmod_poly_div :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_div/ /Q/ /A/ /B/ /ctx/ +--+-- Notionally finds polynomials \(Q\) and \(R\) such that \(A = B Q + R\)+-- with \(\operatorname{len}(R) < \operatorname{len}(B)\), but returns only+-- @Q@. If \(\operatorname{len}(B) = 0\) an exception is raised.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_div"+ fq_nmod_poly_div :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_div_newton_n_preinv/ /Q/ /A/ /lenA/ /B/ /lenB/ /Binv/ /lenBinv/ /ctx_t/ +--+-- Notionally computes polynomials \(Q\) and \(R\) such that \(A = BQ + R\)+-- with \(\operatorname{len}(R)\) less than @lenB@, where @A@ is of length+-- @lenA@ and @B@ is of length @lenB@, but return only \(Q\).+-- +-- We require that \(Q\) have space for @lenA - lenB + 1@ coefficients and+-- assume that the leading coefficient of \(B\) is a unit. Furthermore, we+-- assume that \(Binv\) is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\).+-- +-- The algorithm used is to reverse the polynomials and divide the+-- resulting power series, then reverse the result.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_div_newton_n_preinv"+ _fq_nmod_poly_div_newton_n_preinv :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNMod -> IO ()++-- | /fq_nmod_poly_div_newton_n_preinv/ /Q/ /A/ /B/ /Binv/ /ctx/ +--+-- Notionally computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R) < \operatorname{len}(B)\), but returns only+-- \(Q\).+-- +-- We assume that the leading coefficient of \(B\) is a unit and that+-- \(Binv\) is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\).+-- +-- It is required that the length of \(A\) is less than or equal to 2*the+-- length of \(B\) - 2.+-- +-- The algorithm used is to reverse the polynomials and divide the+-- resulting power series, then reverse the result.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_div_newton_n_preinv"+ fq_nmod_poly_div_newton_n_preinv :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_divrem_newton_n_preinv/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /Binv/ /lenBinv/ /ctx/ +--+-- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R)\) less than @lenB@, where \(A\) is of length+-- @lenA@ and \(B\) is of length @lenB@. We require that \(Q\) have space+-- for @lenA - lenB + 1@ coefficients. Furthermore, we assume that \(Binv\)+-- is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\). The algorithm used is to call+-- @div_newton_preinv@ and then multiply out and compute the remainder.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_divrem_newton_n_preinv"+ _fq_nmod_poly_divrem_newton_n_preinv :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_divrem_newton_n_preinv/ /Q/ /R/ /A/ /B/ /Binv/ /ctx/ +--+-- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R) <+-- \operatorname{len}(B)\). We assume \(Binv\) is the inverse of the+-- reverse of \(B\) mod \(x^{\operatorname{len}(B)}\).+-- +-- It is required that the length of \(A\) is less than or equal to 2*the+-- length of \(B\) - 2.+-- +-- The algorithm used is to call @div_newton@ and then multiply out and+-- compute the remainder.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_divrem_newton_n_preinv"+ fq_nmod_poly_divrem_newton_n_preinv :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_inv_series_newton/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ of length @n@ whose constant coefficient is invertible modulo+-- the given modulus, find a polynomial @Qinv@ of length @n@ such that+-- @Q * Qinv@ is @1@ modulo \(x^n\). Requires @n > 0@. This function can be+-- viewed as inverting a power series via Newton iteration.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_inv_series_newton"+ _fq_nmod_poly_inv_series_newton :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_inv_series_newton/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ find @Qinv@ such that @Q * Qinv@ is @1@ modulo \(x^n\). The+-- constant coefficient of @Q@ must be invertible modulo the modulus of+-- @Q@. An exception is raised if this is not the case or if @n = 0@. This+-- function can be viewed as inverting a power series via Newton iteration.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_inv_series_newton"+ fq_nmod_poly_inv_series_newton :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_inv_series/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ of length @n@ whose constant coefficient is invertible modulo+-- the given modulus, find a polynomial @Qinv@ of length @n@ such that+-- @Q * Qinv@ is @1@ modulo \(x^n\). Requires @n > 0@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_inv_series"+ _fq_nmod_poly_inv_series :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_inv_series/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ find @Qinv@ such that @Q * Qinv@ is @1@ modulo \(x^n\). The+-- constant coefficient of @Q@ must be invertible modulo the modulus of+-- @Q@. An exception is raised if this is not the case or if @n = 0@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_inv_series"+ fq_nmod_poly_inv_series :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_div_series/ /Q/ /A/ /Alen/ /B/ /Blen/ /n/ /ctx/ +--+-- Set @(Q, n)@ to the quotient of the series @(A, Alen@) and @(B, Blen)@+-- assuming @Alen, Blen \<= n@. We assume the bottom coefficient of @B@ is+-- invertible.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_div_series"+ _fq_nmod_poly_div_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_nmod_poly_div_series/ /Q/ /A/ /B/ /n/ /ctx/ +--+-- Set \(Q\) to the quotient of the series \(A\) by \(B\), thinking of the+-- series as though they were of length \(n\). We assume that the bottom+-- coefficient of \(B\) is invertible.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_div_series"+ fq_nmod_poly_div_series :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFqCtx -> IO ()++-- Greatest common divisor -----------------------------------------------------++-- | /fq_nmod_poly_gcd/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the greatest common divisor of @op1@ and @op2@, using the+-- either the Euclidean or HGCD algorithm. The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_gcd"+ fq_nmod_poly_gcd :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_gcd/ /G/ /A/ /lenA/ /B/ /lenB/ /ctx/ +--+-- Computes the GCD of \(A\) of length @lenA@ and \(B\) of length @lenB@,+-- where @lenA >= lenB > 0@ and sets \(G\) to it. The length of the GCD+-- \(G\) is returned by the function. No attempt is made to make the GCD+-- monic. It is required that \(G\) have space for @lenB@ coefficients.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_gcd"+ _fq_nmod_poly_gcd :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO CLong++-- | /_fq_nmod_poly_gcd_euclidean_f/ /f/ /G/ /A/ /lenA/ /B/ /lenB/ /ctx/ +--+-- Either sets \(f = 1\) and \(G\) to the greatest common divisor of+-- \((A,\operatorname{len}(A))\) and \((B, \operatorname{len}(B))\) and+-- returns its length, or sets \(f\) to a non-trivial factor of the modulus+-- of @ctx@ and leaves the contents of the vector \((G, lenB)\) undefined.+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\)+-- and that the vector \(G\) has space for sufficiently many coefficients.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_gcd_euclidean_f"+ _fq_nmod_poly_gcd_euclidean_f :: Ptr CFqNMod -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_poly_gcd_euclidean_f/ /f/ /G/ /A/ /B/ /ctx/ +--+-- Either sets \(f = 1\) and \(G\) to the greatest common divisor of \(A\)+-- and \(B\) or sets \(f\) to a factor of the modulus of @ctx@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_gcd_euclidean_f"+ fq_nmod_poly_gcd_euclidean_f :: Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_xgcd/ /G/ /S/ /T/ /A/ /lenA/ /B/ /lenB/ /ctx/ +--+-- Computes the GCD of \(A\) and \(B\) together with cofactors \(S\) and+-- \(T\) such that \(S A + T B = G\). Returns the length of \(G\).+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1\)+-- and \((\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)\).+-- +-- No attempt is made to make the GCD monic.+-- +-- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- coefficients. Writes \(\operatorname{len}(B)-1\) and+-- \(\operatorname{len}(A)-1\) coefficients to \(S\) and \(T\),+-- respectively. Note that, in fact,+-- \(\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)\)+-- and+-- \(\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)\).+-- +-- No aliasing of input and output operands is permitted.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_xgcd"+ _fq_nmod_poly_xgcd :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_poly_xgcd/ /G/ /S/ /T/ /A/ /B/ /ctx/ +--+-- Computes the GCD of \(A\) and \(B\). The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+-- +-- Polynomials @S@ and @T@ are computed such that @S*A + T*B = G@. The+-- length of @S@ will be at most @lenB@ and the length of @T@ will be at+-- most @lenA@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_xgcd"+ fq_nmod_poly_xgcd :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_xgcd_euclidean_f/ /f/ /G/ /S/ /T/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Either sets \(f = 1\) and computes the GCD of \(A\) and \(B\) together+-- with cofactors \(S\) and \(T\) such that \(S A + T B = G\); otherwise,+-- sets \(f\) to a non-trivial factor of the modulus of @ctx@ and leaves+-- \(G\), \(S\), and \(T\) undefined. Returns the length of \(G\).+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1\)+-- and \((\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)\).+-- +-- No attempt is made to make the GCD monic.+-- +-- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- coefficients. Writes \(\operatorname{len}(B)-1\) and+-- \(\operatorname{len}(A)-1\) coefficients to \(S\) and \(T\),+-- respectively. Note that, in fact,+-- \(\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)\)+-- and+-- \(\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)\).+-- +-- No aliasing of input and output operands is permitted.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_xgcd_euclidean_f"+ _fq_nmod_poly_xgcd_euclidean_f :: Ptr CFqNMod -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFmpz -> Ptr CFqNModCtx -> IO CLong++-- | /fq_nmod_poly_xgcd_euclidean_f/ /f/ /G/ /S/ /T/ /A/ /B/ /ctx/ +--+-- Either sets \(f = 1\) and computes the GCD of \(A\) and \(B\) or sets+-- \(f\) to a non-trivial factor of the modulus of @ctx@.+-- +-- If the GCD is computed, polynomials @S@ and @T@ are computed such that+-- @S*A + T*B = G@; otherwise, they are undefined. The length of @S@ will+-- be at most @lenB@ and the length of @T@ will be at most @lenA@.+-- +-- The GCD of zero polynomials is defined to be zero, whereas the GCD of+-- the zero polynomial and some other polynomial \(P\) is defined to be+-- \(P\). Except in the case where the GCD is zero, the GCD \(G\) is made+-- monic.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_xgcd_euclidean_f"+ fq_nmod_poly_xgcd_euclidean_f :: Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- Divisibility testing --------------------------------------------------------++-- | /_fq_nmod_poly_divides/ /Q/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Returns \(1\) if @(B, lenB)@ divides @(A, lenA)@ exactly and sets \(Q\)+-- to the quotient, otherwise returns \(0\).+-- +-- It is assumed that+-- \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\) and that \(Q\)+-- has space for \(\operatorname{len}(A) - \operatorname{len}(B) + 1\)+-- coefficients.+-- +-- Aliasing of \(Q\) with either of the inputs is not permitted.+-- +-- This function is currently unoptimised and provided for convenience+-- only.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_divides"+ _fq_nmod_poly_divides :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_divides/ /Q/ /A/ /B/ /ctx/ +--+-- Returns \(1\) if \(B\) divides \(A\) exactly and sets \(Q\) to the+-- quotient, otherwise returns \(0\).+-- +-- This function is currently unoptimised and provided for convenience+-- only.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_divides"+ fq_nmod_poly_divides :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt++-- Derivative ------------------------------------------------------------------++-- | /_fq_nmod_poly_derivative/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, len - 1)@ to the derivative of @(op, len)@. Also handles the+-- cases where @len@ is \(0\) or \(1\) correctly. Supports aliasing of+-- @rop@ and @op@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_derivative"+ _fq_nmod_poly_derivative :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_derivative/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the derivative of @op@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_derivative"+ fq_nmod_poly_derivative :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- Square root -----------------------------------------------------------------++-- | /_fq_nmod_poly_invsqrt_series/ /g/ /h/ /n/ /mod/ +--+-- Set the first \(n\) terms of \(g\) to the series expansion of+-- \(1/\sqrt{h}\). It is assumed that \(n > 0\), that \(h\) has constant+-- term 1 and that \(h\) is zero-padded as necessary to length \(n\).+-- Aliasing is not permitted.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_invsqrt_series"+ _fq_nmod_poly_invsqrt_series :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_invsqrt_series/ /g/ /h/ /n/ /ctx/ +--+-- Set \(g\) to the series expansion of \(1/\sqrt{h}\) to order \(O(x^n)\).+-- It is assumed that \(h\) has constant term 1.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_invsqrt_series"+ fq_nmod_poly_invsqrt_series :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_sqrt_series/ /g/ /h/ /n/ /ctx/ +--+-- Set the first \(n\) terms of \(g\) to the series expansion of+-- \(\sqrt{h}\). It is assumed that \(n > 0\), that \(h\) has constant term+-- 1 and that \(h\) is zero-padded as necessary to length \(n\). Aliasing+-- is not permitted.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_sqrt_series"+ _fq_nmod_poly_sqrt_series :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_sqrt_series/ /g/ /h/ /n/ /ctx/ +--+-- Set \(g\) to the series expansion of \(\sqrt{h}\) to order \(O(x^n)\).+-- It is assumed that \(h\) has constant term 1.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_sqrt_series"+ fq_nmod_poly_sqrt_series :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_sqrt/ /s/ /p/ /n/ /mod/ +--+-- If @(p, n)@ is a perfect square, sets @(s, n \/ 2 + 1)@ to a square root+-- of \(p\) and returns 1. Otherwise returns 0.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_sqrt"+ _fq_nmod_poly_sqrt :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_sqrt/ /s/ /p/ /mod/ +--+-- If \(p\) is a perfect square, sets \(s\) to a square root of \(p\) and+-- returns 1. Otherwise returns 0.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_sqrt"+ fq_nmod_poly_sqrt :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt++-- Evaluation ------------------------------------------------------------------++-- | /_fq_nmod_poly_evaluate_fq_nmod/ /rop/ /op/ /len/ /a/ /ctx/ +--+-- Sets @rop@ to @(op, len)@ evaluated at \(a\).+-- +-- Supports zero padding. There are no restrictions on @len@, that is,+-- @len@ is allowed to be zero, too.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_evaluate_fq_nmod"+ _fq_nmod_poly_evaluate_fq_nmod :: Ptr CFqNMod -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_evaluate_fq_nmod/ /rop/ /f/ /a/ /ctx/ +--+-- Sets @rop@ to the value of \(f(a)\).+-- +-- As the coefficient ring \(\mathbf{F}_q\) is finite, Horner\'s method is+-- sufficient.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_evaluate_fq_nmod"+ fq_nmod_poly_evaluate_fq_nmod :: Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- Composition -----------------------------------------------------------------++-- | /_fq_nmod_poly_compose/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @rop@ to the composition of @(op1, len1)@ and @(op2, len2)@.+-- +-- Assumes that @rop@ has space for @(len1-1)*(len2-1) + 1@ coefficients.+-- Assumes that @op1@ and @op2@ are non-zero polynomials. Does not support+-- aliasing between any of the inputs and the output.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_compose"+ _fq_nmod_poly_compose :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_compose/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the composition of @op1@ and @op2@. To be precise about+-- the order of composition, denoting @rop@, @op1@, and @op2@ by \(f\),+-- \(g\), and \(h\), respectively, sets \(f(t) = g(h(t))\).+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_compose"+ fq_nmod_poly_compose :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_compose_mod_horner/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). The output is not allowed+-- to be aliased with any of the inputs.+-- +-- The algorithm used is Horner\'s rule.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_compose_mod_horner"+ _fq_nmod_poly_compose_mod_horner :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_compose_mod_horner/ /res/ /f/ /g/ /h/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero. The algorithm used is Horner\'s rule.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_compose_mod_horner"+ fq_nmod_poly_compose_mod_horner :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_compose_mod_horner_preinv/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /hinv/ /lenhiv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+-- +-- The algorithm used is Horner\'s rule.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_compose_mod_horner_preinv"+ _fq_nmod_poly_compose_mod_horner_preinv :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_compose_mod_horner_preinv/ /res/ /f/ /g/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+-- The algorithm used is Horner\'s rule.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_compose_mod_horner_preinv"+ fq_nmod_poly_compose_mod_horner_preinv :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_compose_mod_brent_kung/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). The output is not+-- allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_compose_mod_brent_kung"+ _fq_nmod_poly_compose_mod_brent_kung :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_compose_mod_brent_kung/ /res/ /f/ /g/ /h/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\). The+-- algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_compose_mod_brent_kung"+ fq_nmod_poly_compose_mod_brent_kung :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_compose_mod_brent_kung_preinv/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /hinv/ /lenhiv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_compose_mod_brent_kung_preinv"+ _fq_nmod_poly_compose_mod_brent_kung_preinv :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_compose_mod_brent_kung_preinv/ /res/ /f/ /g/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_compose_mod_brent_kung_preinv"+ fq_nmod_poly_compose_mod_brent_kung_preinv :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_compose_mod/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). The output is not allowed+-- to be aliased with any of the inputs.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_compose_mod"+ _fq_nmod_poly_compose_mod :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_compose_mod/ /res/ /f/ /g/ /h/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_compose_mod"+ fq_nmod_poly_compose_mod :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_compose_mod_preinv/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /hinv/ /lenhiv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_compose_mod_preinv"+ _fq_nmod_poly_compose_mod_preinv :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_compose_mod_preinv/ /res/ /f/ /g/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_compose_mod_preinv"+ fq_nmod_poly_compose_mod_preinv :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_reduce_matrix_mod_poly/ /A/ /B/ /f/ /ctx/ +--+-- Sets the ith row of @A@ to the reduction of the ith row of \(B\) modulo+-- \(f\) for \(i=1,\ldots,\sqrt{\deg(f)}\). We require \(B\) to be at least+-- a \(\sqrt{\deg(f)}\times \deg(f)\) matrix and \(f\) to be nonzero.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_reduce_matrix_mod_poly"+ _fq_nmod_poly_reduce_matrix_mod_poly :: Ptr CFqNModMat -> Ptr CFqNModMat -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_precompute_matrix/ /A/ /f/ /g/ /leng/ /ginv/ /lenginv/ /ctx/ +--+-- Sets the ith row of @A@ to \(f^i\) modulo \(g\) for+-- \(i=1,\ldots,\sqrt{\deg(g)}\). We require \(A\) to be a+-- \(\sqrt{\deg(g)}\times \deg(g)\) matrix. We require @ginv@ to be the+-- inverse of the reverse of @g@ and \(g\) to be nonzero.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_precompute_matrix"+ _fq_nmod_poly_precompute_matrix :: Ptr CFqNModMat -> Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_precompute_matrix/ /A/ /f/ /g/ /ginv/ /ctx/ +--+-- Sets the ith row of @A@ to \(f^i\) modulo \(g\) for+-- \(i=1,\ldots,\sqrt{\deg(g)}\). We require \(A\) to be a+-- \(\sqrt{\deg(g)}\times \deg(g)\) matrix. We require @ginv@ to be the+-- inverse of the reverse of @g@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_precompute_matrix"+ fq_nmod_poly_precompute_matrix :: Ptr CFqNModMat -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_poly_compose_mod_brent_kung_precomp_preinv/ /res/ /f/ /lenf/ /A/ /h/ /lenh/ /hinv/ /lenhinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero. We require that the ith row of \(A\) contains \(g^i\)+-- for \(i=1,\ldots,\sqrt{\deg(h)}\), i.e. \(A\) is a+-- \(\sqrt{\deg(h)}\times \deg(h)\) matrix. We also require that the length+-- of \(f\) is less than the length of \(h\). Furthermore, we require+-- @hinv@ to be the inverse of the reverse of @h@. The output is not+-- allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_compose_mod_brent_kung_precomp_preinv"+ _fq_nmod_poly_compose_mod_brent_kung_precomp_preinv :: Ptr (Ptr CFqNMod) -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModMat -> Ptr (Ptr CFqNMod) -> CLong -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_compose_mod_brent_kung_precomp_preinv/ /res/ /f/ /A/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that the+-- ith row of \(A\) contains \(g^i\) for \(i=1,\ldots,\sqrt{\deg(h)}\),+-- i.e. \(A\) is a \(\sqrt{\deg(h)}\times+-- \deg(h)\) matrix. We require that \(h\) is nonzero and that \(f\) has+-- smaller degree than \(h\). Furthermore, we require @hinv@ to be the+-- inverse of the reverse of @h@. This version of Brent-Kung modular+-- composition is particularly useful if one has to perform several modular+-- composition of the form \(f(g)\) modulo \(h\) for fixed \(g\) and \(h\).+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_compose_mod_brent_kung_precomp_preinv"+ fq_nmod_poly_compose_mod_brent_kung_precomp_preinv :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModMat -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- Output ----------------------------------------------------------------------++-- | /_fq_nmod_poly_fprint_pretty/ /file/ /poly/ /len/ /x/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to the stream @file@,+-- using the string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_fprint_pretty"+ _fq_nmod_poly_fprint_pretty :: Ptr CFile -> Ptr (Ptr CFqNMod) -> CLong -> CString -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_fprint_pretty/ /file/ /poly/ /x/ /ctx/ +--+-- Prints the pretty representation of @poly@ to the stream @file@, using+-- the string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_fprint_pretty"+ fq_nmod_poly_fprint_pretty :: Ptr CFile -> Ptr CFqNModPoly -> CString -> Ptr CFqNModCtx -> IO CInt++-- | /_fq_nmod_poly_print_pretty/ /poly/ /len/ /x/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to @stdout@, using the+-- string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_print_pretty"+ _fq_nmod_poly_print_pretty :: Ptr (Ptr CFqNMod) -> CLong -> CString -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_print_pretty/ /poly/ /x/ /ctx/ +--+-- Prints the pretty representation of @poly@ to @stdout@, using the string+-- @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+fq_nmod_poly_print_pretty :: Ptr CFqNModPoly -> CString -> Ptr CFqNModCtx -> IO CInt+fq_nmod_poly_print_pretty poly x ctx = + printCStr (\poly -> fq_nmod_poly_get_str_pretty poly x ctx) poly+ +-- | /_fq_nmod_poly_fprint/ /file/ /poly/ /len/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_fprint"+ _fq_nmod_poly_fprint :: Ptr CFile -> Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_fprint/ /file/ /poly/ /ctx/ +--+-- Prints the pretty representation of @poly@ to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_fprint"+ fq_nmod_poly_fprint :: Ptr CFile -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt++-- | /_fq_nmod_poly_print/ /poly/ /len/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_print"+ _fq_nmod_poly_print :: Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_print/ /poly/ /ctx/ +--+-- Prints the representation of @poly@ to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+fq_nmod_poly_print :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt+fq_nmod_poly_print poly ctx = printCStr (`fq_nmod_poly_get_str` ctx) poly++-- | /_fq_nmod_poly_get_str/ /poly/ /len/ /ctx/ +--+-- Returns the plain FLINT string representation of the polynomial+-- @(poly, len)@.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_get_str"+ _fq_nmod_poly_get_str :: Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO CString++-- | /fq_nmod_poly_get_str/ /poly/ /ctx/ +--+-- Returns the plain FLINT string representation of the polynomial @poly@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_get_str"+ fq_nmod_poly_get_str :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CString++-- | /_fq_nmod_poly_get_str_pretty/ /poly/ /len/ /x/ /ctx/ +--+-- Returns a pretty representation of the polynomial @(poly, len)@ using+-- the null-terminated string @x@ as the variable name.+foreign import ccall "fq_nmod_poly.h _fq_nmod_poly_get_str_pretty"+ _fq_nmod_poly_get_str_pretty :: Ptr (Ptr CFqNMod) -> CLong -> CString -> Ptr CFqNModCtx -> IO CString++-- | /fq_nmod_poly_get_str_pretty/ /poly/ /x/ /ctx/ +--+-- Returns a pretty representation of the polynomial @poly@ using the+-- null-terminated string @x@ as the variable name+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_get_str_pretty"+ fq_nmod_poly_get_str_pretty :: Ptr CFqNModPoly -> CString -> Ptr CFqNModCtx -> IO CString++-- Inflation and deflation -----------------------------------------------------++-- | /fq_nmod_poly_inflate/ /result/ /input/ /inflation/ /ctx/ +--+-- Sets @result@ to the inflated polynomial \(p(x^n)\) where \(p\) is given+-- by @input@ and \(n\) is given by @inflation@.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_inflate"+ fq_nmod_poly_inflate :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CULong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_deflate/ /result/ /input/ /deflation/ /ctx/ +--+-- Sets @result@ to the deflated polynomial \(p(x^{1/n})\) where \(p\) is+-- given by @input@ and \(n\) is given by @deflation@. Requires \(n > 0\).+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_deflate"+ fq_nmod_poly_deflate :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> CULong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_deflation/ /input/ /ctx/ +--+-- Returns the largest integer by which @input@ can be deflated. As special+-- cases, returns 0 if @input@ is the zero polynomial and 1 of @input@ is a+-- constant polynomial.+foreign import ccall "fq_nmod_poly.h fq_nmod_poly_deflation"+ fq_nmod_poly_deflation :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CULong+
+ src/Data/Number/Flint/Fq/NMod/Poly/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fq.NMod.Poly.Factor (+ module Data.Number.Flint.Fq.NMod.Poly.Factor.FFI+ ) where++import Data.Number.Flint.Fq.NMod.Poly.Factor.FFI
+ src/Data/Number/Flint/Fq/NMod/Poly/Factor/FFI.hsc view
@@ -0,0 +1,387 @@+{-|+module : Data.Number.Flint.Fq.NMod.Poly.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.NMod.Poly.Factor.FFI (+ -- * Factorisation of univariate polynomials over finite fields+ -- (word-size characteristic)+ FqNModPolyFactor (..)+ , CFqNModPolyFactor (..)+ , newFqNModPolyFactor+ , withFqNModPolyFactor+ -- * Memory Management+ , fq_nmod_poly_factor_init+ , fq_nmod_poly_factor_clear+ , fq_nmod_poly_factor_realloc+ , fq_nmod_poly_factor_fit_length+ -- * Basic Operations+ , fq_nmod_poly_factor_set+ , fq_nmod_poly_factor_print_pretty+ , fq_nmod_poly_factor_print+ , fq_nmod_poly_factor_insert+ , fq_nmod_poly_factor_concat+ , fq_nmod_poly_factor_pow+ , fq_nmod_poly_remove+ -- * Irreducibility Testing+ , fq_nmod_poly_is_irreducible+ , fq_nmod_poly_is_irreducible_ddf+ , fq_nmod_poly_is_irreducible_ben_or+ , _fq_nmod_poly_is_squarefree+ , fq_nmod_poly_is_squarefree+ -- * Factorisation+ , fq_nmod_poly_factor_equal_deg_prob+ , fq_nmod_poly_factor_equal_deg+ , fq_nmod_poly_factor_split_single+ , fq_nmod_poly_factor_distinct_deg+ , fq_nmod_poly_factor_squarefree+ , fq_nmod_poly_factor+ , fq_nmod_poly_factor_cantor_zassenhaus+ , fq_nmod_poly_factor_kaltofen_shoup+ , fq_nmod_poly_factor_berlekamp+ , fq_nmod_poly_factor_with_berlekamp+ , fq_nmod_poly_factor_with_cantor_zassenhaus+ , fq_nmod_poly_factor_with_kaltofen_shoup+ , fq_nmod_poly_iterated_frobenius_preinv+ -- * Root Finding+ , fq_nmod_poly_roots+) where ++-- Factorisation of univariate polynomials over finite fields+-- (word-size characteristic)++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Marshal.Array ( advancePtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mod.Poly++import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.NMod.Mat++import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.Types++import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Mat++import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Poly+import Data.Number.Flint.Fq.NMod.Types++#include <flint/flint.h>+#include <flint/fq_nmod_poly.h>++-- fq_nmod_poly_factor_t -------------------------------------------------------++instance Storable CFqNModPolyFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_nmod_poly_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_nmod_poly_factor_t}+ peek ptr = CFqNModPolyFactor+ <$> #{peek fq_nmod_poly_factor_struct, poly } ptr+ <*> #{peek fq_nmod_poly_factor_struct, exp } ptr+ <*> #{peek fq_nmod_poly_factor_struct, num } ptr+ <*> #{peek fq_nmod_poly_factor_struct, alloc} ptr+ poke = undefined++newFqNModPolyFactor ctx@(FqNModCtx ftx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqNModCtx ctx $ \ctx -> do+ fq_nmod_poly_factor_init x ctx+ addForeignPtrFinalizerEnv p_fq_nmod_poly_factor_clear x ftx+ return $ FqNModPolyFactor x++{-# INLINE withFqNModPolyFactor #-}+withFqNModPolyFactor (FqNModPolyFactor x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqNModPolyFactor x,)++-- Memory Management -----------------------------------------------------------++-- | /fq_nmod_poly_factor_init/ /fac/ /ctx/ +--+-- Initialises @fac@ for use. An @fq_nmod_poly_factor_t@ represents a+-- polynomial in factorised form as a product of polynomials with+-- associated exponents.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_init"+ fq_nmod_poly_factor_init :: Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_clear/ /fac/ /ctx/ +--+-- Frees all memory associated with @fac@.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_clear"+ fq_nmod_poly_factor_clear :: Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ()++foreign import ccall "fq_nmod_poly_factor.h &fq_nmod_poly_factor_clear"+ p_fq_nmod_poly_factor_clear :: FunPtr (Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ())++-- | /fq_nmod_poly_factor_realloc/ /fac/ /alloc/ /ctx/ +--+-- Reallocates the factor structure to provide space for precisely @alloc@+-- factors.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_realloc"+ fq_nmod_poly_factor_realloc :: Ptr CFqNModPolyFactor -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_fit_length/ /fac/ /len/ /ctx/ +--+-- Ensures that the factor structure has space for at least @len@ factors.+-- This function takes care of the case of repeated calls by always at+-- least doubling the number of factors the structure can hold.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_fit_length"+ fq_nmod_poly_factor_fit_length :: Ptr CFqNModPolyFactor -> CLong -> Ptr CFqNModCtx -> IO ()++-- Basic Operations ------------------------------------------------------------++-- | /fq_nmod_poly_factor_set/ /res/ /fac/ /ctx/ +--+-- Sets @res@ to the same factorisation as @fac@.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_set"+ fq_nmod_poly_factor_set :: Ptr CFqNModPolyFactor -> Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_print_pretty/ /fac/ /ctx/ +--+-- Pretty-prints the entries of @fac@ to standard output.+fq_nmod_poly_factor_print_pretty :: Ptr CFqNModPolyFactor+ -> CString+ -> Ptr CFqNModCtx+ -> IO ()+fq_nmod_poly_factor_print_pretty fac var ctx = do+ CFqNModPolyFactor poly exp num alloc <- peek fac+ forM_ [0 .. fromIntegral num - 1] $ \j -> do+ fq_nmod_poly_print_pretty (poly `advancePtr` j) var ctx+ putStr " ^ "+ e <- peek (exp `advancePtr` j)+ putStrLn $ show e +++-- | /fq_nmod_poly_factor_print/ /fac/ /ctx/ +--+-- Prints the entries of @fac@ to standard output.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_print"+ fq_nmod_poly_factor_print :: Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_insert/ /fac/ /poly/ /exp/ /ctx/ +--+-- Inserts the factor @poly@ with multiplicity @exp@ into the factorisation+-- @fac@.+-- +-- If @fac@ already contains @poly@, then @exp@ simply gets added to the+-- exponent of the existing entry.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_insert"+ fq_nmod_poly_factor_insert :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_concat/ /res/ /fac/ /ctx/ +--+-- Concatenates two factorisations.+-- +-- This is equivalent to calling @fq_nmod_poly_factor_insert@ repeatedly+-- with the individual factors of @fac@.+-- +-- Does not support aliasing between @res@ and @fac@.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_concat"+ fq_nmod_poly_factor_concat :: Ptr CFqNModPolyFactor -> Ptr CFqNModPolyFactor -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_pow/ /fac/ /exp/ /ctx/ +--+-- Raises @fac@ to the power @exp@.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_pow"+ fq_nmod_poly_factor_pow :: Ptr CFqNModPolyFactor -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_remove/ /f/ /p/ /ctx/ +--+-- Removes the highest possible power of @p@ from @f@ and returns the+-- exponent.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_remove"+ fq_nmod_poly_remove :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CULong++-- Irreducibility Testing ------------------------------------------------------++-- | /fq_nmod_poly_is_irreducible/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_is_irreducible"+ fq_nmod_poly_is_irreducible :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_is_irreducible_ddf/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+-- Uses fast distinct-degree factorisation.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_is_irreducible_ddf"+ fq_nmod_poly_is_irreducible_ddf :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_is_irreducible_ben_or/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+-- Uses Ben-Or\'s irreducibility test.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_is_irreducible_ben_or"+ fq_nmod_poly_is_irreducible_ben_or :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt++-- | /_fq_nmod_poly_is_squarefree/ /f/ /len/ /ctx/ +--+-- Returns 1 if @(f, len)@ is squarefree, and 0 otherwise. As a special+-- case, the zero polynomial is not considered squarefree. There are no+-- restrictions on the length.+foreign import ccall "fq_nmod_poly_factor.h _fq_nmod_poly_is_squarefree"+ _fq_nmod_poly_is_squarefree :: Ptr (Ptr CFqNMod) -> CLong -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_is_squarefree/ /f/ /ctx/ +--+-- Returns 1 if @f@ is squarefree, and 0 otherwise. As a special case, the+-- zero polynomial is not considered squarefree.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_is_squarefree"+ fq_nmod_poly_is_squarefree :: Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO CInt++-- Factorisation ---------------------------------------------------------------++-- | /fq_nmod_poly_factor_equal_deg_prob/ /factor/ /state/ /pol/ /d/ /ctx/ +--+-- Probabilistic equal degree factorisation of @pol@ into irreducible+-- factors of degree @d@. If it passes, a factor is placed in factor and 1+-- is returned, otherwise 0 is returned and the value of factor is+-- undetermined.+-- +-- Requires that @pol@ be monic, non-constant and squarefree.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_equal_deg_prob"+ fq_nmod_poly_factor_equal_deg_prob :: Ptr CFqNModPoly -> Ptr CFRandState -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO CInt++-- | /fq_nmod_poly_factor_equal_deg/ /factors/ /pol/ /d/ /ctx/ +--+-- Assuming @pol@ is a product of irreducible factors all of degree @d@,+-- finds all those factors and places them in factors. Requires that @pol@+-- be monic, non-constant and squarefree.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_equal_deg"+ fq_nmod_poly_factor_equal_deg :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_split_single/ /linfactor/ /input/ /ctx/ +--+-- Assuming @input@ is a product of factors all of degree 1, finds a single+-- linear factor of @input@ and places it in @linfactor@. Requires that+-- @input@ be monic and non-constant.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_split_single"+ fq_nmod_poly_factor_split_single :: Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_distinct_deg/ /res/ /poly/ /degs/ /ctx/ +--+-- Factorises a monic non-constant squarefree polynomial @poly@ of degree+-- \(n\) into factors \(f[d]\) such that for \(1 \leq d \leq n\) \(f[d]\)+-- is the product of the monic irreducible factors of @poly@ of degree+-- \(d\). Factors are stored in @res@, associated powers of irreducible+-- polynomials are stored in @degs@ in the same order as factors.+-- +-- Requires that @degs@ have enough space for irreducible polynomials\'+-- powers (maximum space required is \(n * sizeof(slong)\)).+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_distinct_deg"+ fq_nmod_poly_factor_distinct_deg :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> Ptr (Ptr CLong) -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_squarefree/ /res/ /f/ /ctx/ +--+-- Sets @res@ to a squarefree factorization of @f@.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_squarefree"+ fq_nmod_poly_factor_squarefree :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor/ /res/ /lead/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- choosing the best algorithm for given modulo and degree. The output+-- @lead@ is set to the leading coefficient of \(f\) upon return. Choice of+-- algorithm is based on heuristic measurements.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor"+ fq_nmod_poly_factor :: Ptr CFqNModPolyFactor -> Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_cantor_zassenhaus/ /res/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the Cantor-Zassenhaus algorithm.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_cantor_zassenhaus"+ fq_nmod_poly_factor_cantor_zassenhaus :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_kaltofen_shoup/ /res/ /poly/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the fast version of Cantor-Zassenhaus algorithm proposed by+-- Kaltofen and Shoup (1998). More precisely this algorithm uses a “baby+-- step\/giant step” strategy for the distinct-degree factorization step.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_kaltofen_shoup"+ fq_nmod_poly_factor_kaltofen_shoup :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_berlekamp/ /factors/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the Berlekamp algorithm.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_berlekamp"+ fq_nmod_poly_factor_berlekamp :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_with_berlekamp/ /res/ /leading_coeff/ /f/ /ctx/ +--+-- Factorises a general polynomial @f@ into monic irreducible factors and+-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is+-- the zero polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Berlekamp on all the+-- individual square-free factors.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_with_berlekamp"+ fq_nmod_poly_factor_with_berlekamp :: Ptr CFqNModPolyFactor -> Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_with_cantor_zassenhaus/ /res/ /leading_coeff/ /f/ /ctx/ +--+-- Factorises a general polynomial @f@ into monic irreducible factors and+-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is+-- the zero polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Cantor-Zassenhaus on all the+-- individual square-free factors.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_with_cantor_zassenhaus"+ fq_nmod_poly_factor_with_cantor_zassenhaus :: Ptr CFqNModPolyFactor -> Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_factor_with_kaltofen_shoup/ /res/ /leading_coeff/ /f/ /ctx/ +--+-- Factorises a general polynomial @f@ into monic irreducible factors and+-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is+-- the zero polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Kaltofen-Shoup on all the+-- individual square-free factors.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_factor_with_kaltofen_shoup"+ fq_nmod_poly_factor_with_kaltofen_shoup :: Ptr CFqNModPolyFactor -> Ptr CFqNMod -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- | /fq_nmod_poly_iterated_frobenius_preinv/ /rop/ /n/ /v/ /vinv/ /ctx/ +--+-- Sets @rop[i]@ to be \(x^{q^i} \bmod v\) for \(0 \le i < n\).+-- +-- It is required that @vinv@ is the inverse of the reverse of @v@ mod+-- @x^lenv@.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_iterated_frobenius_preinv"+ fq_nmod_poly_iterated_frobenius_preinv :: Ptr (Ptr CFqNModPoly) -> CLong -> Ptr CFqNModPoly -> Ptr CFqNModPoly -> Ptr CFqNModCtx -> IO ()++-- Root Finding ----------------------------------------------------------------++-- | /fq_nmod_poly_roots/ /r/ /f/ /with_multiplicity/ /ctx/ +--+-- Fill \(r\) with factors of the form \(x - r_i\) where the \(r_i\) are+-- the distinct roots of a nonzero \(f\) in \(F_q\). If+-- \(with\_multiplicity\) is zero, the exponent \(e_i\) of the factor+-- \(x - r_i\) is \(1\). Otherwise, it is the largest \(e_i\) such that+-- \((x-r_i)^e_i\) divides \(f\). This function throws if \(f\) is zero,+-- but is otherwise always successful.+foreign import ccall "fq_nmod_poly_factor.h fq_nmod_poly_roots"+ fq_nmod_poly_roots :: Ptr CFqNModPolyFactor -> Ptr CFqNModPoly -> CInt -> Ptr CFqNModCtx -> IO ()+
+ src/Data/Number/Flint/Fq/NMod/Types.hs view
@@ -0,0 +1,6 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Fq.NMod.Types (+ module Data.Number.Flint.Fq.NMod.Types.FFI+) where++import Data.Number.Flint.Fq.NMod.Types.FFI
+ src/Data/Number/Flint/Fq/NMod/Types/FFI.hsc view
@@ -0,0 +1,48 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+{-|+module : Data.Number.Flint.Fq.NMod.Types.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.NMod.Types.FFI where++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.C.String++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.NMod+import Data.Number.Flint.NMod.Types++-- fq_nmod_t -------------------------------------------------------------------++data FqNMod = FqNMod {-# UNPACK #-} !(ForeignPtr CFqNMod)+type CFqNMod = CFlint FqNMod++-- fq_nmod_ctx_t ---------------------------------------------------------------++data FqNModCtx = FqNModCtx {-# UNPACK #-} !(ForeignPtr CFqNModCtx)+data CFqNModCtx = CFqNModCtx (Ptr CFmpz) (Ptr CNMod) CInt CInt (Ptr CMpLimb) (Ptr CLong) (Ptr CLong) (Ptr CNModPoly) (Ptr CNModPoly) CString ++-- fq_nmod_poly_t --------------------------------------------------------------++data FqNModPoly = FqNModPoly {-# UNPACK #-} !(ForeignPtr CFqNModPoly)+type CFqNModPoly = CFlint FqNModPoly++-- fq_nmod_poly_factor_t -------------------------------------------------------++data FqNModPolyFactor = FqNModPolyFactor {-# UNPACK #-} !(ForeignPtr CFqNModPolyFactor)+data CFqNModPolyFactor = CFqNModPolyFactor (Ptr CFqNModPoly) (Ptr CLong) CLong CLong++-- fq_nmod_mpoly_t -------------------------------------------------------------++data FqNModMPoly = FqNModMPoly {-# UNPACK #-} !(ForeignPtr CFqNModMPoly)+type CFqNModMPoly = CFlint FqNModMPoly++-- fq_nmod_mat_t ---------------------------------------------------------------++data FqNModMat = FqNModMat {-# UNPACK #-} !(ForeignPtr CFqNModMat)+data CFqNModMat = CFqNModMat (Ptr CFqNMod) CLong CLong (Ptr (Ptr CFqNMod))
+ src/Data/Number/Flint/Fq/NMod/Vec.hs view
@@ -0,0 +1,12 @@+{- | +module : Data.Number.Flint.Fq.Nmod.Vec+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Fq.NMod.Vec (+ module Data.Number.Flint.Fq.NMod.Vec.FFI,+) where++import Data.Number.Flint.Fq.NMod.Vec.FFI
+ src/Data/Number/Flint/Fq/NMod/Vec/FFI.hsc view
@@ -0,0 +1,180 @@+{-|+module : Data.Number.Flint.Fq.NMod.Vec.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.NMod.Vec.FFI (+ -- * Vectors over finite fields (word-size characteristic)+ -- * Memory management+ _fq_nmod_vec_init+ , _fq_nmod_vec_clear+ -- * Randomisation+ , _fq_nmod_vec_randtest+ -- * Input and output+ , _fq_nmod_vec_fprint+ , _fq_nmod_vec_print+ -- * Assignment and basic manipulation+ , _fq_nmod_vec_set+ , _fq_nmod_vec_swap+ , _fq_nmod_vec_zero+ , _fq_nmod_vec_neg+ -- * Comparison+ , _fq_nmod_vec_equal+ , _fq_nmod_vec_is_zero+ -- * Addition and subtraction+ , _fq_nmod_vec_add+ , _fq_nmod_vec_sub+ -- * Scalar multiplication and division+ , _fq_nmod_vec_scalar_addmul_fq_nmod+ , _fq_nmod_vec_scalar_submul_fq_nmod+ -- * Dot products+ , _fq_nmod_vec_dot+) where++-- Vectors over finite fields (word-size characteristic) -----------------------++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr )+import Foreign.Storable++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.NMod.Mat+import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Mat+import Data.Number.Flint.Fq.NMod++#include <flint/flint.h>+#include <flint/fq_nmod.h>+#include <flint/fq_nmod_vec.h>++-- Memory management -----------------------------------------------------------++-- | /_fq_nmod_vec_init/ /len/ /ctx/ +--+-- Returns an initialised vector of @fq_nmod@\'s of given length.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_init"+ _fq_nmod_vec_init :: CLong -> Ptr CFqNModCtx -> IO (Ptr CFqNMod)++-- | /_fq_nmod_vec_clear/ /vec/ /len/ /ctx/ +--+-- Clears the entries of @(vec, len)@ and frees the space allocated for+-- @vec@.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_clear"+ _fq_nmod_vec_clear :: Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO ()++-- Randomisation ---------------------------------------------------------------++-- | /_fq_nmod_vec_randtest/ /f/ /state/ /len/ /ctx/ +--+-- Sets the entries of a vector of the given length to elements of the+-- finite field.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_randtest"+ _fq_nmod_vec_randtest ::Ptr CFqNMod -> Ptr CFRandState -> CLong -> Ptr CFqNModCtx -> IO ()++-- Input and output ------------------------------------------------------------++-- | /_fq_nmod_vec_fprint/ /file/ /vec/ /len/ /ctx/ +--+-- Prints the vector of given length to the stream @file@. The format is+-- the length followed by two spaces, then a space separated list of+-- coefficients. If the length is zero, only \(0\) is printed.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_fprint"+ _fq_nmod_vec_fprint :: Ptr CFile -> Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO CInt++-- | /_fq_nmod_vec_print/ /vec/ /len/ /ctx/ +--+-- Prints the vector of given length to @stdout@.+-- +-- For further details, see @_fq_nmod_vec_fprint()@.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_print"+ _fq_nmod_vec_print ::Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO CInt++-- Assignment and basic manipulation -------------------------------------------++-- | /_fq_nmod_vec_set/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Makes a copy of @(vec2, len2)@ into @vec1@.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_set"+ _fq_nmod_vec_set ::Ptr CFqNMod -> Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_vec_swap/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Swaps the elements in @(vec1, len2)@ and @(vec2, len2)@.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_swap"+ _fq_nmod_vec_swap ::Ptr CFqNMod -> Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_vec_zero/ /vec/ /len/ /ctx/ +--+-- Zeros the entries of @(vec, len)@.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_zero"+ _fq_nmod_vec_zero ::Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_vec_neg/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Negates @(vec2, len2)@ and places it into @vec1@.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_neg"+ _fq_nmod_vec_neg ::Ptr CFqNMod -> Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /_fq_nmod_vec_equal/ /vec1/ /vec2/ /len/ /ctx/ +--+-- Compares two vectors of the given length and returns \(1\) if they are+-- equal, otherwise returns \(0\).+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_equal"+ _fq_nmod_vec_equal ::Ptr CFqNMod -> Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO CInt++-- | /_fq_nmod_vec_is_zero/ /vec/ /len/ /ctx/ +--+-- Returns \(1\) if @(vec, len)@ is zero, and \(0\) otherwise.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_is_zero"+ _fq_nmod_vec_is_zero ::Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /_fq_nmod_vec_add/ /res/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Sets @(res, len2)@ to the sum of @(vec1, len2)@ and @(vec2, len2)@.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_add"+ _fq_nmod_vec_add ::Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_vec_sub/ /res/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Sets @(res, len2)@ to @(vec1, len2)@ minus @(vec2, len2)@.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_sub"+ _fq_nmod_vec_sub ::Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO ()++-- Scalar multiplication and division ------------------------------------------++-- | /_fq_nmod_vec_scalar_addmul_fq_nmod/ /vec1/ /vec2/ /len2/ /c/ /ctx/ +--+-- Adds @(vec2, len2)@ times \(c\) to @(vec1, len2)@, where \(c\) is a+-- @fq_nmod_t@.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_scalar_addmul_fq_nmod"+ _fq_nmod_vec_scalar_addmul_fq_nmod ::Ptr CFqNMod -> Ptr CFqNMod -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- | /_fq_nmod_vec_scalar_submul_fq_nmod/ /vec1/ /vec2/ /len2/ /c/ /ctx/ +--+-- Subtracts @(vec2, len2)@ times \(c\) from @(vec1, len2)@, where \(c\) is+-- a @fq_nmod_t@.+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_scalar_submul_fq_nmod"+ _fq_nmod_vec_scalar_submul_fq_nmod ::Ptr CFqNMod -> Ptr CFqNMod -> CLong -> Ptr CFqNMod -> Ptr CFqNModCtx -> IO ()++-- Dot products ----------------------------------------------------------------++-- | /_fq_nmod_vec_dot/ /res/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Sets @res@ to the dot product of (@vec1@, @len@) and (@vec2@, @len@).+foreign import ccall "fq_nmod_vec.h _fq_nmod_vec_dot"+ _fq_nmod_vec_dot :: Ptr CFqNMod -> Ptr CFqNMod -> Ptr CFqNMod -> CLong -> Ptr CFqNModCtx -> IO ()+
+ src/Data/Number/Flint/Fq/Poly.hs view
@@ -0,0 +1,16 @@+{- | +module : Data.Number.Flint.Fq.Poly+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de++An @FqPoly@ represents a polynomial over a finite field.+This module implements operations on polynomials over a finite field.++-}++module Data.Number.Flint.Fq.Poly (+ module Data.Number.Flint.Fq.Poly.FFI,+) where++import Data.Number.Flint.Fq.Poly.FFI
+ src/Data/Number/Flint/Fq/Poly/FFI.hsc view
@@ -0,0 +1,1992 @@+{-|+module : Data.Number.Flint.Fq.Poly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Poly.FFI (+ -- * Univariate polynomials over finite fields+ -- * Types+ FqPoly (..)+ , CFqPoly (..)+ , newFqPoly+ , withFqPoly+ , withNewFqPoly+ -- * Memory management+ , fq_poly_init+ , fq_poly_init2+ , fq_poly_realloc+ , fq_poly_fit_length+ , _fq_poly_set_length+ , fq_poly_clear+ , _fq_poly_normalise+ , _fq_poly_normalise2+ , fq_poly_truncate+ , fq_poly_set_trunc+ , _fq_poly_reverse+ , fq_poly_reverse+ -- * Polynomial parameters+ , fq_poly_degree+ , fq_poly_length+ , fq_poly_lead+ -- * Randomisation+ , fq_poly_randtest+ , fq_poly_randtest_not_zero+ , fq_poly_randtest_monic+ , fq_poly_randtest_irreducible+ -- * Assignment and basic manipulation+ , _fq_poly_set+ , fq_poly_set+ , fq_poly_set_fq+ , fq_poly_set_fmpz_mod_poly+ , fq_poly_set_nmod_poly+ , fq_poly_swap+ , _fq_poly_zero+ , fq_poly_zero+ , fq_poly_one+ , fq_poly_gen+ , fq_poly_make_monic+ , _fq_poly_make_monic+ -- * Getting and setting coefficients+ , fq_poly_get_coeff+ , fq_poly_set_coeff+ , fq_poly_set_coeff_fmpz+ -- * Comparison+ , fq_poly_equal+ , fq_poly_equal_trunc+ , fq_poly_is_zero+ , fq_poly_is_one+ , fq_poly_is_gen+ , fq_poly_is_unit+ , fq_poly_equal_fq+ -- * Addition and subtraction+ , _fq_poly_add+ , fq_poly_add+ , fq_poly_add_si+ , fq_poly_add_series+ , _fq_poly_sub+ , fq_poly_sub+ , fq_poly_sub_series+ , _fq_poly_neg+ , fq_poly_neg+ -- * Scalar multiplication and division+ , _fq_poly_scalar_mul_fq+ , fq_poly_scalar_mul_fq+ , _fq_poly_scalar_addmul_fq+ , fq_poly_scalar_addmul_fq+ , _fq_poly_scalar_submul_fq+ , fq_poly_scalar_submul_fq+ , _fq_poly_scalar_div_fq+ , fq_poly_scalar_div_fq+ -- * Multiplication+ , _fq_poly_mul_classical+ , fq_poly_mul_classical+ , _fq_poly_mul_reorder+ , fq_poly_mul_reorder+ , _fq_poly_mul_univariate+ , fq_poly_mul_univariate+ , _fq_poly_mul_KS+ , fq_poly_mul_KS+ , _fq_poly_mul+ , fq_poly_mul+ , _fq_poly_mullow_classical+ , fq_poly_mullow_classical+ , _fq_poly_mullow_univariate+ , fq_poly_mullow_univariate+ , _fq_poly_mullow_KS+ , fq_poly_mullow_KS+ , _fq_poly_mullow+ , fq_poly_mullow+ , _fq_poly_mulhigh_classical+ , fq_poly_mulhigh_classical+ , _fq_poly_mulhigh+ , fq_poly_mulhigh+ , _fq_poly_mulmod+ , fq_poly_mulmod+ , _fq_poly_mulmod_preinv+ , fq_poly_mulmod_preinv+ -- * Squaring+ , _fq_poly_sqr_classical+ , fq_poly_sqr_classical+ , _fq_poly_sqr_reorder+ , fq_poly_sqr_reorder+ , _fq_poly_sqr_KS+ , fq_poly_sqr_KS+ , _fq_poly_sqr+ , fq_poly_sqr+ -- * Powering+ , _fq_poly_pow+ , fq_poly_pow+ , _fq_poly_powmod_ui_binexp+ , fq_poly_powmod_ui_binexp+ , _fq_poly_powmod_ui_binexp_preinv+ , fq_poly_powmod_ui_binexp_preinv+ , _fq_poly_powmod_fmpz_binexp+ , fq_poly_powmod_fmpz_binexp+ , _fq_poly_powmod_fmpz_binexp_preinv+ , fq_poly_powmod_fmpz_binexp_preinv+ , _fq_poly_powmod_fmpz_sliding_preinv+ , fq_poly_powmod_fmpz_sliding_preinv+ , _fq_poly_powmod_x_fmpz_preinv+ , fq_poly_powmod_x_fmpz_preinv+ , _fq_poly_pow_trunc_binexp+ , fq_poly_pow_trunc_binexp+ , _fq_poly_pow_trunc+ , fq_poly_pow_trunc+ -- * Shifting+ , _fq_poly_shift_left+ , fq_poly_shift_left+ , _fq_poly_shift_right+ , fq_poly_shift_right+ -- * Norms+ , fq_poly_hamming_weight+ -- * Euclidean division+ , _fq_poly_divrem+ , fq_poly_divrem+ , fq_poly_divrem_f+ , _fq_poly_rem+ , fq_poly_rem+ , _fq_poly_div+ , fq_poly_div+ , _fq_poly_div_newton_n_preinv+ , fq_poly_div_newton_n_preinv+ , _fq_poly_divrem_newton_n_preinv+ --, fq_poly_divrem_newton_preinv+ , _fq_poly_inv_series_newton+ , fq_poly_inv_series_newton+ , _fq_poly_inv_series+ , fq_poly_inv_series+ , _fq_poly_div_series+ , fq_poly_div_series+ -- * Greatest common divisor+ , fq_poly_gcd+ , _fq_poly_gcd+ , _fq_poly_gcd_euclidean_f+ , fq_poly_gcd_euclidean_f+ , _fq_poly_xgcd+ , fq_poly_xgcd+ , _fq_poly_xgcd_euclidean_f+ , fq_poly_xgcd_euclidean_f+ -- * Divisibility testing+ , _fq_poly_divides+ , fq_poly_divides+ -- * Derivative+ , _fq_poly_derivative+ , fq_poly_derivative+ -- * Square root+ , _fq_poly_invsqrt_series+ , fq_poly_invsqrt_series+ , _fq_poly_sqrt_series+ , fq_poly_sqrt_series+ , _fq_poly_sqrt+ , fq_poly_sqrt+ -- * Evaluation+ , _fq_poly_evaluate_fq+ , fq_poly_evaluate_fq+ -- * Composition+ , _fq_poly_compose+ , fq_poly_compose+ , _fq_poly_compose_mod_horner+ , fq_poly_compose_mod_horner+ , _fq_poly_compose_mod_horner_preinv+ , fq_poly_compose_mod_horner_preinv+ , _fq_poly_compose_mod_brent_kung+ , fq_poly_compose_mod_brent_kung+ , _fq_poly_compose_mod_brent_kung_preinv+ , fq_poly_compose_mod_brent_kung_preinv+ , _fq_poly_compose_mod+ , fq_poly_compose_mod+ , _fq_poly_compose_mod_preinv+ , fq_poly_compose_mod_preinv+ , _fq_poly_reduce_matrix_mod_poly+ , _fq_poly_precompute_matrix+ , fq_poly_precompute_matrix+ , _fq_poly_compose_mod_brent_kung_precomp_preinv+ , fq_poly_compose_mod_brent_kung_precomp_preinv+ -- * Output+ , _fq_poly_fprint_pretty+ , fq_poly_fprint_pretty+ , _fq_poly_print_pretty+ , fq_poly_print_pretty+ , _fq_poly_fprint+ , fq_poly_fprint+ , _fq_poly_print+ , fq_poly_print+ , _fq_poly_get_str+ , fq_poly_get_str+ , _fq_poly_get_str_pretty+ , fq_poly_get_str_pretty+ -- * Inflation and deflation+ , fq_poly_inflate+ , fq_poly_deflate+ , fq_poly_deflation+) where++-- Univariate polynomials over finite fields -----------------------------------++import System.IO.Unsafe+import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Mod.Poly++import Data.Number.Flint.Fmpq++import Data.Number.Flint.NMod.Types++import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.Mat++#include <flint/flint.h>+#include <flint/fq_poly.h>++-- fq_poly_t -------------------------------------------------------------------++data FqPoly = FqPoly {-# UNPACK #-} !(ForeignPtr CFqPoly)+data CFqPoly = CFqPoly (Ptr CFq) CLong CLong++-- data CFqPoly = CFqPoly {+-- -- | pointer to the coefficients of the polynomial+-- coeffs :: Ptr CFq,+-- -- | number of allocated coefficients+-- alloc :: CLong,+-- -- | number of coefficients+-- num :: CLong+-- }++instance Storable CFqPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_poly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_poly_t}+ peek ptr = CFqPoly+ <$> #{peek fq_poly_struct, coeffs} ptr+ <*> #{peek fq_poly_struct, alloc } ptr+ <*> #{peek fq_poly_struct, length} ptr+ poke = undefined+ +-- | Create a new `FqPoly` structure with context `ctx`.+newFqPoly ctx@(FqCtx fctx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqCtx ctx $ \ctx -> do+ fq_poly_init x ctx+ addForeignPtrFinalizerEnv p_fq_poly_clear x fctx+ return $ FqPoly x++-- | Use `FqPoly` structure.+{-# INLINE withFqPoly #-}+withFqPoly (FqPoly x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqPoly x,)++-- | Use new `FqPoly` structure.+{-# INLINE withNewFqPoly #-}+withNewFqPoly ctx f = do+ x <- newFqPoly ctx+ withFqPoly x $ \x -> f x++-- Memory management -----------------------------------------------------------++-- | /fq_poly_init/ /poly/ /ctx/ +--+-- Initialises @poly@ for use, with context ctx, and setting its length to+-- zero. A corresponding call to @fq_poly_clear@ must be made after+-- finishing with the @fq_poly_t@ to free the memory used by the+-- polynomial.+foreign import ccall "fq_poly.h fq_poly_init"+ fq_poly_init :: Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_init2/ /poly/ /alloc/ /ctx/ +--+-- Initialises @poly@ with space for at least @alloc@ coefficients and sets+-- the length to zero. The allocated coefficients are all set to zero. A+-- corresponding call to @fq_poly_clear@ must be made after finishing with+-- the @fq_poly_t@ to free the memory used by the polynomial.+foreign import ccall "fq_poly.h fq_poly_init2"+ fq_poly_init2 :: Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_realloc/ /poly/ /alloc/ /ctx/ +--+-- Reallocates the given polynomial to have space for @alloc@ coefficients.+-- If @alloc@ is zero the polynomial is cleared and then reinitialised. If+-- the current length is greater than @alloc@ the polynomial is first+-- truncated to length @alloc@.+foreign import ccall "fq_poly.h fq_poly_realloc"+ fq_poly_realloc :: Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_fit_length/ /poly/ /len/ /ctx/ +--+-- If @len@ is greater than the number of coefficients currently allocated,+-- then the polynomial is reallocated to have space for at least @len@+-- coefficients. No data is lost when calling this function.+-- +-- The function efficiently deals with the case where @fit_length@ is+-- called many times in small increments by at least doubling the number of+-- allocated coefficients when length is larger than the number of+-- coefficients currently allocated.+foreign import ccall "fq_poly.h fq_poly_fit_length"+ fq_poly_fit_length :: Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_set_length/ /poly/ /newlen/ /ctx/ +--+-- Sets the coefficients of @poly@ beyond @len@ to zero and sets the length+-- of @poly@ to @len@.+foreign import ccall "fq_poly.h _fq_poly_set_length"+ _fq_poly_set_length :: Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_clear/ /poly/ /ctx/ +--+-- Clears the given polynomial, releasing any memory used. It must be+-- reinitialised in order to be used again.+foreign import ccall "fq_poly.h fq_poly_clear"+ fq_poly_clear :: Ptr CFqPoly -> Ptr CFqCtx -> IO ()++foreign import ccall "fq_poly.h &fq_poly_clear"+ p_fq_poly_clear :: FunPtr (Ptr CFqPoly -> Ptr CFqCtx -> IO ())++-- | /_fq_poly_normalise/ /poly/ /ctx/ +--+-- Sets the length of @poly@ so that the top coefficient is non-zero. If+-- all coefficients are zero, the length is set to zero. This function is+-- mainly used internally, as all functions guarantee normalisation.+foreign import ccall "fq_poly.h _fq_poly_normalise"+ _fq_poly_normalise :: Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_normalise2/ /poly/ /length/ /ctx/ +--+-- Sets the length @length@ of @(poly,length)@ so that the top coefficient+-- is non-zero. If all coefficients are zero, the length is set to zero.+-- This function is mainly used internally, as all functions guarantee+-- normalisation.+foreign import ccall "fq_poly.h _fq_poly_normalise2"+ _fq_poly_normalise2 :: Ptr (Ptr CFq) -> Ptr CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_truncate/ /poly/ /newlen/ /ctx/ +--+-- Truncates the polynomial to length at most \(n\).+foreign import ccall "fq_poly.h fq_poly_truncate"+ fq_poly_truncate :: Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_set_trunc/ /poly1/ /poly2/ /newlen/ /ctx/ +--+-- Sets @poly1@ to @poly2@ truncated to length \(n\).+foreign import ccall "fq_poly.h fq_poly_set_trunc"+ fq_poly_set_trunc :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_reverse/ /output/ /input/ /len/ /m/ /ctx/ +--+-- Sets @output@ to the reverse of @input@, which is of length @len@, but+-- thinking of it as a polynomial of length @m@, notionally zero-padded if+-- necessary. The length @m@ must be non-negative, but there are no other+-- restrictions. The polynomial @output@ must have space for @m@+-- coefficients.+foreign import ccall "fq_poly.h _fq_poly_reverse"+ _fq_poly_reverse :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_reverse/ /output/ /input/ /m/ /ctx/ +--+-- Sets @output@ to the reverse of @input@, thinking of it as a polynomial+-- of length @m@, notionally zero-padded if necessary). The length @m@ must+-- be non-negative, but there are no other restrictions. The output+-- polynomial will be set to length @m@ and then normalised.+foreign import ccall "fq_poly.h fq_poly_reverse"+ fq_poly_reverse :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- Polynomial parameters -------------------------------------------------------++-- | /fq_poly_degree/ /poly/ /ctx/ +--+-- Returns the degree of the polynomial @poly@.+foreign import ccall "fq_poly.h fq_poly_degree"+ fq_poly_degree :: Ptr CFqPoly -> Ptr CFqCtx -> IO CLong++-- | /fq_poly_length/ /poly/ /ctx/ +--+-- Returns the length of the polynomial @poly@.+foreign import ccall "fq_poly.h fq_poly_length"+ fq_poly_length :: Ptr CFqPoly -> Ptr CFqCtx -> IO CLong++-- | /fq_poly_lead/ /poly/ /ctx/ +--+-- Returns a pointer to the leading coefficient of @poly@, or @NULL@ if+-- @poly@ is the zero polynomial.+foreign import ccall "fq_poly.h fq_poly_lead"+ fq_poly_lead :: Ptr CFqPoly -> Ptr CFqCtx -> IO (Ptr (Ptr CFq))++-- Randomisation ---------------------------------------------------------------++-- | /fq_poly_randtest/ /f/ /state/ /len/ /ctx/ +--+-- Sets \(f\) to a random polynomial of length at most @len@ with entries+-- in the field described by @ctx@.+foreign import ccall "fq_poly.h fq_poly_randtest"+ fq_poly_randtest :: Ptr CFqPoly -> Ptr CFRandState -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_randtest_not_zero/ /f/ /state/ /len/ /ctx/ +--+-- Same as @fq_poly_randtest@ but guarantees that the polynomial is not+-- zero.+foreign import ccall "fq_poly.h fq_poly_randtest_not_zero"+ fq_poly_randtest_not_zero :: Ptr CFqPoly -> Ptr CFRandState -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_randtest_monic/ /f/ /state/ /len/ /ctx/ +--+-- Sets \(f\) to a random monic polynomial of length @len@ with entries in+-- the field described by @ctx@.+foreign import ccall "fq_poly.h fq_poly_randtest_monic"+ fq_poly_randtest_monic :: Ptr CFqPoly -> Ptr CFRandState -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_randtest_irreducible/ /f/ /state/ /len/ /ctx/ +--+-- Sets \(f\) to a random monic, irreducible polynomial of length @len@+-- with entries in the field described by @ctx@.+foreign import ccall "fq_poly.h fq_poly_randtest_irreducible"+ fq_poly_randtest_irreducible :: Ptr CFqPoly -> Ptr CFRandState -> CLong -> Ptr CFqCtx -> IO ()++-- Assignment and basic manipulation -------------------------------------------++-- | /_fq_poly_set/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, len@) to @(op, len)@.+foreign import ccall "fq_poly.h _fq_poly_set"+ _fq_poly_set :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_set/ /poly1/ /poly2/ /ctx/ +--+-- Sets the polynomial @poly1@ to the polynomial @poly2@.+foreign import ccall "fq_poly.h fq_poly_set"+ fq_poly_set :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_set_fq/ /poly/ /c/ /ctx/ +--+-- Sets the polynomial @poly@ to @c@.+foreign import ccall "fq_poly.h fq_poly_set_fq"+ fq_poly_set_fq :: Ptr CFqPoly -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_poly_set_fmpz_mod_poly/ /rop/ /op/ /ctx/ +--+-- Sets the polynomial @rop@ to the polynomial @op@+foreign import ccall "fq_poly.h fq_poly_set_fmpz_mod_poly"+ fq_poly_set_fmpz_mod_poly :: Ptr CFqPoly -> Ptr CFmpzModPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_set_nmod_poly/ /rop/ /op/ /ctx/ +--+-- Sets the polynomial @rop@ to the polynomial @op@+foreign import ccall "fq_poly.h fq_poly_set_nmod_poly"+ fq_poly_set_nmod_poly :: Ptr CFqPoly -> Ptr CNModPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_swap/ /op1/ /op2/ /ctx/ +--+-- Swaps the two polynomials @op1@ and @op2@.+foreign import ccall "fq_poly.h fq_poly_swap"+ fq_poly_swap :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_zero/ /rop/ /len/ /ctx/ +--+-- Sets @(rop, len)@ to the zero polynomial.+foreign import ccall "fq_poly.h _fq_poly_zero"+ _fq_poly_zero :: Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_zero/ /poly/ /ctx/ +--+-- Sets @poly@ to the zero polynomial.+foreign import ccall "fq_poly.h fq_poly_zero"+ fq_poly_zero :: Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_one/ /poly/ /ctx/ +--+-- Sets @poly@ to the constant polynomial \(1\).+foreign import ccall "fq_poly.h fq_poly_one"+ fq_poly_one :: Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_gen/ /poly/ /ctx/ +--+-- Sets @poly@ to the polynomial \(x\).+foreign import ccall "fq_poly.h fq_poly_gen"+ fq_poly_gen :: Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_make_monic/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to @op@, normed to have leading coefficient 1.+foreign import ccall "fq_poly.h fq_poly_make_monic"+ fq_poly_make_monic :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_make_monic/ /rop/ /op/ /length/ /ctx/ +--+-- Sets @rop@ to @(op,length)@, normed to have leading coefficient 1.+-- Assumes that @rop@ has enough space for the polynomial, assumes that+-- @op@ is not zero (and thus has an invertible leading coefficient).+foreign import ccall "fq_poly.h _fq_poly_make_monic"+ _fq_poly_make_monic :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- Getting and setting coefficients --------------------------------------------++-- | /fq_poly_get_coeff/ /x/ /poly/ /n/ /ctx/ +--+-- Sets \(x\) to the coefficient of \(X^n\) in @poly@.+foreign import ccall "fq_poly.h fq_poly_get_coeff"+ fq_poly_get_coeff :: Ptr CFq -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_set_coeff/ /poly/ /n/ /x/ /ctx/ +--+-- Sets the coefficient of \(X^n\) in @poly@ to \(x\).+foreign import ccall "fq_poly.h fq_poly_set_coeff"+ fq_poly_set_coeff :: Ptr CFqPoly -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_poly_set_coeff_fmpz/ /poly/ /n/ /x/ /ctx/ +--+-- Sets the coefficient of \(X^n\) in the polynomial to \(x\), assuming+-- \(n \geq 0\).+foreign import ccall "fq_poly.h fq_poly_set_coeff_fmpz"+ fq_poly_set_coeff_fmpz :: Ptr CFqPoly -> CLong -> Ptr CFmpz -> Ptr CFqCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fq_poly_equal/ /poly1/ /poly2/ /ctx/ +--+-- Returns nonzero if the two polynomials @poly1@ and @poly2@ are equal,+-- otherwise returns zero.+foreign import ccall "fq_poly.h fq_poly_equal"+ fq_poly_equal :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_equal_trunc/ /poly1/ /poly2/ /n/ /ctx/ +--+-- Notionally truncate @poly1@ and @poly2@ to length \(n\) and return+-- nonzero if they are equal, otherwise return zero.+foreign import ccall "fq_poly.h fq_poly_equal_trunc"+ fq_poly_equal_trunc :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_is_zero/ /poly/ /ctx/ +--+-- Returns whether the polynomial @poly@ is the zero polynomial.+foreign import ccall "fq_poly.h fq_poly_is_zero"+ fq_poly_is_zero :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_is_one/ /op/ +--+-- Returns whether the polynomial @poly@ is equal to the constant+-- polynomial \(1\).+foreign import ccall "fq_poly.h fq_poly_is_one"+ fq_poly_is_one :: Ptr CFqPoly -> IO CInt++-- | /fq_poly_is_gen/ /op/ /ctx/ +--+-- Returns whether the polynomial @poly@ is equal to the polynomial \(x\).+foreign import ccall "fq_poly.h fq_poly_is_gen"+ fq_poly_is_gen :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_is_unit/ /op/ /ctx/ +--+-- Returns whether the polynomial @poly@ is a unit in the polynomial ring+-- \(\mathbf{F}_q[X]\), i.e. if it has degree \(0\) and is non-zero.+foreign import ccall "fq_poly.h fq_poly_is_unit"+ fq_poly_is_unit :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_equal_fq/ /poly/ /c/ /ctx/ +--+-- Returns whether the polynomial @poly@ is equal the (constant)+-- \(\mathbf{F}_q\) element @c@+foreign import ccall "fq_poly.h fq_poly_equal_fq"+ fq_poly_equal_fq :: Ptr CFqPoly -> Ptr CFq -> Ptr CFqCtx -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /_fq_poly_add/ /res/ /poly1/ /len1/ /poly2/ /len2/ /ctx/ +--+-- Sets @res@ to the sum of @(poly1,len1)@ and @(poly2,len2)@.+foreign import ccall "fq_poly.h _fq_poly_add"+ _fq_poly_add :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_add/ /res/ /poly1/ /poly2/ /ctx/ +--+-- Sets @res@ to the sum of @poly1@ and @poly2@.+foreign import ccall "fq_poly.h fq_poly_add"+ fq_poly_add :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_add_si/ /res/ /poly1/ /c/ /ctx/ +--+-- Sets @res@ to the sum of @poly1@ and @c@.+foreign import ccall "fq_poly.h fq_poly_add_si"+ fq_poly_add_si :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_add_series/ /res/ /poly1/ /poly2/ /n/ /ctx/ +--+-- Notionally truncate @poly1@ and @poly2@ to length @n@ and set @res@ to+-- the sum.+foreign import ccall "fq_poly.h fq_poly_add_series"+ fq_poly_add_series :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_sub/ /res/ /poly1/ /len1/ /poly2/ /len2/ /ctx/ +--+-- Sets @res@ to the difference of @(poly1,len1)@ and @(poly2,len2)@.+foreign import ccall "fq_poly.h _fq_poly_sub"+ _fq_poly_sub :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_sub/ /res/ /poly1/ /poly2/ /ctx/ +--+-- Sets @res@ to the difference of @poly1@ and @poly2@.+foreign import ccall "fq_poly.h fq_poly_sub"+ fq_poly_sub :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_sub_series/ /res/ /poly1/ /poly2/ /n/ /ctx/ +--+-- Notionally truncate @poly1@ and @poly2@ to length @n@ and set @res@ to+-- the difference.+foreign import ccall "fq_poly.h fq_poly_sub_series"+ fq_poly_sub_series :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_neg/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @rop@ to the additive inverse of @(poly,len)@.+foreign import ccall "fq_poly.h _fq_poly_neg"+ _fq_poly_neg :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_neg/ /res/ /poly/ /ctx/ +--+-- Sets @res@ to the additive inverse of @poly@.+foreign import ccall "fq_poly.h fq_poly_neg"+ fq_poly_neg :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- Scalar multiplication and division ------------------------------------------++-- | /_fq_poly_scalar_mul_fq/ /rop/ /op/ /len/ /x/ /ctx/ +--+-- Sets @(rop,len)@ to the product of @(op,len)@ by the scalar @x@, in the+-- context defined by @ctx@.+foreign import ccall "fq_poly.h _fq_poly_scalar_mul_fq"+ _fq_poly_scalar_mul_fq :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_poly_scalar_mul_fq/ /rop/ /op/ /x/ /ctx/ +--+-- Sets @rop@ to the product of @op@ by the scalar @x@, in the context+-- defined by @ctx@.+foreign import ccall "fq_poly.h fq_poly_scalar_mul_fq"+ fq_poly_scalar_mul_fq :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_scalar_addmul_fq/ /rop/ /op/ /len/ /x/ /ctx/ +--+-- Adds to @(rop,len)@ the product of @(op,len)@ by the scalar @x@, in the+-- context defined by @ctx@. In particular, assumes the same length for+-- @op@ and @rop@.+foreign import ccall "fq_poly.h _fq_poly_scalar_addmul_fq"+ _fq_poly_scalar_addmul_fq :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_poly_scalar_addmul_fq/ /rop/ /op/ /x/ /ctx/ +--+-- Adds to @rop@ the product of @op@ by the scalar @x@, in the context+-- defined by @ctx@.+foreign import ccall "fq_poly.h fq_poly_scalar_addmul_fq"+ fq_poly_scalar_addmul_fq :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_scalar_submul_fq/ /rop/ /op/ /len/ /x/ /ctx/ +--+-- Subtracts from @(rop,len)@ the product of @(op,len)@ by the scalar @x@,+-- in the context defined by @ctx@. In particular, assumes the same length+-- for @op@ and @rop@.+foreign import ccall "fq_poly.h _fq_poly_scalar_submul_fq"+ _fq_poly_scalar_submul_fq :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_poly_scalar_submul_fq/ /rop/ /op/ /x/ /ctx/ +--+-- Subtracts from @rop@ the product of @op@ by the scalar @x@, in the+-- context defined by @ctx@.+foreign import ccall "fq_poly.h fq_poly_scalar_submul_fq"+ fq_poly_scalar_submul_fq :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_scalar_div_fq/ /rop/ /op/ /len/ /x/ /ctx/ +--+-- Sets @(rop,len)@ to the quotient of @(op,len)@ by the scalar @x@, in the+-- context defined by @ctx@. An exception is raised if @x@ is zero.+foreign import ccall "fq_poly.h _fq_poly_scalar_div_fq"+ _fq_poly_scalar_div_fq :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_poly_scalar_div_fq/ /rop/ /op/ /x/ /ctx/ +--+-- Sets @rop@ to the quotient of @op@ by the scalar @x@, in the context+-- defined by @ctx@. An exception is raised if @x@ is zero.+foreign import ccall "fq_poly.h fq_poly_scalar_div_fq"+ fq_poly_scalar_div_fq :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /_fq_poly_mul_classical/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@, assuming that @len1@ is at least @len2@ and neither is+-- zero.+-- +-- Permits zero padding. Does not support aliasing of @rop@ with either+-- @op1@ or @op2@.+foreign import ccall "fq_poly.h _fq_poly_mul_classical"+ _fq_poly_mul_classical :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mul_classical/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@ using classical polynomial+-- multiplication.+foreign import ccall "fq_poly.h fq_poly_mul_classical"+ fq_poly_mul_classical :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mul_reorder/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@, assuming that @len1@ and @len2@ are non-zero.+-- +-- Permits zero padding. Supports aliasing.+foreign import ccall "fq_poly.h _fq_poly_mul_reorder"+ _fq_poly_mul_reorder :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mul_reorder/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@, reordering the two+-- indeterminates \(X\) and \(Y\) when viewing the polynomials as elements+-- of \(\mathbf{F}_p[X,Y]\).+-- +-- Suppose \(\mathbf{F}_q = \mathbf{F}_p[X]/ (f(X))\) and recall that+-- elements of \(\mathbf{F}_q\) are internally represented by elements of+-- type @fmpz_poly@. For small degree extensions but polynomials in+-- \(\mathbf{F}_q[Y]\) of large degree \(n\), we change the representation+-- to+-- +-- \[`\]+-- \[\begin{aligned}+-- \begin{split}+-- g(Y) & = \sum_{i=0}^{n} a_i(X) Y^i \\+-- & = \sum_{j=0}^{d} \sum_{i=0}^{n} \text{Coeff}(a_i(X), j) Y^i.+-- \end{split}+-- \end{aligned}\]+-- +-- This allows us to use a poor algorithm (such as classical+-- multiplication) in the \(X\)-direction and leverage the existing fast+-- integer multiplication routines in the \(Y\)-direction where the+-- polynomial degree \(n\) is large.+foreign import ccall "fq_poly.h fq_poly_mul_reorder"+ fq_poly_mul_reorder :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mul_univariate/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@.+-- +-- Permits zero padding and places no assumptions on the lengths @len1@ and+-- @len2@. Supports aliasing.+foreign import ccall "fq_poly.h _fq_poly_mul_univariate"+ _fq_poly_mul_univariate :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mul_univariate/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@ using a bivariate to+-- univariate transformation and reducing this problem to multiplying two+-- univariate polynomials.+foreign import ccall "fq_poly.h fq_poly_mul_univariate"+ fq_poly_mul_univariate :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mul_KS/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@.+-- +-- Permits zero padding and places no assumptions on the lengths @len1@ and+-- @len2@. Supports aliasing.+foreign import ccall "fq_poly.h _fq_poly_mul_KS"+ _fq_poly_mul_KS :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mul_KS/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@ using Kronecker+-- substitution, that is, by encoding each coefficient in+-- \(\mathbf{F}_{q}\) as an integer and reducing this problem to+-- multiplying two polynomials over the integers.+foreign import ccall "fq_poly.h fq_poly_mul_KS"+ fq_poly_mul_KS :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mul/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@, choosing an appropriate algorithm.+-- +-- Permits zero padding. Does not support aliasing.+foreign import ccall "fq_poly.h _fq_poly_mul"+ _fq_poly_mul :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mul/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@, choosing an appropriate+-- algorithm.+foreign import ccall "fq_poly.h fq_poly_mul"+ fq_poly_mul :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mullow_classical/ /rop/ /op1/ /len1/ /op2/ /len2/ /n/ /ctx/ +--+-- Sets @(rop, n)@ to the first \(n\) coefficients of @(op1, len1)@+-- multiplied by @(op2, len2)@.+-- +-- Assumes @0 \< n \<= len1 + len2 - 1@. Assumes neither @len1@ nor @len2@+-- is zero.+foreign import ccall "fq_poly.h _fq_poly_mullow_classical"+ _fq_poly_mullow_classical :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mullow_classical/ /rop/ /op1/ /op2/ /n/ /ctx/ +--+-- Sets @rop@ to the product of @poly1@ and @poly2@, computed using the+-- classical or schoolbook method.+foreign import ccall "fq_poly.h fq_poly_mullow_classical"+ fq_poly_mullow_classical :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mullow_univariate/ /rop/ /op1/ /len1/ /op2/ /len2/ /n/ /ctx/ +--+-- Sets @(rop, n)@ to the lowest \(n\) coefficients of the product of+-- @(op1, len1)@ and @(op2, len2)@, computed using a bivariate to+-- univariate transformation.+-- +-- Assumes that @len1@ and @len2@ are positive, but does allow for the+-- polynomials to be zero-padded. The polynomials may be zero, too. Assumes+-- \(n\) is positive. Supports aliasing between @res@, @poly1@ and @poly2@.+foreign import ccall "fq_poly.h _fq_poly_mullow_univariate"+ _fq_poly_mullow_univariate :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mullow_univariate/ /rop/ /op1/ /op2/ /n/ /ctx/ +--+-- Sets @rop@ to the lowest \(n\) coefficients of the product of @op1@ and+-- @op2@, computed using a bivariate to univariate transformation.+foreign import ccall "fq_poly.h fq_poly_mullow_univariate"+ fq_poly_mullow_univariate :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mullow_KS/ /rop/ /op1/ /len1/ /op2/ /len2/ /n/ /ctx/ +--+-- Sets @(rop, n)@ to the lowest \(n\) coefficients of the product of+-- @(op1, len1)@ and @(op2, len2)@.+-- +-- Assumes that @len1@ and @len2@ are positive, but does allow for the+-- polynomials to be zero-padded. The polynomials may be zero, too. Assumes+-- \(n\) is positive. Supports aliasing between @rop@, @op1@ and @op2@.+foreign import ccall "fq_poly.h _fq_poly_mullow_KS"+ _fq_poly_mullow_KS :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mullow_KS/ /rop/ /op1/ /op2/ /n/ /ctx/ +--+-- Sets @rop@ to the lowest \(n\) coefficients of the product of @op1@ and+-- @op2@.+foreign import ccall "fq_poly.h fq_poly_mullow_KS"+ fq_poly_mullow_KS :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mullow/ /rop/ /op1/ /len1/ /op2/ /len2/ /n/ /ctx/ +--+-- Sets @(rop, n)@ to the lowest \(n\) coefficients of the product of+-- @(op1, len1)@ and @(op2, len2)@.+-- +-- Assumes @0 \< n \<= len1 + len2 - 1@. Allows for zero-padding in the+-- inputs. Does not support aliasing between the inputs and the output.+foreign import ccall "fq_poly.h _fq_poly_mullow"+ _fq_poly_mullow :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mullow/ /rop/ /op1/ /op2/ /n/ /ctx/ +--+-- Sets @rop@ to the lowest \(n\) coefficients of the product of @op1@ and+-- @op2@.+foreign import ccall "fq_poly.h fq_poly_mullow"+ fq_poly_mullow :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mulhigh_classical/ /res/ /poly1/ /len1/ /poly2/ /len2/ /start/ /ctx/ +--+-- Computes the product of @(poly1, len1)@ and @(poly2, len2)@ and writes+-- the coefficients from @start@ onwards into the high coefficients of+-- @res@, the remaining coefficients being arbitrary but reduced. Assumes+-- that @len1 >= len2 > 0@. Aliasing of inputs and output is not permitted.+-- Algorithm is classical multiplication.+foreign import ccall "fq_poly.h _fq_poly_mulhigh_classical"+ _fq_poly_mulhigh_classical :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mulhigh_classical/ /res/ /poly1/ /poly2/ /start/ /ctx/ +--+-- Computes the product of @poly1@ and @poly2@ and writes the coefficients+-- from @start@ onwards into the high coefficients of @res@, the remaining+-- coefficients being arbitrary but reduced. Algorithm is classical+-- multiplication.+foreign import ccall "fq_poly.h fq_poly_mulhigh_classical"+ fq_poly_mulhigh_classical :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mulhigh/ /res/ /poly1/ /len1/ /poly2/ /len2/ /start/ /ctx/ +--+-- Computes the product of @(poly1, len1)@ and @(poly2, len2)@ and writes+-- the coefficients from @start@ onwards into the high coefficients of+-- @res@, the remaining coefficients being arbitrary but reduced. Assumes+-- that @len1 >= len2 > 0@. Aliasing of inputs and output is not permitted.+foreign import ccall "fq_poly.h _fq_poly_mulhigh"+ _fq_poly_mulhigh :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mulhigh/ /res/ /poly1/ /poly2/ /start/ /ctx/ +--+-- Computes the product of @poly1@ and @poly2@ and writes the coefficients+-- from @start@ onwards into the high coefficients of @res@, the remaining+-- coefficients being arbitrary but reduced.+foreign import ccall "fq_poly.h fq_poly_mulhigh"+ fq_poly_mulhigh :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mulmod/ /res/ /poly1/ /len1/ /poly2/ /len2/ /f/ /lenf/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+-- +-- It is required that @len1 + len2 - lenf > 0@, which is equivalent to+-- requiring that the result will actually be reduced. Otherwise, simply+-- use @_fq_poly_mul@ instead.+-- +-- Aliasing of @f@ and @res@ is not permitted.+foreign import ccall "fq_poly.h _fq_poly_mulmod"+ _fq_poly_mulmod :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mulmod/ /res/ /poly1/ /poly2/ /f/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+foreign import ccall "fq_poly.h fq_poly_mulmod"+ fq_poly_mulmod :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_mulmod_preinv/ /res/ /poly1/ /len1/ /poly2/ /len2/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+-- +-- It is required that @finv@ is the inverse of the reverse of @f@ mod+-- @x^lenf@.+-- +-- Aliasing of @res@ with any of the inputs is not permitted.+foreign import ccall "fq_poly.h _fq_poly_mulmod_preinv"+ _fq_poly_mulmod_preinv :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_mulmod_preinv/ /res/ /poly1/ /poly2/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@. @finv@ is the inverse of the reverse of @f@.+foreign import ccall "fq_poly.h fq_poly_mulmod_preinv"+ fq_poly_mulmod_preinv :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- Squaring --------------------------------------------------------------------++-- | /_fq_poly_sqr_classical/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, 2*len - 1)@ to the square of @(op, len)@, assuming that+-- @(op,len)@ is not zero and using classical polynomial multiplication.+-- +-- Permits zero padding. Does not support aliasing of @rop@ with either+-- @op1@ or @op2@.+foreign import ccall "fq_poly.h _fq_poly_sqr_classical"+ _fq_poly_sqr_classical :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_sqr_classical/ /rop/ /op/ /ctx/ +--+-- [Sets @rop@ to the square of @op@ using classical]+-- polynomial multiplication.+foreign import ccall "fq_poly.h fq_poly_sqr_classical"+ fq_poly_sqr_classical :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_sqr_reorder/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, 2*len- 1)@ to the square of @(op, len)@, assuming that @len@+-- is not zero reordering the two indeterminates \(X\) and \(Y\) when+-- viewing the polynomials as elements of \(\mathbf{F}_p[X,Y]\).+-- +-- Permits zero padding. Supports aliasing.+foreign import ccall "fq_poly.h _fq_poly_sqr_reorder"+ _fq_poly_sqr_reorder :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_sqr_reorder/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the square of @op@, assuming that @len@ is not zero+-- reordering the two indeterminates \(X\) and \(Y\) when viewing the+-- polynomials as elements of \(\mathbf{F}_p[X,Y]\). See+-- @fq_poly_mul_reorder@.+foreign import ccall "fq_poly.h fq_poly_sqr_reorder"+ fq_poly_sqr_reorder :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_sqr_KS/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, 2*len - 1)@ to the square of @(op, len)@.+-- +-- Permits zero padding and places no assumptions on the lengths @len1@ and+-- @len2@. Supports aliasing.+foreign import ccall "fq_poly.h _fq_poly_sqr_KS"+ _fq_poly_sqr_KS :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_sqr_KS/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the square @op@ using Kronecker substitution, that is, by+-- encoding each coefficient in \(\mathbf{F}_{q}\) as an integer and+-- reducing this problem to multiplying two polynomials over the integers.+foreign import ccall "fq_poly.h fq_poly_sqr_KS"+ fq_poly_sqr_KS :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_sqr/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, 2* len - 1)@ to the square of @(op, len)@, choosing an+-- appropriate algorithm.+-- +-- Permits zero padding. Does not support aliasing.+foreign import ccall "fq_poly.h _fq_poly_sqr"+ _fq_poly_sqr :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_sqr/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the square of @op@, choosing an appropriate algorithm.+foreign import ccall "fq_poly.h fq_poly_sqr"+ fq_poly_sqr :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- Powering --------------------------------------------------------------------++-- | /_fq_poly_pow/ /rop/ /op/ /len/ /e/ /ctx/ +--+-- Sets @rop = op^e@, assuming that @e, len > 0@ and that @rop@ has space+-- for @e*(len - 1) + 1@ coefficients. Does not support aliasing.+foreign import ccall "fq_poly.h _fq_poly_pow"+ _fq_poly_pow :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> CULong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_pow/ /rop/ /op/ /e/ /ctx/ +--+-- Computes @rop = op^e@. If \(e\) is zero, returns one, so that in+-- particular @0^0 = 1@.+foreign import ccall "fq_poly.h fq_poly_pow"+ fq_poly_pow :: Ptr CFqPoly -> Ptr CFqPoly -> CULong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_powmod_ui_binexp/ /res/ /poly/ /e/ /f/ /lenf/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_poly.h _fq_poly_powmod_ui_binexp"+ _fq_poly_powmod_ui_binexp :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CULong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_powmod_ui_binexp/ /res/ /poly/ /e/ /f/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@.+foreign import ccall "fq_poly.h fq_poly_powmod_ui_binexp"+ fq_poly_powmod_ui_binexp :: Ptr CFqPoly -> Ptr CFqPoly -> CULong -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_powmod_ui_binexp_preinv/ /res/ /poly/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_poly.h _fq_poly_powmod_ui_binexp_preinv"+ _fq_poly_powmod_ui_binexp_preinv :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CULong -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_powmod_ui_binexp_preinv/ /res/ /poly/ /e/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+foreign import ccall "fq_poly.h fq_poly_powmod_ui_binexp_preinv"+ fq_poly_powmod_ui_binexp_preinv :: Ptr CFqPoly -> Ptr CFqPoly -> CULong -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_powmod_fmpz_binexp/ /res/ /poly/ /e/ /f/ /lenf/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_poly.h _fq_poly_powmod_fmpz_binexp"+ _fq_poly_powmod_fmpz_binexp :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> Ptr CFmpz -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_powmod_fmpz_binexp/ /res/ /poly/ /e/ /f/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@.+foreign import ccall "fq_poly.h fq_poly_powmod_fmpz_binexp"+ fq_poly_powmod_fmpz_binexp :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFmpz -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_powmod_fmpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_poly.h _fq_poly_powmod_fmpz_binexp_preinv"+ _fq_poly_powmod_fmpz_binexp_preinv :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> Ptr CFmpz -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_powmod_fmpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+foreign import ccall "fq_poly.h fq_poly_powmod_fmpz_binexp_preinv"+ fq_poly_powmod_fmpz_binexp_preinv :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFmpz -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_powmod_fmpz_sliding_preinv/ /res/ /poly/ /e/ /k/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using+-- sliding-window exponentiation with window size @k@. We require @e > 0@.+-- We require @finv@ to be the inverse of the reverse of @f@. If @k@ is set+-- to zero, then an \"optimum\" size will be selected automatically base on+-- @e@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_poly.h _fq_poly_powmod_fmpz_sliding_preinv"+ _fq_poly_powmod_fmpz_sliding_preinv :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> Ptr CFmpz -> CULong -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_powmod_fmpz_sliding_preinv/ /res/ /poly/ /e/ /k/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using+-- sliding-window exponentiation with window size @k@. We require @e >= 0@.+-- We require @finv@ to be the inverse of the reverse of @f@. If @k@ is set+-- to zero, then an \"optimum\" size will be selected automatically base on+-- @e@.+foreign import ccall "fq_poly.h fq_poly_powmod_fmpz_sliding_preinv"+ fq_poly_powmod_fmpz_sliding_preinv :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFmpz -> CULong -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_powmod_x_fmpz_preinv/ /res/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e > 0@. We require @finv@ to be the+-- inverse of the reverse of @f@.+-- +-- We require @lenf > 2@. The output @res@ must have room for @lenf - 1@+-- coefficients.+foreign import ccall "fq_poly.h _fq_poly_powmod_x_fmpz_preinv"+ _fq_poly_powmod_x_fmpz_preinv :: Ptr (Ptr CFq) -> Ptr CFmpz -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_powmod_x_fmpz_preinv/ /res/ /e/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e >= 0@. We require @finv@ to be the+-- inverse of the reverse of @f@.+foreign import ccall "fq_poly.h fq_poly_powmod_x_fmpz_preinv"+ fq_poly_powmod_x_fmpz_preinv :: Ptr CFqPoly -> Ptr CFmpz -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_pow_trunc_binexp/ /res/ /poly/ /e/ /trunc/ /ctx/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ (assumed to be zero+-- padded if necessary to length @trunc@) to the power @e@. This is+-- equivalent to doing a powering followed by a truncation. We require that+-- @res@ has enough space for @trunc@ coefficients, that @trunc > 0@ and+-- that @e > 1@. Aliasing is not permitted. Uses the binary exponentiation+-- method.+foreign import ccall "fq_poly.h _fq_poly_pow_trunc_binexp"+ _fq_poly_pow_trunc_binexp :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CULong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_pow_trunc_binexp/ /res/ /poly/ /e/ /trunc/ /ctx/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ to the power @e@.+-- This is equivalent to doing a powering followed by a truncation. Uses+-- the binary exponentiation method.+foreign import ccall "fq_poly.h fq_poly_pow_trunc_binexp"+ fq_poly_pow_trunc_binexp :: Ptr CFqPoly -> Ptr CFqPoly -> CULong -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_pow_trunc/ /res/ /poly/ /e/ /trunc/ /mod/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ (assumed to be zero+-- padded if necessary to length @trunc@) to the power @e@. This is+-- equivalent to doing a powering followed by a truncation. We require that+-- @res@ has enough space for @trunc@ coefficients, that @trunc > 0@ and+-- that @e > 1@. Aliasing is not permitted.+foreign import ccall "fq_poly.h _fq_poly_pow_trunc"+ _fq_poly_pow_trunc :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CULong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_pow_trunc/ /res/ /poly/ /e/ /trunc/ /ctx/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ to the power @e@.+-- This is equivalent to doing a powering followed by a truncation.+foreign import ccall "fq_poly.h fq_poly_pow_trunc"+ fq_poly_pow_trunc :: Ptr CFqPoly -> Ptr CFqPoly -> CULong -> CLong -> Ptr CFqCtx -> IO ()++-- Shifting --------------------------------------------------------------------++-- | /_fq_poly_shift_left/ /rop/ /op/ /len/ /n/ /ctx/ +--+-- Sets @(rop, len + n)@ to @(op, len)@ shifted left by \(n\) coefficients.+-- +-- Inserts zero coefficients at the lower end. Assumes that @len@ and \(n\)+-- are positive, and that @rop@ fits @len + n@ elements. Supports aliasing+-- between @rop@ and @op@.+foreign import ccall "fq_poly.h _fq_poly_shift_left"+ _fq_poly_shift_left :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_shift_left/ /rop/ /op/ /n/ /ctx/ +--+-- Sets @rop@ to @op@ shifted left by \(n\) coeffs. Zero coefficients are+-- inserted.+foreign import ccall "fq_poly.h fq_poly_shift_left"+ fq_poly_shift_left :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_shift_right/ /rop/ /op/ /len/ /n/ /ctx/ +--+-- Sets @(rop, len - n)@ to @(op, len)@ shifted right by \(n\)+-- coefficients.+-- +-- Assumes that @len@ and \(n\) are positive, that @len > n@, and that+-- @rop@ fits @len - n@ elements. Supports aliasing between @rop@ and @op@,+-- although in this case the top coefficients of @op@ are not set to zero.+foreign import ccall "fq_poly.h _fq_poly_shift_right"+ _fq_poly_shift_right :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_shift_right/ /rop/ /op/ /n/ /ctx/ +--+-- Sets @rop@ to @op@ shifted right by \(n\) coefficients. If \(n\) is+-- equal to or greater than the current length of @op@, @rop@ is set to the+-- zero polynomial.+foreign import ccall "fq_poly.h fq_poly_shift_right"+ fq_poly_shift_right :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- Norms -----------------------------------------------------------------------++-- | /fq_poly_hamming_weight/ /op/ /ctx/ +--+-- Returns the number of non-zero entries in the polynomial @op@.+foreign import ccall "fq_poly.h fq_poly_hamming_weight"+ fq_poly_hamming_weight :: Ptr CFqPoly -> Ptr CFqCtx -> IO CLong++-- Euclidean division ----------------------------------------------------------++-- | /_fq_poly_divrem/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Computes @(Q, lenA - lenB + 1)@, @(R, lenA)@ such that \(A = B Q + R\)+-- with \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- Assumes that the leading coefficient of \(B\) is invertible and that+-- @invB@ is its inverse.+-- +-- Assumes that \(\operatorname{len}(A), \operatorname{len}(B) > 0\).+-- Allows zero-padding in @(A, lenA)@. \(R\) and \(A\) may be aliased, but+-- apart from this no aliasing of input and output operands is allowed.+foreign import ccall "fq_poly.h _fq_poly_divrem"+ _fq_poly_divrem :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_poly_divrem/ /Q/ /R/ /A/ /B/ /ctx/ +--+-- Computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- Assumes that the leading coefficient of \(B\) is invertible. This can be+-- taken for granted the context is for a finite field, that is, when \(p\)+-- is prime and \(f(X)\) is irreducible.+foreign import ccall "fq_poly.h fq_poly_divrem"+ fq_poly_divrem :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_divrem_f/ /f/ /Q/ /R/ /A/ /B/ /ctx/ +--+-- Either finds a non-trivial factor \(f\) of the modulus of @ctx@, or+-- computes \(Q\), \(R\) such that \(A = B Q + R\) and+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- If the leading coefficient of \(B\) is invertible, the division with+-- remainder operation is carried out, \(Q\) and \(R\) are computed+-- correctly, and \(f\) is set to \(1\). Otherwise, \(f\) is set to a+-- non-trivial factor of the modulus and \(Q\) and \(R\) are not touched.+-- +-- Assumes that \(B\) is non-zero.+foreign import ccall "fq_poly.h fq_poly_divrem_f"+ fq_poly_divrem_f :: Ptr CFq -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_rem/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Sets @R@ to the remainder of the division of @(A,lenA)@ by @(B,lenB)@.+-- Assumes that the leading coefficient of @(B,lenB)@ is invertible and+-- that @invB@ is its inverse.+foreign import ccall "fq_poly.h _fq_poly_rem"+ _fq_poly_rem :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_poly_rem/ /R/ /A/ /B/ /ctx/ +--+-- Sets @R@ to the remainder of the division of @A@ by @B@ in the context+-- described by @ctx@.+foreign import ccall "fq_poly.h fq_poly_rem"+ fq_poly_rem :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_div/ /Q/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) with \(0+-- \leq \operatorname{len}(R) < \operatorname{len}(B)\) but only sets+-- @(Q, lenA - lenB + 1)@. Allows zero-padding in \(A\) but not in \(B\).+-- Assumes that the leading coefficient of \(B\) is a unit.+foreign import ccall "fq_poly.h _fq_poly_div"+ _fq_poly_div :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_poly_div/ /Q/ /A/ /B/ /ctx/ +--+-- Notionally finds polynomials \(Q\) and \(R\) such that \(A = B Q + R\)+-- with \(\operatorname{len}(R) < \operatorname{len}(B)\), but returns only+-- @Q@. If \(\operatorname{len}(B) = 0\) an exception is raised.+foreign import ccall "fq_poly.h fq_poly_div"+ fq_poly_div :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_div_newton_n_preinv/ /Q/ /A/ /lenA/ /B/ /lenB/ /Binv/ /lenBinv/ /ctx_t/ +--+-- Notionally computes polynomials \(Q\) and \(R\) such that \(A = BQ + R\)+-- with \(\operatorname{len}(R)\) less than @lenB@, where @A@ is of length+-- @lenA@ and @B@ is of length @lenB@, but return only \(Q\).+-- +-- We require that \(Q\) have space for @lenA - lenB + 1@ coefficients and+-- assume that the leading coefficient of \(B\) is a unit. Furthermore, we+-- assume that \(Binv\) is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\).+-- +-- The algorithm used is to reverse the polynomials and divide the+-- resulting power series, then reverse the result.+foreign import ccall "fq_poly.h _fq_poly_div_newton_n_preinv"+ _fq_poly_div_newton_n_preinv :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFq -> IO ()++-- | /fq_poly_div_newton_n_preinv/ /Q/ /A/ /B/ /Binv/ /ctx/ +--+-- Notionally computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R) < \operatorname{len}(B)\), but returns only+-- \(Q\).+-- +-- We assume that the leading coefficient of \(B\) is a unit and that+-- \(Binv\) is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\).+-- +-- It is required that the length of \(A\) is less than or equal to 2*the+-- length of \(B\) - 2.+-- +-- The algorithm used is to reverse the polynomials and divide the+-- resulting power series, then reverse the result.+foreign import ccall "fq_poly.h fq_poly_div_newton_n_preinv"+ fq_poly_div_newton_n_preinv :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_divrem_newton_n_preinv/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /Binv/ /lenBinv/ /ctx/ +--+-- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R)\) less than @lenB@, where \(A\) is of length+-- @lenA@ and \(B\) is of length @lenB@. We require that \(Q\) have space+-- for @lenA - lenB + 1@ coefficients. Furthermore, we assume that \(Binv\)+-- is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\). The algorithm used is to call+-- @div_newton_n_preinv@ and then multiply out and compute the remainder.+foreign import ccall "fq_poly.h _fq_poly_divrem_newton_n_preinv"+ _fq_poly_divrem_newton_n_preinv :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- -- | /fq_poly_divrem_newton_preinv/ /Q/ /R/ /A/ /B/ /Binv/ /ctx/ +-- --+-- -- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- -- \(\operatorname{len}(R) <+-- -- \operatorname{len}(B)\). We assume \(Binv\) is the inverse of the+-- -- reverse of \(B\) mod \(x^{\operatorname{len}(B)}\).+-- -- +-- -- It is required that the length of \(A\) is less than or equal to 2*the+-- -- length of \(B\) - 2.+-- -- +-- -- The algorithm used is to call @div_newton_n@ and then multiply out and+-- -- compute the remainder.+-- foreign import ccall "fq_poly.h fq_poly_divrem_newton_preinv"+-- fq_poly_divrem_newton_preinv :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_inv_series_newton/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ of length @n@ whose constant coefficient is invertible modulo+-- the given modulus, find a polynomial @Qinv@ of length @n@ such that+-- @Q * Qinv@ is @1@ modulo \(x^n\). Requires @n > 0@. This function can be+-- viewed as inverting a power series via Newton iteration.+foreign import ccall "fq_poly.h _fq_poly_inv_series_newton"+ _fq_poly_inv_series_newton :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_inv_series_newton/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ find @Qinv@ such that @Q * Qinv@ is @1@ modulo \(x^n\). The+-- constant coefficient of @Q@ must be invertible modulo the modulus of+-- @Q@. An exception is raised if this is not the case or if @n = 0@. This+-- function can be viewed as inverting a power series via Newton iteration.+foreign import ccall "fq_poly.h fq_poly_inv_series_newton"+ fq_poly_inv_series_newton :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_inv_series/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ of length @n@ whose constant coefficient is invertible modulo+-- the given modulus, find a polynomial @Qinv@ of length @n@ such that+-- @Q * Qinv@ is @1@ modulo \(x^n\). Requires @n > 0@.+foreign import ccall "fq_poly.h _fq_poly_inv_series"+ _fq_poly_inv_series :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_inv_series/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ find @Qinv@ such that @Q * Qinv@ is @1@ modulo \(x^n\). The+-- constant coefficient of @Q@ must be invertible modulo the modulus of+-- @Q@. An exception is raised if this is not the case or if @n = 0@.+foreign import ccall "fq_poly.h fq_poly_inv_series"+ fq_poly_inv_series :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_div_series/ /Q/ /A/ /Alen/ /B/ /Blen/ /n/ /ctx/ +--+-- Set @(Q, n)@ to the quotient of the series @(A, Alen@) and @(B, Blen)@+-- assuming @Alen, Blen \<= n@. We assume the bottom coefficient of @B@ is+-- invertible.+foreign import ccall "fq_poly.h _fq_poly_div_series"+ _fq_poly_div_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_div_series/ /Q/ /A/ /B/ /n/ /ctx/ +--+-- Set \(Q\) to the quotient of the series \(A\) by \(B\), thinking of the+-- series as though they were of length \(n\). We assume that the bottom+-- coefficient of \(B\) is invertible.+foreign import ccall "fq_poly.h fq_poly_div_series"+ fq_poly_div_series :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFqCtx -> IO ()++-- Greatest common divisor -----------------------------------------------------++-- | /fq_poly_gcd/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the greatest common divisor of @op1@ and @op2@, using the+-- either the Euclidean or HGCD algorithm. The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+foreign import ccall "fq_poly.h fq_poly_gcd"+ fq_poly_gcd :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_gcd/ /G/ /A/ /lenA/ /B/ /lenB/ /ctx/ +--+-- Computes the GCD of \(A\) of length @lenA@ and \(B\) of length @lenB@,+-- where @lenA >= lenB > 0@ and sets \(G\) to it. The length of the GCD+-- \(G\) is returned by the function. No attempt is made to make the GCD+-- monic. It is required that \(G\) have space for @lenB@ coefficients.+foreign import ccall "fq_poly.h _fq_poly_gcd"+ _fq_poly_gcd :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO CLong++-- | /_fq_poly_gcd_euclidean_f/ /f/ /G/ /A/ /lenA/ /B/ /lenB/ /ctx/ +--+-- Either sets \(f = 1\) and \(G\) to the greatest common divisor of+-- \((A,\operatorname{len}(A))\) and \((B, \operatorname{len}(B))\) and+-- returns its length, or sets \(f\) to a non-trivial factor of the modulus+-- of @ctx@ and leaves the contents of the vector \((G, lenB)\) undefined.+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\)+-- and that the vector \(G\) has space for sufficiently many coefficients.+foreign import ccall "fq_poly.h _fq_poly_gcd_euclidean_f"+ _fq_poly_gcd_euclidean_f :: Ptr CFq -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO CLong++-- | /fq_poly_gcd_euclidean_f/ /f/ /G/ /A/ /B/ /ctx/ +--+-- Either sets \(f = 1\) and \(G\) to the greatest common divisor of \(A\)+-- and \(B\) or sets \(f\) to a factor of the modulus of @ctx@.+foreign import ccall "fq_poly.h fq_poly_gcd_euclidean_f"+ fq_poly_gcd_euclidean_f :: Ptr CFq -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_xgcd/ /G/ /S/ /T/ /A/ /lenA/ /B/ /lenB/ /ctx/ +--+-- Computes the GCD of \(A\) and \(B\) together with cofactors \(S\) and+-- \(T\) such that \(S A + T B = G\). Returns the length of \(G\).+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1\)+-- and \((\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)\).+-- +-- No attempt is made to make the GCD monic.+-- +-- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- coefficients. Writes \(\operatorname{len}(B)-1\) and+-- \(\operatorname{len}(A)-1\) coefficients to \(S\) and \(T\),+-- respectively. Note that, in fact,+-- \(\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)\)+-- and+-- \(\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)\).+-- +-- No aliasing of input and output operands is permitted.+foreign import ccall "fq_poly.h _fq_poly_xgcd"+ _fq_poly_xgcd :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO CLong++-- | /fq_poly_xgcd/ /G/ /S/ /T/ /A/ /B/ /ctx/ +--+-- Computes the GCD of \(A\) and \(B\). The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+-- +-- Polynomials @S@ and @T@ are computed such that @S*A + T*B = G@. The+-- length of @S@ will be at most @lenB@ and the length of @T@ will be at+-- most @lenA@.+foreign import ccall "fq_poly.h fq_poly_xgcd"+ fq_poly_xgcd :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_xgcd_euclidean_f/ /f/ /G/ /S/ /T/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Either sets \(f = 1\) and computes the GCD of \(A\) and \(B\) together+-- with cofactors \(S\) and \(T\) such that \(S A + T B = G\); otherwise,+-- sets \(f\) to a non-trivial factor of the modulus of @ctx@ and leaves+-- \(G\), \(S\), and \(T\) undefined. Returns the length of \(G\).+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1\)+-- and \((\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)\).+-- +-- No attempt is made to make the GCD monic.+-- +-- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- coefficients. Writes \(\operatorname{len}(B)-1\) and+-- \(\operatorname{len}(A)-1\) coefficients to \(S\) and \(T\),+-- respectively. Note that, in fact,+-- \(\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)\)+-- and+-- \(\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)\).+-- +-- No aliasing of input and output operands is permitted.+foreign import ccall "fq_poly.h _fq_poly_xgcd_euclidean_f"+ _fq_poly_xgcd_euclidean_f :: Ptr CFq -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFmpz -> Ptr CFqCtx -> IO CLong++-- | /fq_poly_xgcd_euclidean_f/ /f/ /G/ /S/ /T/ /A/ /B/ /ctx/ +--+-- Either sets \(f = 1\) and computes the GCD of \(A\) and \(B\) or sets+-- \(f\) to a non-trivial factor of the modulus of @ctx@.+-- +-- If the GCD is computed, polynomials @S@ and @T@ are computed such that+-- @S*A + T*B = G@; otherwise, they are undefined. The length of @S@ will+-- be at most @lenB@ and the length of @T@ will be at most @lenA@.+-- +-- The GCD of zero polynomials is defined to be zero, whereas the GCD of+-- the zero polynomial and some other polynomial \(P\) is defined to be+-- \(P\). Except in the case where the GCD is zero, the GCD \(G\) is made+-- monic.+foreign import ccall "fq_poly.h fq_poly_xgcd_euclidean_f"+ fq_poly_xgcd_euclidean_f :: Ptr CFq -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- Divisibility testing --------------------------------------------------------++-- | /_fq_poly_divides/ /Q/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Returns \(1\) if @(B, lenB)@ divides @(A, lenA)@ exactly and sets \(Q\)+-- to the quotient, otherwise returns \(0\).+-- +-- It is assumed that+-- \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\) and that \(Q\)+-- has space for \(\operatorname{len}(A) - \operatorname{len}(B) + 1\)+-- coefficients.+-- +-- Aliasing of \(Q\) with either of the inputs is not permitted.+-- +-- This function is currently unoptimised and provided for convenience+-- only.+foreign import ccall "fq_poly.h _fq_poly_divides"+ _fq_poly_divides :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_divides/ /Q/ /A/ /B/ /ctx/ +--+-- Returns \(1\) if \(B\) divides \(A\) exactly and sets \(Q\) to the+-- quotient, otherwise returns \(0\).+-- +-- This function is currently unoptimised and provided for convenience+-- only.+foreign import ccall "fq_poly.h fq_poly_divides"+ fq_poly_divides :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO CInt++-- Derivative ------------------------------------------------------------------++-- | /_fq_poly_derivative/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, len - 1)@ to the derivative of @(op, len)@. Also handles the+-- cases where @len@ is \(0\) or \(1\) correctly. Supports aliasing of+-- @rop@ and @op@.+foreign import ccall "fq_poly.h _fq_poly_derivative"+ _fq_poly_derivative :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_derivative/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the derivative of @op@.+foreign import ccall "fq_poly.h fq_poly_derivative"+ fq_poly_derivative :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- Square root -----------------------------------------------------------------++-- | /_fq_poly_invsqrt_series/ /g/ /h/ /n/ /mod/ +--+-- Set the first \(n\) terms of \(g\) to the series expansion of+-- \(1/\sqrt{h}\). It is assumed that \(n > 0\), that \(h\) has constant+-- term 1 and that \(h\) is zero-padded as necessary to length \(n\).+-- Aliasing is not permitted.+foreign import ccall "fq_poly.h _fq_poly_invsqrt_series"+ _fq_poly_invsqrt_series :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_invsqrt_series/ /g/ /h/ /n/ /ctx/ +--+-- Set \(g\) to the series expansion of \(1/\sqrt{h}\) to order \(O(x^n)\).+-- It is assumed that \(h\) has constant term 1.+foreign import ccall "fq_poly.h fq_poly_invsqrt_series"+ fq_poly_invsqrt_series :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_sqrt_series/ /g/ /h/ /n/ /ctx/ +--+-- Set the first \(n\) terms of \(g\) to the series expansion of+-- \(\sqrt{h}\). It is assumed that \(n > 0\), that \(h\) has constant term+-- 1 and that \(h\) is zero-padded as necessary to length \(n\). Aliasing+-- is not permitted.+foreign import ccall "fq_poly.h _fq_poly_sqrt_series"+ _fq_poly_sqrt_series :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_sqrt_series/ /g/ /h/ /n/ /ctx/ +--+-- Set \(g\) to the series expansion of \(\sqrt{h}\) to order \(O(x^n)\).+-- It is assumed that \(h\) has constant term 1.+foreign import ccall "fq_poly.h fq_poly_sqrt_series"+ fq_poly_sqrt_series :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_sqrt/ /s/ /p/ /n/ /mod/ +--+-- If @(p, n)@ is a perfect square, sets @(s, n \/ 2 + 1)@ to a square root+-- of \(p\) and returns 1. Otherwise returns 0.+foreign import ccall "fq_poly.h _fq_poly_sqrt"+ _fq_poly_sqrt :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_sqrt/ /s/ /p/ /mod/ +--+-- If \(p\) is a perfect square, sets \(s\) to a square root of \(p\) and+-- returns 1. Otherwise returns 0.+foreign import ccall "fq_poly.h fq_poly_sqrt"+ fq_poly_sqrt :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO CInt++-- Evaluation ------------------------------------------------------------------++-- | /_fq_poly_evaluate_fq/ /rop/ /op/ /len/ /a/ /ctx/ +--+-- Sets @rop@ to @(op, len)@ evaluated at \(a\).+-- +-- Supports zero padding. There are no restrictions on @len@, that is,+-- @len@ is allowed to be zero, too.+foreign import ccall "fq_poly.h _fq_poly_evaluate_fq"+ _fq_poly_evaluate_fq :: Ptr CFq -> Ptr (Ptr CFq) -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /fq_poly_evaluate_fq/ /rop/ /f/ /a/ /ctx/ +--+-- Sets @rop@ to the value of \(f(a)\).+-- +-- As the coefficient ring \(\mathbf{F}_q\) is finite, Horner\'s method is+-- sufficient.+foreign import ccall "fq_poly.h fq_poly_evaluate_fq"+ fq_poly_evaluate_fq :: Ptr CFq -> Ptr CFqPoly -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- Composition -----------------------------------------------------------------++-- | /_fq_poly_compose/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @rop@ to the composition of @(op1, len1)@ and @(op2, len2)@.+-- +-- Assumes that @rop@ has space for @(len1-1)*(len2-1) + 1@ coefficients.+-- Assumes that @op1@ and @op2@ are non-zero polynomials. Does not support+-- aliasing between any of the inputs and the output.+foreign import ccall "fq_poly.h _fq_poly_compose"+ _fq_poly_compose :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_compose/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the composition of @op1@ and @op2@. To be precise about+-- the order of composition, denoting @rop@, @op1@, and @op2@ by \(f\),+-- \(g\), and \(h\), respectively, sets \(f(t) = g(h(t))\).+foreign import ccall "fq_poly.h fq_poly_compose"+ fq_poly_compose :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_compose_mod_horner/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). The output is not allowed+-- to be aliased with any of the inputs.+-- +-- The algorithm used is Horner\'s rule.+foreign import ccall "fq_poly.h _fq_poly_compose_mod_horner"+ _fq_poly_compose_mod_horner :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_compose_mod_horner/ /res/ /f/ /g/ /h/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero. The algorithm used is Horner\'s rule.+foreign import ccall "fq_poly.h fq_poly_compose_mod_horner"+ fq_poly_compose_mod_horner :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_compose_mod_horner_preinv/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /hinv/ /lenhiv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+-- +-- The algorithm used is Horner\'s rule.+foreign import ccall "fq_poly.h _fq_poly_compose_mod_horner_preinv"+ _fq_poly_compose_mod_horner_preinv :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_compose_mod_horner_preinv/ /res/ /f/ /g/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+-- The algorithm used is Horner\'s rule.+foreign import ccall "fq_poly.h fq_poly_compose_mod_horner_preinv"+ fq_poly_compose_mod_horner_preinv :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_compose_mod_brent_kung/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). The output is not+-- allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_poly.h _fq_poly_compose_mod_brent_kung"+ _fq_poly_compose_mod_brent_kung :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_compose_mod_brent_kung/ /res/ /f/ /g/ /h/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\). The+-- algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_poly.h fq_poly_compose_mod_brent_kung"+ fq_poly_compose_mod_brent_kung :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_compose_mod_brent_kung_preinv/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /hinv/ /lenhiv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_poly.h _fq_poly_compose_mod_brent_kung_preinv"+ _fq_poly_compose_mod_brent_kung_preinv :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_compose_mod_brent_kung_preinv/ /res/ /f/ /g/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_poly.h fq_poly_compose_mod_brent_kung_preinv"+ fq_poly_compose_mod_brent_kung_preinv :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_compose_mod/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). The output is not allowed+-- to be aliased with any of the inputs.+foreign import ccall "fq_poly.h _fq_poly_compose_mod"+ _fq_poly_compose_mod :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_compose_mod/ /res/ /f/ /g/ /h/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero.+foreign import ccall "fq_poly.h fq_poly_compose_mod"+ fq_poly_compose_mod :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_compose_mod_preinv/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /hinv/ /lenhiv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+foreign import ccall "fq_poly.h _fq_poly_compose_mod_preinv"+ _fq_poly_compose_mod_preinv :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_compose_mod_preinv/ /res/ /f/ /g/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+foreign import ccall "fq_poly.h fq_poly_compose_mod_preinv"+ fq_poly_compose_mod_preinv :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_reduce_matrix_mod_poly/ /A/ /B/ /f/ /ctx/ +--+-- Sets the ith row of @A@ to the reduction of the ith row of \(B\) modulo+-- \(f\) for \(i=1,\ldots,\sqrt{\deg(f)}\). We require \(B\) to be at least+-- a \(\sqrt{\deg(f)}\times \deg(f)\) matrix and \(f\) to be nonzero.+foreign import ccall "fq_poly.h _fq_poly_reduce_matrix_mod_poly"+ _fq_poly_reduce_matrix_mod_poly :: Ptr CFqMat -> Ptr CFqMat -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_precompute_matrix/ /A/ /f/ /g/ /leng/ /ginv/ /lenginv/ /ctx/ +--+-- Sets the ith row of @A@ to \(f^i\) modulo \(g\) for+-- \(i=1,\ldots,\sqrt{\deg(g)}\). We require \(A\) to be a+-- \(\sqrt{\deg(g)}\times \deg(g)\) matrix. We require @ginv@ to be the+-- inverse of the reverse of @g@ and \(g\) to be nonzero.+foreign import ccall "fq_poly.h _fq_poly_precompute_matrix"+ _fq_poly_precompute_matrix :: Ptr CFqMat -> Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_precompute_matrix/ /A/ /f/ /g/ /ginv/ /ctx/ +--+-- Sets the ith row of @A@ to \(f^i\) modulo \(g\) for+-- \(i=1,\ldots,\sqrt{\deg(g)}\). We require \(A\) to be a+-- \(\sqrt{\deg(g)}\times \deg(g)\) matrix. We require @ginv@ to be the+-- inverse of the reverse of @g@.+foreign import ccall "fq_poly.h fq_poly_precompute_matrix"+ fq_poly_precompute_matrix :: Ptr CFqMat -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /_fq_poly_compose_mod_brent_kung_precomp_preinv/ /res/ /f/ /lenf/ /A/ /h/ /lenh/ /hinv/ /lenhinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero. We require that the ith row of \(A\) contains \(g^i\)+-- for \(i=1,\ldots,\sqrt{\deg(h)}\), i.e. \(A\) is a+-- \(\sqrt{\deg(h)}\times \deg(h)\) matrix. We also require that the length+-- of \(f\) is less than the length of \(h\). Furthermore, we require+-- @hinv@ to be the inverse of the reverse of @h@. The output is not+-- allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_poly.h _fq_poly_compose_mod_brent_kung_precomp_preinv"+ _fq_poly_compose_mod_brent_kung_precomp_preinv :: Ptr (Ptr CFq) -> Ptr (Ptr CFq) -> CLong -> Ptr CFqMat -> Ptr (Ptr CFq) -> CLong -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_compose_mod_brent_kung_precomp_preinv/ /res/ /f/ /A/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that the+-- ith row of \(A\) contains \(g^i\) for \(i=1,\ldots,\sqrt{\deg(h)}\),+-- i.e. \(A\) is a \(\sqrt{\deg(h)}\times+-- \deg(h)\) matrix. We require that \(h\) is nonzero and that \(f\) has+-- smaller degree than \(h\). Furthermore, we require @hinv@ to be the+-- inverse of the reverse of @h@. This version of Brent-Kung modular+-- composition is particularly useful if one has to perform several modular+-- composition of the form \(f(g)\) modulo \(h\) for fixed \(g\) and \(h\).+foreign import ccall "fq_poly.h fq_poly_compose_mod_brent_kung_precomp_preinv"+ fq_poly_compose_mod_brent_kung_precomp_preinv :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqMat -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- Output ----------------------------------------------------------------------++-- | /_fq_poly_fprint_pretty/ /file/ /poly/ /len/ /x/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to the stream @file@,+-- using the string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_poly.h _fq_poly_fprint_pretty"+ _fq_poly_fprint_pretty :: Ptr CFile -> Ptr (Ptr CFq) -> CLong -> CString -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_fprint_pretty/ /file/ /poly/ /x/ /ctx/ +--+-- Prints the pretty representation of @poly@ to the stream @file@, using+-- the string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_poly.h fq_poly_fprint_pretty"+ fq_poly_fprint_pretty :: Ptr CFile -> Ptr CFqPoly -> CString -> Ptr CFqCtx -> IO CInt++-- | /_fq_poly_print_pretty/ /poly/ /len/ /x/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to @stdout@, using the+-- string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_poly.h _fq_poly_print_pretty"+ _fq_poly_print_pretty :: Ptr (Ptr CFq) -> CLong -> CString -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_print_pretty/ /poly/ /x/ /ctx/ +--+-- Prints the pretty representation of @poly@ to @stdout@, using the string+-- @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+fq_poly_print_pretty :: Ptr CFqPoly -> CString -> Ptr CFqCtx -> IO CInt+fq_poly_print_pretty poly var ctx = + printCStr (\poly -> fq_poly_get_str_pretty poly var ctx) poly+ +-- | /_fq_poly_fprint/ /file/ /poly/ /len/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_poly.h _fq_poly_fprint"+ _fq_poly_fprint :: Ptr CFile -> Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_fprint/ /file/ /poly/ /ctx/ +--+-- Prints the pretty representation of @poly@ to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_poly.h fq_poly_fprint"+ fq_poly_fprint :: Ptr CFile -> Ptr CFqPoly -> Ptr CFqCtx -> IO CInt+ +-- | /_fq_poly_print/ /poly/ /len/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_poly.h _fq_poly_print"+ _fq_poly_print :: Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_print/ /poly/ /ctx/ +--+-- Prints the representation of @poly@ to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+fq_poly_print :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt+fq_poly_print poly ctx = printCStr (flip fq_poly_get_str ctx) poly+ +-- | /_fq_poly_get_str/ /poly/ /len/ /ctx/ +--+-- Returns the plain FLINT string representation of the polynomial+-- @(poly, len)@.+foreign import ccall "fq_poly.h _fq_poly_get_str"+ _fq_poly_get_str :: Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO CString++-- | /fq_poly_get_str/ /poly/ /ctx/ +--+-- Returns the plain FLINT string representation of the polynomial @poly@.+foreign import ccall "fq_poly.h fq_poly_get_str"+ fq_poly_get_str :: Ptr CFqPoly -> Ptr CFqCtx -> IO CString++-- | /_fq_poly_get_str_pretty/ /poly/ /len/ /x/ /ctx/ +--+-- Returns a pretty representation of the polynomial @(poly, len)@ using+-- the null-terminated string @x@ as the variable name.+foreign import ccall "fq_poly.h _fq_poly_get_str_pretty"+ _fq_poly_get_str_pretty :: Ptr (Ptr CFq) -> CLong -> CString -> Ptr CFqCtx -> IO CString++-- | /fq_poly_get_str_pretty/ /poly/ /x/ /ctx/ +--+-- Returns a pretty representation of the polynomial @poly@ using the+-- null-terminated string @x@ as the variable name+foreign import ccall "fq_poly.h fq_poly_get_str_pretty"+ fq_poly_get_str_pretty :: Ptr CFqPoly -> CString -> Ptr CFqCtx -> IO CString++-- Inflation and deflation -----------------------------------------------------++-- | /fq_poly_inflate/ /result/ /input/ /inflation/ /ctx/ +--+-- Sets @result@ to the inflated polynomial \(p(x^n)\) where \(p\) is given+-- by @input@ and \(n\) is given by @inflation@.+foreign import ccall "fq_poly.h fq_poly_inflate"+ fq_poly_inflate :: Ptr CFqPoly -> Ptr CFqPoly -> CULong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_deflate/ /result/ /input/ /deflation/ /ctx/ +--+-- Sets @result@ to the deflated polynomial \(p(x^{1/n})\) where \(p\) is+-- given by @input@ and \(n\) is given by @deflation@. Requires \(n > 0\).+foreign import ccall "fq_poly.h fq_poly_deflate"+ fq_poly_deflate :: Ptr CFqPoly -> Ptr CFqPoly -> CULong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_deflation/ /input/ /ctx/ +--+-- Returns the largest integer by which @input@ can be deflated. As special+-- cases, returns 0 if @input@ is the zero polynomial and 1 of @input@ is a+-- constant polynomial.+foreign import ccall "fq_poly.h fq_poly_deflation"+ fq_poly_deflation :: Ptr CFqPoly -> Ptr CFqCtx -> IO CULong
+ src/Data/Number/Flint/Fq/Poly/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fq.Poly.Factor (+ module Data.Number.Flint.Fq.Poly.Factor.FFI+ ) where++import Data.Number.Flint.Fq.Poly.Factor.FFI
+ src/Data/Number/Flint/Fq/Poly/Factor/FFI.hsc view
@@ -0,0 +1,388 @@+{-|+module : Data.Number.Flint.Fq.Poly.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Poly.Factor.FFI (+ -- * Factorisation of univariate polynomials over finite fields+ FqPolyFactor (..)+ , CFqPolyFactor (..)+ , newFqPolyFactor+ , withFqPolyFactor+ , withNewFqPolyFactor+ -- * Memory Management+ , fq_poly_factor_init+ , fq_poly_factor_clear+ , fq_poly_factor_realloc+ , fq_poly_factor_fit_length+ -- * Basic Operations+ , fq_poly_factor_set+ , fq_poly_factor_print_pretty+ , fq_poly_factor_print+ , fq_poly_factor_insert+ , fq_poly_factor_concat+ , fq_poly_factor_pow+ , fq_poly_remove+ -- * Irreducibility Testing+ , fq_poly_is_irreducible+ , fq_poly_is_irreducible_ddf+ , fq_poly_is_irreducible_ben_or+ , _fq_poly_is_squarefree+ , fq_poly_is_squarefree+ -- * Factorisation+ , fq_poly_factor_equal_deg_prob+ , fq_poly_factor_equal_deg+ , fq_poly_factor_split_single+ , fq_poly_factor_distinct_deg+ , fq_poly_factor_squarefree+ , fq_poly_factor+ , fq_poly_factor_cantor_zassenhaus+ , fq_poly_factor_kaltofen_shoup+ , fq_poly_factor_berlekamp+ , fq_poly_factor_with_berlekamp+ , fq_poly_factor_with_cantor_zassenhaus+ , fq_poly_factor_with_kaltofen_shoup+ , fq_poly_iterated_frobenius_preinv+ -- * Root Finding+ , fq_poly_roots+) where ++-- Factorisation of univariate polynomials over finite fields ------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mod.Poly+import Data.Number.Flint.Fmpz.Mod.Mat+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.Poly++#include <flint/flint.h>++#include <flint/fmpz.h>+#include <flint/fmpz_poly.h>++#include <flint/fq.h>+#include <flint/fq_poly.h>++-- fq_poly_factor_t ------------------------------------------------------------++data FqPolyFactor = FqPolyFactor {-# UNPACK #-} !(ForeignPtr CFqPolyFactor)+data CFqPolyFactor = CFqPolyFactor (Ptr CFqPoly) (Ptr CLong) CLong CLong++instance Storable CFqPolyFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_poly_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_poly_factor_t}+ peek ptr = do+ poly <- #{peek fq_poly_factor_struct, poly } ptr+ exp <- #{peek fq_poly_factor_struct, exp } ptr+ num <- #{peek fq_poly_factor_struct, num } ptr+ alloc <- #{peek fq_poly_factor_struct, alloc } ptr+ return $ CFqPolyFactor poly exp num alloc+ poke = undefined++newFqPolyFactor ctx@(FqCtx fctx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqCtx ctx $ \ctx -> do+ fq_poly_factor_init x ctx+ addForeignPtrFinalizerEnv p_fq_poly_factor_clear x fctx+ return $ FqPolyFactor x++{-# INLINE withFqPolyFactor #-}+withFqPolyFactor (FqPolyFactor x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqPolyFactor x,)++{-# INLINE withNewFqPolyFactor #-}+withNewFqPolyFactor ctx f = do+ x <- newFqPolyFactor ctx+ withFqPolyFactor x f+ +-- Memory Management -----------------------------------------------------------++-- | /fq_poly_factor_init/ /fac/ /ctx/ +--+-- Initialises @fac@ for use. An @fq_poly_factor_t@ represents a polynomial+-- in factorised form as a product of polynomials with associated+-- exponents.+foreign import ccall "fq_poly_factor.h fq_poly_factor_init"+ fq_poly_factor_init :: Ptr CFqPolyFactor -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_clear/ /fac/ /ctx/ +--+-- Frees all memory associated with @fac@.+foreign import ccall "fq_poly_factor.h fq_poly_factor_clear"+ fq_poly_factor_clear :: Ptr CFqPolyFactor -> Ptr CFqCtx -> IO ()++foreign import ccall "fq_poly_factor.h &fq_poly_factor_clear"+ p_fq_poly_factor_clear :: FunPtr (Ptr CFqPolyFactor -> Ptr CFqCtx -> IO ())++-- | /fq_poly_factor_realloc/ /fac/ /alloc/ /ctx/ +--+-- Reallocates the factor structure to provide space for precisely @alloc@+-- factors.+foreign import ccall "fq_poly_factor.h fq_poly_factor_realloc"+ fq_poly_factor_realloc :: Ptr CFqPolyFactor -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_fit_length/ /fac/ /len/ /ctx/ +--+-- Ensures that the factor structure has space for at least @len@ factors.+-- This function takes care of the case of repeated calls by always at+-- least doubling the number of factors the structure can hold.+foreign import ccall "fq_poly_factor.h fq_poly_factor_fit_length"+ fq_poly_factor_fit_length :: Ptr CFqPolyFactor -> CLong -> Ptr CFqCtx -> IO ()++-- Basic Operations ------------------------------------------------------------++-- | /fq_poly_factor_set/ /res/ /fac/ /ctx/ +--+-- Sets @res@ to the same factorisation as @fac@.+foreign import ccall "fq_poly_factor.h fq_poly_factor_set"+ fq_poly_factor_set :: Ptr CFqPolyFactor -> Ptr CFqPolyFactor -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_print_pretty/ /fac/ /var/ /ctx/ +-- +-- Pretty-prints the entries of @fac@ to standard output.+fq_poly_factor_print_pretty fac var ctx = do+ CFqPolyFactor poly exp num alloc <- peek fac+ forM_ [0..fromIntegral num-1] $ \j -> do+ fq_poly_print_pretty (poly `advancePtr` j) var ctx+ m <- peek (exp `advancePtr` j)+ putStrLn $ " ^ " ++ show m+ +-- | /fq_poly_factor_print/ /fac/ /ctx/ +-- +-- Prints the entries of @fac@ to standard output.+fq_poly_factor_print fac ctx = do+ CFqPolyFactor poly exp num alloc <- peek fac+ forM_ [0..fromIntegral num-1] $ \j -> do+ fq_poly_print (poly `advancePtr` j) ctx+ m <- peek (exp `advancePtr` j)+ putStrLn $ " ^ " ++ show m++-- | /fq_poly_factor_insert/ /fac/ /poly/ /exp/ /ctx/ +--+-- Inserts the factor @poly@ with multiplicity @exp@ into the factorisation+-- @fac@.+-- +-- If @fac@ already contains @poly@, then @exp@ simply gets added to the+-- exponent of the existing entry.+foreign import ccall "fq_poly_factor.h fq_poly_factor_insert"+ fq_poly_factor_insert :: Ptr CFqPolyFactor -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_concat/ /res/ /fac/ /ctx/ +--+-- Concatenates two factorisations.+-- +-- This is equivalent to calling @fq_poly_factor_insert@ repeatedly with+-- the individual factors of @fac@.+-- +-- Does not support aliasing between @res@ and @fac@.+foreign import ccall "fq_poly_factor.h fq_poly_factor_concat"+ fq_poly_factor_concat :: Ptr CFqPolyFactor -> Ptr CFqPolyFactor -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_pow/ /fac/ /exp/ /ctx/ +--+-- Raises @fac@ to the power @exp@.+foreign import ccall "fq_poly_factor.h fq_poly_factor_pow"+ fq_poly_factor_pow :: Ptr CFqPolyFactor -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_remove/ /f/ /p/ /ctx/ +--+-- Removes the highest possible power of @p@ from @f@ and returns the+-- exponent.+foreign import ccall "fq_poly_factor.h fq_poly_remove"+ fq_poly_remove :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO CULong++-- Irreducibility Testing ------------------------------------------------------++-- | /fq_poly_is_irreducible/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+foreign import ccall "fq_poly_factor.h fq_poly_is_irreducible"+ fq_poly_is_irreducible :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_is_irreducible_ddf/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+-- Uses fast distinct-degree factorisation.+foreign import ccall "fq_poly_factor.h fq_poly_is_irreducible_ddf"+ fq_poly_is_irreducible_ddf :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_is_irreducible_ben_or/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+-- Uses Ben-Or\'s irreducibility test.+foreign import ccall "fq_poly_factor.h fq_poly_is_irreducible_ben_or"+ fq_poly_is_irreducible_ben_or :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt++-- | /_fq_poly_is_squarefree/ /f/ /len/ /ctx/ +--+-- Returns 1 if @(f, len)@ is squarefree, and 0 otherwise. As a special+-- case, the zero polynomial is not considered squarefree. There are no+-- restrictions on the length.+foreign import ccall "fq_poly_factor.h _fq_poly_is_squarefree"+ _fq_poly_is_squarefree :: Ptr (Ptr CFq) -> CLong -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_is_squarefree/ /f/ /ctx/ +--+-- Returns 1 if @f@ is squarefree, and 0 otherwise. As a special case, the+-- zero polynomial is not considered squarefree.+foreign import ccall "fq_poly_factor.h fq_poly_is_squarefree"+ fq_poly_is_squarefree :: Ptr CFqPoly -> Ptr CFqCtx -> IO CInt++-- Factorisation ---------------------------------------------------------------++-- | /fq_poly_factor_equal_deg_prob/ /factor/ /state/ /pol/ /d/ /ctx/ +--+-- Probabilistic equal degree factorisation of @pol@ into irreducible+-- factors of degree @d@. If it passes, a factor is placed in factor and 1+-- is returned, otherwise 0 is returned and the value of factor is+-- undetermined.+-- +-- Requires that @pol@ be monic, non-constant and squarefree.+foreign import ccall "fq_poly_factor.h fq_poly_factor_equal_deg_prob"+ fq_poly_factor_equal_deg_prob :: Ptr CFqPoly -> Ptr CFRandState -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO CInt++-- | /fq_poly_factor_equal_deg/ /factors/ /pol/ /d/ /ctx/ +--+-- Assuming @pol@ is a product of irreducible factors all of degree @d@,+-- finds all those factors and places them in factors. Requires that @pol@+-- be monic, non-constant and squarefree.+foreign import ccall "fq_poly_factor.h fq_poly_factor_equal_deg"+ fq_poly_factor_equal_deg :: Ptr CFqPolyFactor -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_split_single/ /linfactor/ /input/ /ctx/ +--+-- Assuming @input@ is a product of factors all of degree 1, finds a single+-- linear factor of @input@ and places it in @linfactor@. Requires that+-- @input@ be monic and non-constant.+foreign import ccall "fq_poly_factor.h fq_poly_factor_split_single"+ fq_poly_factor_split_single :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_distinct_deg/ /res/ /poly/ /degs/ /ctx/ +--+-- Factorises a monic non-constant squarefree polynomial @poly@ of degree+-- \(n\) into factors \(f[d]\) such that for \(1 \leq d \leq n\) \(f[d]\)+-- is the product of the monic irreducible factors of @poly@ of degree+-- \(d\). Factors are stored in @res@, associated powers of irreducible+-- polynomials are stored in @degs@ in the same order as factors.+-- +-- Requires that @degs@ have enough space for irreducible polynomials\'+-- powers (maximum space required is @n * sizeof(slong)@).+foreign import ccall "fq_poly_factor.h fq_poly_factor_distinct_deg"+ fq_poly_factor_distinct_deg :: Ptr CFqPolyFactor -> Ptr CFqPoly -> Ptr (Ptr CLong) -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_squarefree/ /res/ /f/ /ctx/ +--+-- Sets @res@ to a squarefree factorization of @f@.+foreign import ccall "fq_poly_factor.h fq_poly_factor_squarefree"+ fq_poly_factor_squarefree :: Ptr CFqPolyFactor -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor/ /res/ /lead/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- choosing the best algorithm for given modulo and degree. The output+-- @lead@ is set to the leading coefficient of \(f\) upon return. Choice of+-- algorithm is based on heuristic measurements.+foreign import ccall "fq_poly_factor.h fq_poly_factor"+ fq_poly_factor :: Ptr CFqPolyFactor -> Ptr CFq -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_cantor_zassenhaus/ /res/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the Cantor-Zassenhaus algorithm.+foreign import ccall "fq_poly_factor.h fq_poly_factor_cantor_zassenhaus"+ fq_poly_factor_cantor_zassenhaus :: Ptr CFqPolyFactor -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_kaltofen_shoup/ /res/ /poly/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the fast version of Cantor-Zassenhaus algorithm proposed by+-- Kaltofen and Shoup (1998). More precisely this algorithm uses a “baby+-- step\/giant step” strategy for the distinct-degree factorization step.+foreign import ccall "fq_poly_factor.h fq_poly_factor_kaltofen_shoup"+ fq_poly_factor_kaltofen_shoup :: Ptr CFqPolyFactor -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_berlekamp/ /factors/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the Berlekamp algorithm.+foreign import ccall "fq_poly_factor.h fq_poly_factor_berlekamp"+ fq_poly_factor_berlekamp :: Ptr CFqPolyFactor -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_with_berlekamp/ /res/ /leading_coeff/ /f/ /ctx/ +--+-- Factorises a general polynomial @f@ into monic irreducible factors and+-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is+-- the zero polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Berlekamp factorisation on+-- all the individual square-free factors.+foreign import ccall "fq_poly_factor.h fq_poly_factor_with_berlekamp"+ fq_poly_factor_with_berlekamp :: Ptr CFqPolyFactor -> Ptr CFq -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_with_cantor_zassenhaus/ /res/ /leading_coeff/ /f/ /ctx/ +--+-- Factorises a general polynomial @f@ into monic irreducible factors and+-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is+-- the zero polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Cantor-Zassenhaus on all the+-- individual square-free factors.+foreign import ccall "fq_poly_factor.h fq_poly_factor_with_cantor_zassenhaus"+ fq_poly_factor_with_cantor_zassenhaus :: Ptr CFqPolyFactor -> Ptr CFq -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_factor_with_kaltofen_shoup/ /res/ /leading_coeff/ /f/ /ctx/ +--+-- Factorises a general polynomial @f@ into monic irreducible factors and+-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is+-- the zero polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Kaltofen-Shoup on all the+-- individual square-free factors.+foreign import ccall "fq_poly_factor.h fq_poly_factor_with_kaltofen_shoup"+ fq_poly_factor_with_kaltofen_shoup :: Ptr CFqPolyFactor -> Ptr CFq -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- | /fq_poly_iterated_frobenius_preinv/ /rop/ /n/ /v/ /vinv/ /ctx/ +--+-- Sets @rop[i]@ to be \(x^{q^i}\bmod v\) for \(0 \le i < n\).+-- +-- It is required that @vinv@ is the inverse of the reverse of @v@ mod+-- @x^lenv@.+foreign import ccall "fq_poly_factor.h fq_poly_iterated_frobenius_preinv"+ fq_poly_iterated_frobenius_preinv :: Ptr (Ptr CFqPoly) -> CLong -> Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqCtx -> IO ()++-- Root Finding ----------------------------------------------------------------++-- | /fq_poly_roots/ /r/ /f/ /with_multiplicity/ /ctx/ +--+-- Fill \(r\) with factors of the form \(x - r_i\) where the \(r_i\) are+-- the distinct roots of a nonzero \(f\) in \(F_q\). If+-- \(with\_multiplicity\) is zero, the exponent \(e_i\) of the factor+-- \(x - r_i\) is \(1\). Otherwise, it is the largest \(e_i\) such that+-- \((x-r_i)^e_i\) divides \(f\). This function throws if \(f\) is zero,+-- but is otherwise always successful.+foreign import ccall "fq_poly_factor.h fq_poly_roots"+ fq_poly_roots :: Ptr CFqPolyFactor -> Ptr CFqPoly -> CInt -> Ptr CFqCtx -> IO ()+
+ src/Data/Number/Flint/Fq/Types.hs view
@@ -0,0 +1,6 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Fq.Types (+ module Data.Number.Flint.Fq.Types.FFI+ ) where++import Data.Number.Flint.Fq.Types.FFI
+ src/Data/Number/Flint/Fq/Types/FFI.hsc view
@@ -0,0 +1,28 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+{-|+module : Data.Number.Flint.Fq.Types.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Types.FFI where++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz.Poly++data Fq = Fq {-# UNPACK #-} !(ForeignPtr CFq)+type CFq = CFmpzPoly++-- fq_poly_t -------------------------------------------------------------------++data FqPoly = FqPoly {-# UNPACK #-} !(ForeignPtr CFqPoly)+type CFqPoly = CFlint FqPoly++-- fq_mat_t --------------------------------------------------------------------++data FqMat = FqMat {-# UNPACK #-} !(ForeignPtr CFqMat)+data CFqMat = CFqMat (Ptr CFq) CLong CLong (Ptr (Ptr CFq))
+ src/Data/Number/Flint/Fq/Vec.hs view
@@ -0,0 +1,12 @@+{-| +module : Data.Number.Flint.Fq.Vec+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Fq.Vec (+ module Data.Number.Flint.Fq.Vec.FFI,+) where++import Data.Number.Flint.Fq.Vec.FFI
+ src/Data/Number/Flint/Fq/Vec/FFI.hsc view
@@ -0,0 +1,166 @@+{-|+module : Data.Number.Flint.Fq.Vec.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Vec.FFI (+ -- * Vectors over finite fields+ -- * Memory management+ _fq_vec_init+ , _fq_vec_clear+ -- * Randomisation+ , _fq_vec_randtest+ -- * Input and output+ , _fq_vec_fprint+ , _fq_vec_print+ -- * Assignment and basic manipulation+ , _fq_vec_set+ , _fq_vec_swap+ , _fq_vec_zero+ , _fq_vec_neg+ -- * Comparison+ , _fq_vec_equal+ , _fq_vec_is_zero+ -- * Addition and subtraction+ , _fq_vec_add+ , _fq_vec_sub+ -- * Scalar multiplication and division+ , _fq_vec_scalar_addmul_fq+ , _fq_vec_scalar_submul_fq+ -- * Dot products+ , _fq_vec_dot+) where ++-- Vectors over finite fields --------------------------------------------------++import Foreign.Ptr+import Foreign.C.Types++import Data.Number.Flint.Flint+import Data.Number.Flint.Fq++-- Memory management -----------------------------------------------------------++-- | /_fq_vec_init/ /len/ /ctx/ +--+-- Returns an initialised vector of @fq@\'s of given length.+foreign import ccall "fq_vec.h _fq_vec_init"+ _fq_vec_init :: CLong -> Ptr CFqCtx -> IO (Ptr CFq)++-- | /_fq_vec_clear/ /vec/ /len/ /ctx/ +--+-- Clears the entries of @(vec, len)@ and frees the space allocated for+-- @vec@.+foreign import ccall "fq_vec.h _fq_vec_clear"+ _fq_vec_clear :: Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()++-- Randomisation ---------------------------------------------------------------++-- | /_fq_vec_randtest/ /f/ /state/ /len/ /ctx/ +--+-- Sets the entries of a vector of the given length to elements of the+-- finite field.+foreign import ccall "fq_vec.h _fq_vec_randtest"+ _fq_vec_randtest :: Ptr CFq -> Ptr CFRandState -> CLong -> Ptr CFqCtx -> IO ()++-- Input and output ------------------------------------------------------------++-- | /_fq_vec_fprint/ /file/ /vec/ /len/ /ctx/ +--+-- Prints the vector of given length to the stream @file@. The format is+-- the length followed by two spaces, then a space separated list of+-- coefficients. If the length is zero, only \(0\) is printed.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_vec.h _fq_vec_fprint"+ _fq_vec_fprint :: Ptr CFile -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO CInt++-- | /_fq_vec_print/ /vec/ /len/ /ctx/ +--+-- Prints the vector of given length to @stdout@.+-- +-- For further details, see @_fq_vec_fprint()@.+foreign import ccall "fq_vec.h _fq_vec_print"+ _fq_vec_print :: Ptr CFq -> CLong -> Ptr CFqCtx -> IO CInt++-- Assignment and basic manipulation -------------------------------------------++-- | /_fq_vec_set/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Makes a copy of @(vec2, len2)@ into @vec1@.+foreign import ccall "fq_vec.h _fq_vec_set"+ _fq_vec_set :: Ptr CFq -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_vec_swap/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Swaps the elements in @(vec1, len2)@ and @(vec2, len2)@.+foreign import ccall "fq_vec.h _fq_vec_swap"+ _fq_vec_swap :: Ptr CFq -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_vec_zero/ /vec/ /len/ /ctx/ +--+-- Zeros the entries of @(vec, len)@.+foreign import ccall "fq_vec.h _fq_vec_zero"+ _fq_vec_zero :: Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_vec_neg/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Negates @(vec2, len2)@ and places it into @vec1@.+foreign import ccall "fq_vec.h _fq_vec_neg"+ _fq_vec_neg :: Ptr CFq -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /_fq_vec_equal/ /vec1/ /vec2/ /len/ /ctx/ +--+-- Compares two vectors of the given length and returns \(1\) if they are+-- equal, otherwise returns \(0\).+foreign import ccall "fq_vec.h _fq_vec_equal"+ _fq_vec_equal :: Ptr CFq -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO CInt++-- | /_fq_vec_is_zero/ /vec/ /len/ /ctx/ +--+-- Returns \(1\) if @(vec, len)@ is zero, and \(0\) otherwise.+foreign import ccall "fq_vec.h _fq_vec_is_zero"+ _fq_vec_is_zero :: Ptr CFq -> CLong -> Ptr CFqCtx -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /_fq_vec_add/ /res/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Sets @(res, len2)@ to the sum of @(vec1, len2)@ and @(vec2, len2)@.+foreign import ccall "fq_vec.h _fq_vec_add"+ _fq_vec_add :: Ptr CFq -> Ptr CFq -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_vec_sub/ /res/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Sets @(res, len2)@ to @(vec1, len2)@ minus @(vec2, len2)@.+foreign import ccall "fq_vec.h _fq_vec_sub"+ _fq_vec_sub :: Ptr CFq -> Ptr CFq -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()++-- Scalar multiplication and division ------------------------------------------++-- | /_fq_vec_scalar_addmul_fq/ /vec1/ /vec2/ /len2/ /c/ /ctx/ +--+-- Adds @(vec2, len2)@ times \(c\) to @(vec1, len2)@, where \(c\) is a+-- @fq_t@.+foreign import ccall "fq_vec.h _fq_vec_scalar_addmul_fq"+ _fq_vec_scalar_addmul_fq :: Ptr CFq -> Ptr CFq -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- | /_fq_vec_scalar_submul_fq/ /vec1/ /vec2/ /len2/ /c/ /ctx/ +--+-- Subtracts @(vec2, len2)@ times \(c\) from @(vec1, len2)@, where \(c\) is+-- a @fq_t@.+foreign import ccall "fq_vec.h _fq_vec_scalar_submul_fq"+ _fq_vec_scalar_submul_fq :: Ptr CFq -> Ptr CFq -> CLong -> Ptr CFq -> Ptr CFqCtx -> IO ()++-- Dot products ----------------------------------------------------------------++-- | /_fq_vec_dot/ /res/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Sets @res@ to the dot product of (@vec1@, @len@) and (@vec2@, @len@).+foreign import ccall "fq_vec.h _fq_vec_dot"+ _fq_vec_dot :: Ptr CFq -> Ptr CFq -> Ptr CFq -> CLong -> Ptr CFqCtx -> IO ()+
+ src/Data/Number/Flint/Fq/Zech.hs view
@@ -0,0 +1,12 @@+{-| +module : Data.Number.Flint.Fq.Zech+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Fq.Zech (+ module Data.Number.Flint.Fq.Zech.FFI,+) where++import Data.Number.Flint.Fq.Zech.FFI
+ src/Data/Number/Flint/Fq/Zech/Embed.hs view
@@ -0,0 +1,12 @@+{- | +module : Data.Number.Flint.Fq.Zech.Embed+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Fq.Zech.Embed (+ module Data.Number.Flint.Fq.Zech.Embed.FFI,+) where++import Data.Number.Flint.Fq.Zech.Embed.FFI
+ src/Data/Number/Flint/Fq/Zech/Embed/FFI.hsc view
@@ -0,0 +1,159 @@+{-|+module : Data.Number.Flint.Fq.Zech.Embed.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Zech.Embed.FFI (+ -- * Computing isomorphisms and embeddings of finite fields+ fq_zech_embed_gens+ , _fq_zech_embed_gens_naive+ , fq_zech_embed_matrices+ , fq_zech_embed_trace_matrix+ , fq_zech_embed_composition_matrix+ , fq_zech_embed_composition_matrix_sub+ , fq_zech_embed_mul_matrix+ , fq_zech_embed_mono_to_dual_matrix+ , fq_zech_embed_dual_to_mono_matrix+ , fq_zech_modulus_pow_series_inv+ , fq_zech_modulus_derivative_inv+) where++-- Computing isomorphisms and embeddings of finite fields ----------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types++import Data.Number.Flint.Flint++import Data.Number.Flint.NMod.Mat+import Data.Number.Flint.NMod.Poly++import Data.Number.Flint.Fq.Zech+import Data.Number.Flint.Fq.Zech.Types++--------------------------------------------------------------------------------++-- | /fq_zech_embed_gens/ /gen_sub/ /gen_sup/ /minpoly/ /sub_ctx/ /sup_ctx/ +--+-- Given two contexts @sub_ctx@ and @sup_ctx@, such that @degree(sub_ctx)@+-- divides @degree(sup_ctx)@, compute:+-- +-- - an element @gen_sub@ in @sub_ctx@ such that @gen_sub@ generates the+-- finite field defined by @sub_ctx@,+-- - its minimal polynomial @minpoly@,+-- - a root @gen_sup@ of @minpoly@ inside the field defined by @sup_ctx@.+-- +-- These data uniquely define an embedding of @sub_ctx@ into @sup_ctx@.+foreign import ccall "fq_zech_embed.h fq_zech_embed_gens"+ fq_zech_embed_gens :: Ptr CFqZech -> Ptr CFqZech -> Ptr CNModPoly -> Ptr CFqZechCtx -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_embed_gens_naive/ /gen_sub/ /gen_sup/ /minpoly/ /sub_ctx/ /sup_ctx/ +--+-- Given two contexts @sub_ctx@ and @sup_ctx@, such that @degree(sub_ctx)@+-- divides @degree(sup_ctx)@, compute an embedding of @sub_ctx@ into+-- @sup_ctx@ defined as follows:+-- +-- - @gen_sub@ is the canonical generator of @sup_ctx@ (i.e., the class+-- of \(X\)),+-- - @minpoly@ is the defining polynomial of @sub_ctx@,+-- - @gen_sup@ is a root of @minpoly@ inside the field defined by+-- @sup_ctx@.+foreign import ccall "fq_zech_embed.h _fq_zech_embed_gens_naive"+ _fq_zech_embed_gens_naive :: Ptr CFqZech -> Ptr CFqZech -> Ptr CNModPoly -> Ptr CFqZechCtx -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_embed_matrices/ /embed/ /project/ /gen_sub/ /sub_ctx/ /gen_sup/ /sup_ctx/ /gen_minpoly/ +--+-- Given:+-- +-- - two contexts @sub_ctx@ and @sup_ctx@, of respective degrees \(m\)+-- and \(n\), such that \(m\) divides \(n\);+-- - a generator @gen_sub@ of @sub_ctx@, its minimal polynomial+-- @gen_minpoly@, and a root @gen_sup@ of @gen_minpoly@ in @sup_ctx@,+-- as returned by @fq_zech_embed_gens@;+-- +-- Compute:+-- +-- - the \(n\times m\) matrix @embed@ mapping @gen_sub@ to @gen_sup@, and+-- all their powers accordingly;+-- - an \(m\times n\) matrix @project@ such that @project@ \(\times\)+-- @embed@ is the \(m\times m\) identity matrix.+foreign import ccall "fq_zech_embed.h fq_zech_embed_matrices"+ fq_zech_embed_matrices :: Ptr CNModMat -> Ptr CNModMat -> Ptr CFqZech -> Ptr CFqZechCtx -> Ptr CFqZech -> Ptr CFqZechCtx -> Ptr CNModPoly -> IO ()++-- | /fq_zech_embed_trace_matrix/ /res/ /basis/ /sub_ctx/ /sup_ctx/ +--+-- Given:+-- +-- - two contexts @sub_ctx@ and @sup_ctx@, of degrees \(m\) and \(n\),+-- such that \(m\) divides \(n\);+-- - an \(n\times m\) matrix @basis@ that maps @sub_ctx@ to an isomorphic+-- subfield in @sup_ctx@;+-- +-- Compute the \(m\times n\) matrix of the trace from @sup_ctx@ to+-- @sub_ctx@.+-- +-- This matrix is computed as+-- +-- @embed_dual_to_mono_matrix(_, sub_ctx)@ \(\times\) @basis@t \(\times\)+-- @embed_mono_to_dual_matrix(_, sup_ctx)}@.+-- +-- __Note:__ if \(m=n\), @basis@ represents a Frobenius, and the result is+-- its inverse matrix.+foreign import ccall "fq_zech_embed.h fq_zech_embed_trace_matrix"+ fq_zech_embed_trace_matrix :: Ptr CNModMat -> Ptr CNModMat -> Ptr CFqZechCtx -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_embed_composition_matrix/ /matrix/ /gen/ /ctx/ +--+-- Compute the /composition matrix/ of @gen@.+-- +-- For an element \(a\in\mathbf{F}_{p^n}\), its composition matrix is the+-- matrix whose columns are \(a^0, a^1, \ldots, a^{n-1}\).+foreign import ccall "fq_zech_embed.h fq_zech_embed_composition_matrix"+ fq_zech_embed_composition_matrix :: Ptr CNModMat -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_embed_composition_matrix_sub/ /matrix/ /gen/ /ctx/ /trunc/ +--+-- Compute the /composition matrix/ of @gen@, truncated to @trunc@ columns.+foreign import ccall "fq_zech_embed.h fq_zech_embed_composition_matrix_sub"+ fq_zech_embed_composition_matrix_sub :: Ptr CNModMat -> Ptr CFqZech -> Ptr CFqZechCtx -> CLong -> IO ()++-- | /fq_zech_embed_mul_matrix/ /matrix/ /gen/ /ctx/ +--+-- Compute the /multiplication matrix/ of @gen@.+-- +-- For an element \(a\) in \(\mathbf{F}_{p^n}=\mathbf{F}_p[x]\), its+-- multiplication matrix is the matrix whose columns are \(a, ax,+-- \dots, ax^{n-1}\).+foreign import ccall "fq_zech_embed.h fq_zech_embed_mul_matrix"+ fq_zech_embed_mul_matrix :: Ptr CNModMat -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_embed_mono_to_dual_matrix/ /res/ /ctx/ +--+-- Compute the change of basis matrix from the monomial basis of @ctx@ to+-- its dual basis.+foreign import ccall "fq_zech_embed.h fq_zech_embed_mono_to_dual_matrix"+ fq_zech_embed_mono_to_dual_matrix :: Ptr CNModMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_embed_dual_to_mono_matrix/ /res/ /ctx/ +--+-- Compute the change of basis matrix from the dual basis of @ctx@ to its+-- monomial basis.+foreign import ccall "fq_zech_embed.h fq_zech_embed_dual_to_mono_matrix"+ fq_zech_embed_dual_to_mono_matrix :: Ptr CNModMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_modulus_pow_series_inv/ /res/ /ctx/ /trunc/ +--+-- Compute the power series inverse of the reverse of the modulus of @ctx@+-- up to \(O(x^\texttt{trunc})\).+foreign import ccall "fq_zech_embed.h fq_zech_modulus_pow_series_inv"+ fq_zech_modulus_pow_series_inv :: Ptr CNModPoly -> Ptr CFqZechCtx -> CLong -> IO ()++-- | /fq_zech_modulus_derivative_inv/ /m_prime/ /m_prime_inv/ /ctx/ +--+-- Compute the derivative @m_prime@ of the modulus of @ctx@ as an element+-- of @ctx@, and its inverse @m_prime_inv@.+foreign import ccall "fq_zech_embed.h fq_zech_modulus_derivative_inv"+ fq_zech_modulus_derivative_inv :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()+
+ src/Data/Number/Flint/Fq/Zech/FFI.hsc view
@@ -0,0 +1,894 @@+{-|+module : Data.Number.Flint.Fq.Zech.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Zech.FFI (+ -- * Finite fields (Zech logarithm representation)+ FqZech (..)+ , CFqZech (..)+ , newFqZech+ , withFqZech+ -- * Context+ , FqZechCtx (..)+ , CFqZechCtx (..)+ -- ** create new context+ , newFqZechCtx+ , newFqZechCtxConway+ , newFqZechCtxRandom+ , newFqZechCtxModulus+ , newFqZechCtxModulusCheck+ , newFqZechCtxFqNModCtx+ , newFqZechCtxFqNModCtxCheck+ -- * work with context+ , withFqZechCtx+ -- * Context Management+ , fq_zech_ctx_init+ , _fq_zech_ctx_init_conway+ , fq_zech_ctx_init_conway+ , fq_zech_ctx_init_random+ , fq_zech_ctx_init_modulus+ , fq_zech_ctx_init_modulus_check+ , fq_zech_ctx_init_fq_nmod_ctx+ , fq_zech_ctx_init_fq_nmod_ctx_check+ , fq_zech_ctx_clear+ , fq_zech_ctx_modulus+ , fq_zech_ctx_degree+ --, fq_zech_ctx_prime+ , fq_zech_ctx_order+ , fq_zech_ctx_order_ui+ , fq_zech_ctx_get_str+ , fq_zech_ctx_fprint+ , fq_zech_ctx_print+ , fq_zech_ctx_randtest+ , fq_zech_ctx_randtest_reducible+ -- * Memory management+ , fq_zech_init+ , fq_zech_init2+ , fq_zech_clear+ --, _fq_zech_sparse_reduce+ --, _fq_zech_dense_reduce+ --, _fq_zech_reduce+ , fq_zech_reduce+ -- * Basic arithmetic+ , fq_zech_add+ , fq_zech_sub+ , fq_zech_sub_one+ , fq_zech_neg+ , fq_zech_mul+ , fq_zech_mul_fmpz+ , fq_zech_mul_si+ , fq_zech_mul_ui+ , fq_zech_sqr+ , fq_zech_div+ --, _fq_zech_inv+ , fq_zech_inv+ , fq_zech_gcdinv+ --, _fq_zech_pow+ , fq_zech_pow+ , fq_zech_pow_ui+ -- * Roots+ , fq_zech_sqrt+ , fq_zech_pth_root+ , fq_zech_is_square+ -- * Output+ , fq_zech_fprint_pretty+ , fq_zech_print_pretty+ , fq_zech_fprint+ , fq_zech_print+ , fq_zech_get_str+ , fq_zech_get_str_pretty+ -- * Randomisation+ , fq_zech_randtest+ , fq_zech_randtest_not_zero+ --, fq_zech_randtest_dense+ , fq_zech_rand+ , fq_zech_rand_not_zero+ -- * Assignments and conversions+ , fq_zech_set+ , fq_zech_set_si+ , fq_zech_set_ui+ , fq_zech_set_fmpz+ , fq_zech_swap+ , fq_zech_zero+ , fq_zech_one+ , fq_zech_gen+ , fq_zech_get_fmpz+ , fq_zech_get_fq_nmod+ , fq_zech_set_fq_nmod+ , fq_zech_get_nmod_poly+ , fq_zech_set_nmod_poly+ , fq_zech_get_nmod_mat+ , fq_zech_set_nmod_mat+ -- * Comparison+ , fq_zech_is_zero+ , fq_zech_is_one+ , fq_zech_equal+ , fq_zech_is_invertible+ , fq_zech_is_invertible_f+ -- * Special functions+ , fq_zech_trace+ , fq_zech_norm+ , fq_zech_frobenius+ , fq_zech_multiplicative_order+ -- , fq_zech_is_primitive+ -- * Bit packing+ , fq_zech_bit_pack+ , fq_zech_bit_unpack+) where++-- Finite fields (Zech logarithm representation) -------------------------------++-- finite fields (Zech logarithm representation) -------------------------------++import Foreign.C.String+import Foreign.C.Types++import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.ForeignPtr+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.NMod.Mat+import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Mat+import Data.Number.Flint.Fq.Zech.Types++#include <flint/flint.h>+#include <flint/fq_zech.h>++-- fq_zech_t -------------------------------------------------------------------++instance Storable CFqZech where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_zech_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_zech_t}+ peek = undefined+ poke = undefined++newFqZech ctx@(FqZechCtx ftx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqZechCtx ctx $ \ctx -> do+ fq_zech_init x ctx+ addForeignPtrFinalizerEnv p_fq_zech_clear x ftx+ return $ FqZech x++{-# INLINE withFqZech #-}+withFqZech (FqZech x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqZech x,)++-- fq_zech_ctx_t ---------------------------------------------------------------++instance Storable CFqZechCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_zech_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_zech_ctx_t}+ peek = undefined+ poke = undefined++_newFqZechCtx f p d var = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFmpz p $ \p -> + withCString var $ \var -> do+ f x p d var+ addForeignPtrFinalizer p_fq_zech_ctx_clear x+ return $ FqZechCtx x++newFqZechCtx = _newFqZechCtx fq_zech_ctx_init+newFqZechCtxConway = _newFqZechCtx fq_zech_ctx_init_conway+newFqZechCtxRandom = _newFqZechCtx fq_zech_ctx_init_random++newFqZechCtxModulus f modulus var = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withNModPoly modulus $ \modulus -> + withCString var $ \var -> + fq_zech_ctx_init_modulus x modulus var+ addForeignPtrFinalizer p_fq_zech_ctx_clear x+ return $ FqZechCtx x++newFqZechCtxModulusCheck f modulus var = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withNModPoly modulus $ \modulus -> + withCString var $ \var -> + fq_zech_ctx_init_modulus_check x modulus var+ addForeignPtrFinalizer p_fq_zech_ctx_clear x+ return $ FqZechCtx x++newFqZechCtxFqNModCtx f ctxn = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFqNModCtx ctxn $ \ctxn -> + fq_zech_ctx_init_fq_nmod_ctx x ctxn+ addForeignPtrFinalizer p_fq_zech_ctx_clear x+ return $ FqZechCtx x++newFqZechCtxFqNModCtxCheck f ctxn = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFqNModCtx ctxn $ \ctxn -> + fq_zech_ctx_init_fq_nmod_ctx_check x ctxn+ addForeignPtrFinalizer p_fq_zech_ctx_clear x+ return $ FqZechCtx x++newFqZechCtxFqCtxModulusCheck f ctxn = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFqNModCtx ctxn $ \ctxn -> + fq_zech_ctx_init_fq_nmod_ctx_check x ctxn+ addForeignPtrFinalizer p_fq_zech_ctx_clear x+ return $ FqZechCtx x++{-# INLINE withFqZechCtx #-}+withFqZechCtx (FqZechCtx x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqZechCtx x,)++-- Context Management ----------------------------------------------------------++-- | /fq_zech_ctx_init/ /ctx/ /p/ /d/ /var/ +--+-- Initialises the context for prime \(p\) and extension degree \(d\), with+-- name @var@ for the generator. By default, it will try use a Conway+-- polynomial; if one is not available, a random primitive polynomial will+-- be used.+-- +-- Assumes that \(p\) is a prime and \(p^d < 2^{\mathtt{FLINT\_BITS}}\).+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq_zech.h fq_zech_ctx_init"+ fq_zech_ctx_init :: Ptr CFqZechCtx -> Ptr CFmpz -> CLong -> CString -> IO ()++-- | /_fq_zech_ctx_init_conway/ /ctx/ /p/ /d/ /var/ +--+-- Attempts to initialise the context for prime \(p\) and extension degree+-- \(d\), with name @var@ for the generator using a Conway polynomial for+-- the modulus.+-- +-- Returns \(1\) if the Conway polynomial is in the database for the given+-- size and the initialization is successful; otherwise, returns \(0\).+-- +-- Assumes that \(p\) is a prime and \(p^d < 2^\mathtt{FLINT\_BITS}\).+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq_zech.h _fq_zech_ctx_init_conway"+ _fq_zech_ctx_init_conway :: Ptr CFqZechCtx -> Ptr CFmpz -> CLong -> CString -> IO CInt++-- | /fq_zech_ctx_init_conway/ /ctx/ /p/ /d/ /var/ +--+-- Initialises the context for prime \(p\) and extension degree \(d\), with+-- name @var@ for the generator using a Conway polynomial for the modulus.+-- +-- Assumes that \(p\) is a prime and \(p^d < 2^\mathtt{FLINT\_BITS}\).+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq_zech.h fq_zech_ctx_init_conway"+ fq_zech_ctx_init_conway :: Ptr CFqZechCtx -> Ptr CFmpz -> CLong -> CString -> IO ()++-- | /fq_zech_ctx_init_random/ /ctx/ /p/ /d/ /var/ +--+-- Initialises the context for prime \(p\) and extension degree \(d\), with+-- name @var@ for the generator using a random primitive polynomial.+-- +-- Assumes that \(p\) is a prime and \(p^d < 2^\mathtt{FLINT\_BITS}\).+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq_zech.h fq_zech_ctx_init_random"+ fq_zech_ctx_init_random :: Ptr CFqZechCtx -> Ptr CFmpz -> CLong -> CString -> IO ()++-- | /fq_zech_ctx_init_modulus/ /ctx/ /modulus/ /var/ +--+-- Initialises the context for given @modulus@ with name @var@ for the+-- generator.+-- +-- Assumes that @modulus@ is an primitive polynomial over+-- \(\mathbf{F}_{p}\). An exception is raised if a non-primitive modulus is+-- detected.+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+foreign import ccall "fq_zech.h fq_zech_ctx_init_modulus"+ fq_zech_ctx_init_modulus :: Ptr CFqZechCtx -> Ptr CNModPoly -> CString -> IO ()++-- | /fq_zech_ctx_init_modulus_check/ /ctx/ /modulus/ /var/ +--+-- As per the previous function, but returns \(0\) if the modulus was not+-- primitive and \(1\) if the context was successfully initialised with the+-- given modulus. No exception is raised.+foreign import ccall "fq_zech.h fq_zech_ctx_init_modulus_check"+ fq_zech_ctx_init_modulus_check :: Ptr CFqZechCtx -> Ptr CNModPoly -> CString -> IO CInt++-- | /fq_zech_ctx_init_fq_nmod_ctx/ /ctx/ /ctxn/ +--+-- Initializes the context @ctx@ to be the Zech representation for the+-- finite field given by @ctxn@.+foreign import ccall "fq_zech.h fq_zech_ctx_init_fq_nmod_ctx"+ fq_zech_ctx_init_fq_nmod_ctx :: Ptr CFqZechCtx -> Ptr CFqNModCtx -> IO ()++-- | /fq_zech_ctx_init_fq_nmod_ctx_check/ /ctx/ /ctxn/ +--+-- As per the previous function but returns \(0\) if a non-primitive+-- modulus is detected. Returns \(0\) if the Zech representation was+-- successfully initialised.+foreign import ccall "fq_zech.h fq_zech_ctx_init_fq_nmod_ctx_check"+ fq_zech_ctx_init_fq_nmod_ctx_check :: Ptr CFqZechCtx -> Ptr CFqNModCtx -> IO CInt++-- | /fq_zech_ctx_clear/ /ctx/ +--+-- Clears all memory that has been allocated as part of the context.+foreign import ccall "fq_zech.h fq_zech_ctx_clear"+ fq_zech_ctx_clear :: Ptr CFqZechCtx -> IO ()++foreign import ccall "fq_zech.h &fq_zech_ctx_clear"+ p_fq_zech_ctx_clear :: FunPtr (Ptr CFqZechCtx -> IO ())++-- | /fq_zech_ctx_modulus/ /ctx/ +--+-- Returns a pointer to the modulus in the context.+foreign import ccall "fq_zech.h fq_zech_ctx_modulus"+ fq_zech_ctx_modulus :: Ptr CFqZechCtx -> IO (Ptr (Ptr CNModPoly))++-- | /fq_zech_ctx_degree/ /ctx/ +--+-- Returns the degree of the field extension+-- \([\mathbf{F}_{q} : \mathbf{F}_{p}]\), which is equal to \(\log_{p} q\).+foreign import ccall "fq_zech.h fq_zech_ctx_degree"+ fq_zech_ctx_degree :: Ptr CFqZechCtx -> IO CLong++-- -- | /fq_zech_ctx_prime/ /ctx/ +-- --+-- -- Returns a pointer to the prime \(p\) in the context.+-- foreign import ccall "fq_zech.h fq_zech_ctx_prime"+-- fq_zech_ctx_prime :: Ptr CFqZechCtx -> IO (Ptr CFmpz)++-- | /fq_zech_ctx_order/ /f/ /ctx/ +--+-- Sets \(f\) to be the size of the finite field.+foreign import ccall "fq_zech.h fq_zech_ctx_order"+ fq_zech_ctx_order :: Ptr CFmpz -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_ctx_order_ui/ /ctx/ +--+-- Returns the size of the finite field.+foreign import ccall "fq_zech.h fq_zech_ctx_order_ui"+ fq_zech_ctx_order_ui :: Ptr CFqZechCtx -> IO CMpLimb++foreign import ccall "fq_zech.h fq_zech_ctx_get_str"+ fq_zech_ctx_get_str :: Ptr CFqZechCtx -> IO CString++-- | /fq_zech_ctx_fprint/ /file/ /ctx/ +--+-- Prints the context information to {tt{file}}. Returns 1 for a success+-- and a negative number for an error.+foreign import ccall "fq_zech.h fq_zech_ctx_fprint"+ fq_zech_ctx_fprint :: Ptr CFile -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_ctx_print/ /ctx/ +--+-- Prints the context information to {tt{stdout}}.+fq_zech_ctx_print :: Ptr CFqZechCtx -> IO ()+fq_zech_ctx_print ctx = do+ printCStr fq_zech_ctx_get_str ctx+ return ()+ +-- | /fq_zech_ctx_randtest/ /ctx/ +--+-- Initializes @ctx@ to a random finite field. Assumes that+-- @fq_zech_ctx_init@ has not been called on @ctx@ already.+foreign import ccall "fq_zech.h fq_zech_ctx_randtest"+ fq_zech_ctx_randtest :: Ptr CFqZechCtx -> IO ()++-- | /fq_zech_ctx_randtest_reducible/ /ctx/ +--+-- Since the Zech logarithm representation does not work with a+-- non-irreducible modulus, does the same as @fq_zech_ctx_randtest@.+foreign import ccall "fq_zech.h fq_zech_ctx_randtest_reducible"+ fq_zech_ctx_randtest_reducible :: Ptr CFqZechCtx -> IO ()++-- Memory management -----------------------------------------------------------++-- | /fq_zech_init/ /rop/ /ctx/ +--+-- Initialises the element @rop@, setting its value to \(0\).+foreign import ccall "fq_zech.h fq_zech_init"+ fq_zech_init :: Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_init2/ /rop/ /ctx/ +--+-- Initialises @poly@ with at least enough space for it to be an element of+-- @ctx@ and sets it to \(0\).+foreign import ccall "fq_zech.h fq_zech_init2"+ fq_zech_init2 :: Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_clear/ /rop/ /ctx/ +--+-- Clears the element @rop@.+foreign import ccall "fq_zech.h fq_zech_clear"+ fq_zech_clear :: Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++foreign import ccall "fq_zech.h &fq_zech_clear"+ p_fq_zech_clear :: FunPtr (Ptr CFqZech -> Ptr CFqZechCtx -> IO ())++-- -- | /_fq_zech_sparse_reduce/ /R/ /lenR/ /ctx/ +-- --+-- -- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of+-- -- @ctx@.+-- foreign import ccall "fq_zech.h _fq_zech_sparse_reduce"+-- _fq_zech_sparse_reduce :: Ptr CMp -> CLong -> Ptr CFqZechCtx -> IO ()++-- -- | /_fq_zech_dense_reduce/ /R/ /lenR/ /ctx/ +-- --+-- -- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of+-- -- @ctx@ using Newton division.+-- foreign import ccall "fq_zech.h _fq_zech_dense_reduce"+-- _fq_zech_dense_reduce :: Ptr CMp -> CLong -> Ptr CFqZechCtx -> IO ()++-- -- | /_fq_zech_reduce/ /r/ /lenR/ /ctx/ +-- --+-- -- Reduces @(R, lenR)@ modulo the polynomial \(f\) given by the modulus of+-- -- @ctx@. Does either sparse or dense reduction based on+-- -- @ctx->sparse_modulus@.+-- foreign import ccall "fq_zech.h _fq_zech_reduce"+-- _fq_zech_reduce :: Ptr CMp -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_reduce/ /rop/ /ctx/ +--+-- Reduces the polynomial @rop@ as an element of+-- \(\mathbf{F}_p[X] / (f(X))\).+foreign import ccall "fq_zech.h fq_zech_reduce"+ fq_zech_reduce :: Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- Basic arithmetic ------------------------------------------------------------++-- | /fq_zech_add/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the sum of @op1@ and @op2@.+foreign import ccall "fq_zech.h fq_zech_add"+ fq_zech_add :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_sub/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the difference of @op1@ and @op2@.+foreign import ccall "fq_zech.h fq_zech_sub"+ fq_zech_sub :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_sub_one/ /rop/ /op1/ /ctx/ +--+-- Sets @rop@ to the difference of @op1@ and \(1\).+foreign import ccall "fq_zech.h fq_zech_sub_one"+ fq_zech_sub_one :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_neg/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the negative of @op@.+foreign import ccall "fq_zech.h fq_zech_neg"+ fq_zech_neg :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mul/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@, reducing the output in the+-- given context.+foreign import ccall "fq_zech.h fq_zech_mul"+ fq_zech_mul :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mul_fmpz/ /rop/ /op/ /x/ /ctx/ +--+-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the+-- given context.+foreign import ccall "fq_zech.h fq_zech_mul_fmpz"+ fq_zech_mul_fmpz :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFmpz -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mul_si/ /rop/ /op/ /x/ /ctx/ +--+-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the+-- given context.+foreign import ccall "fq_zech.h fq_zech_mul_si"+ fq_zech_mul_si :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mul_ui/ /rop/ /op/ /x/ /ctx/ +--+-- Sets @rop@ to the product of @op@ and \(x\), reducing the output in the+-- given context.+foreign import ccall "fq_zech.h fq_zech_mul_ui"+ fq_zech_mul_ui :: Ptr CFqZech -> Ptr CFqZech -> CULong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_sqr/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the square of @op@, reducing the output in the given+-- context.+foreign import ccall "fq_zech.h fq_zech_sqr"+ fq_zech_sqr :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_div/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the quotient of @op1@ and @op2@, reducing the output in+-- the given context.+foreign import ccall "fq_zech.h fq_zech_div"+ fq_zech_div :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- -- | /_fq_zech_inv/ /rop/ /op/ /len/ /ctx/ +-- --+-- -- Sets @(rop, d)@ to the inverse of the non-zero element @(op, len)@.+-- foreign import ccall "fq_zech.h _fq_zech_inv"+-- _fq_zech_inv :: Ptr (Ptr CMp) -> Ptr (Ptr CMp) -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_inv/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the inverse of the non-zero element @op@.+foreign import ccall "fq_zech.h fq_zech_inv"+ fq_zech_inv :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_gcdinv/ /f/ /inv/ /op/ /ctx/ +--+-- Sets @inv@ to be the inverse of @op@ modulo the modulus of @ctx@ and+-- sets @f@ to one. Since the modulus for @ctx@ is always irreducible, @op@+-- is always invertible.+foreign import ccall "fq_zech.h fq_zech_gcdinv"+ fq_zech_gcdinv :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- -- | /_fq_zech_pow/ /rop/ /op/ /len/ /e/ /ctx/ +-- --+-- -- Sets @(rop, 2*d-1)@ to @(op,len)@ raised to the power \(e\), reduced+-- -- modulo \(f(X)\), the modulus of @ctx@.+-- -- +-- -- Assumes that \(e \geq 0\) and that @len@ is positive and at most \(d\).+-- -- +-- -- Although we require that @rop@ provides space for \(2d - 1\)+-- -- coefficients, the output will be reduced modulo \(f(X)\), which is a+-- -- polynomial of degree \(d\).+-- -- +-- -- Does not support aliasing.+-- foreign import ccall "fq_zech.h _fq_zech_pow"+-- _fq_zech_pow :: Ptr (Ptr CMp) -> Ptr (Ptr CMp) -> CLong -> Ptr CFmpz -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_pow/ /rop/ /op/ /e/ /ctx/ +--+-- Sets @rop@ the @op@ raised to the power \(e\).+-- +-- Currently assumes that \(e \geq 0\).+-- +-- Note that for any input @op@, @rop@ is set to \(1\) whenever \(e = 0\).+foreign import ccall "fq_zech.h fq_zech_pow"+ fq_zech_pow :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFmpz -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_pow_ui/ /rop/ /op/ /e/ /ctx/ +--+-- Sets @rop@ the @op@ raised to the power \(e\).+-- +-- Currently assumes that \(e \geq 0\).+-- +-- Note that for any input @op@, @rop@ is set to \(1\) whenever \(e = 0\).+foreign import ccall "fq_zech.h fq_zech_pow_ui"+ fq_zech_pow_ui :: Ptr CFqZech -> Ptr CFqZech -> CULong -> Ptr CFqZechCtx -> IO ()++-- Roots -----------------------------------------------------------------------++-- | /fq_zech_sqrt/ /rop/ /op1/ /ctx/ +--+-- Sets @rop@ to the square root of @op1@ if it is a square, and return+-- \(1\), otherwise return \(0\).+foreign import ccall "fq_zech.h fq_zech_sqrt"+ fq_zech_sqrt :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_pth_root/ /rop/ /op1/ /ctx/ +--+-- Sets @rop@ to a \(p^{th}\) root root of @op1@. Currently, this computes+-- the root by raising @op1@ to \(p^{d-1}\) where \(d\) is the degree of+-- the extension.+foreign import ccall "fq_zech.h fq_zech_pth_root"+ fq_zech_pth_root :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_is_square/ /op/ /ctx/ +--+-- Return @1@ if @op@ is a square.+foreign import ccall "fq_zech.h fq_zech_is_square"+ fq_zech_is_square :: Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- Output ----------------------------------------------------------------------++-- | /fq_zech_fprint_pretty/ /file/ /op/ /ctx/ +--+-- Prints a pretty representation of @op@ to @file@.+-- +-- In the current implementation, always returns \(1\). The return code is+-- part of the function\'s signature to allow for a later implementation to+-- return the number of characters printed or a non-positive error code.+foreign import ccall "fq_zech.h fq_zech_fprint_pretty"+ fq_zech_fprint_pretty :: Ptr CFile -> Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_print_pretty/ /op/ /ctx/ +--+-- Prints a pretty representation of @op@ to @stdout@.+-- +-- In the current implementation, always returns \(1\). The return code is+-- part of the function\'s signature to allow for a later implementation to+-- return the number of characters printed or a non-positive error code.+fq_zech_print_pretty :: Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt+fq_zech_print_pretty op ctx = do+ printCStr (\op -> fq_zech_get_str_pretty op ctx) op++-- | /fq_zech_fprint/ /file/ /op/ /ctx/ +--+-- Prints a representation of @op@ to @file@.+foreign import ccall "fq_zech.h fq_zech_fprint"+ fq_zech_fprint :: Ptr CFile -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_print/ /op/ /ctx/ +--+-- Prints a representation of @op@ to @stdout@.+fq_zech_print :: Ptr CFqZech -> Ptr CFqZechCtx -> IO ()+fq_zech_print op ctx = do+ printCStr (\op -> fq_zech_get_str op ctx) op+ return ()++-- | /fq_zech_get_str/ /op/ /ctx/ +--+-- Returns the plain FLINT string representation of the element @op@.+foreign import ccall "fq_zech.h fq_zech_get_str"+ fq_zech_get_str :: Ptr CFqZech -> Ptr CFqZechCtx -> IO CString++-- | /fq_zech_get_str_pretty/ /op/ /ctx/ +--+-- Returns a pretty representation of the element @op@ using the+-- null-terminated string @x@ as the variable name.+foreign import ccall "fq_zech.h fq_zech_get_str_pretty"+ fq_zech_get_str_pretty :: Ptr CFqZech -> Ptr CFqZechCtx -> IO CString++-- Randomisation ---------------------------------------------------------------++-- | /fq_zech_randtest/ /rop/ /state/ /ctx/ +--+-- Generates a random element of \(\mathbf{F}_q\).+foreign import ccall "fq_zech.h fq_zech_randtest"+ fq_zech_randtest :: Ptr CFqZech -> Ptr CFRandState -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_randtest_not_zero/ /rop/ /state/ /ctx/ +--+-- Generates a random non-zero element of \(\mathbf{F}_q\).+foreign import ccall "fq_zech.h fq_zech_randtest_not_zero"+ fq_zech_randtest_not_zero :: Ptr CFqZech -> Ptr CFRandState -> Ptr CFqZechCtx -> IO ()++-- -- | /fq_zech_randtest_dense/ /rop/ /state/ /ctx/ +-- --+-- -- Generates a random element of \(\mathbf{F}_q\) which has an underlying+-- -- polynomial with dense coefficients.+-- foreign import ccall "fq_zech.h fq_zech_randtest_dense"+-- fq_zech_randtest_dense :: Ptr CFqZech -> Ptr CFRandState -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_rand/ /rop/ /state/ /ctx/ +--+-- Generates a high quality random element of \(\mathbf{F}_q\).+foreign import ccall "fq_zech.h fq_zech_rand"+ fq_zech_rand :: Ptr CFqZech -> Ptr CFRandState -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_rand_not_zero/ /rop/ /state/ /ctx/ +--+-- Generates a high quality non-zero random element of \(\mathbf{F}_q\).+foreign import ccall "fq_zech.h fq_zech_rand_not_zero"+ fq_zech_rand_not_zero :: Ptr CFqZech -> Ptr CFRandState -> Ptr CFqZechCtx -> IO ()++-- Assignments and conversions -------------------------------------------------++-- | /fq_zech_set/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to @op@.+foreign import ccall "fq_zech.h fq_zech_set"+ fq_zech_set :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_set_si/ /rop/ /x/ /ctx/ +--+-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).+foreign import ccall "fq_zech.h fq_zech_set_si"+ fq_zech_set_si :: Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_set_ui/ /rop/ /x/ /ctx/ +--+-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).+foreign import ccall "fq_zech.h fq_zech_set_ui"+ fq_zech_set_ui :: Ptr CFqZech -> CULong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_set_fmpz/ /rop/ /x/ /ctx/ +--+-- Sets @rop@ to @x@, considered as an element of \(\mathbf{F}_p\).+foreign import ccall "fq_zech.h fq_zech_set_fmpz"+ fq_zech_set_fmpz :: Ptr CFqZech -> Ptr CFmpz -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_swap/ /op1/ /op2/ /ctx/ +--+-- Swaps the two elements @op1@ and @op2@.+foreign import ccall "fq_zech.h fq_zech_swap"+ fq_zech_swap :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_zero/ /rop/ /ctx/ +--+-- Sets @rop@ to zero.+foreign import ccall "fq_zech.h fq_zech_zero"+ fq_zech_zero :: Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_one/ /rop/ /ctx/ +--+-- Sets @rop@ to one, reduced in the given context.+foreign import ccall "fq_zech.h fq_zech_one"+ fq_zech_one :: Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_gen/ /rop/ /ctx/ +--+-- Sets @rop@ to a generator for the finite field. There is no guarantee+-- this is a multiplicative generator of the finite field.+foreign import ccall "fq_zech.h fq_zech_gen"+ fq_zech_gen :: Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_get_fmpz/ /rop/ /op/ /ctx/ +--+-- If @op@ has a lift to the integers, return \(1\) and set @rop@ to the+-- lift in \([0,p)\). Otherwise, return \(0\) and leave \(rop\) undefined.+foreign import ccall "fq_zech.h fq_zech_get_fmpz"+ fq_zech_get_fmpz :: Ptr CFmpz -> Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_get_fq_nmod/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the @fq_nmod_t@ element corresponding to @op@.+foreign import ccall "fq_zech.h fq_zech_get_fq_nmod"+ fq_zech_get_fq_nmod :: Ptr CFqNMod -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_set_fq_nmod/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the @fq_zech_t@ element corresponding to @op@.+foreign import ccall "fq_zech.h fq_zech_set_fq_nmod"+ fq_zech_set_fq_nmod :: Ptr CFqZech -> Ptr CFqNMod -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_get_nmod_poly/ /a/ /b/ /ctx/ +--+-- Set @a@ to a representative of @b@ in @ctx@. The representatives are+-- taken in \((\mathbb{Z}/p\mathbb{Z})[x]/h(x)\) where \(h(x)\) is the+-- defining polynomial in @ctx@.+foreign import ccall "fq_zech.h fq_zech_get_nmod_poly"+ fq_zech_get_nmod_poly :: Ptr CNModPoly -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_set_nmod_poly/ /a/ /b/ /ctx/ +--+-- Set @a@ to the element in @ctx@ with representative @b@. The+-- representatives are taken in \((\mathbb{Z}/p\mathbb{Z})[x]/h(x)\) where+-- \(h(x)\) is the defining polynomial in @ctx@.+foreign import ccall "fq_zech.h fq_zech_set_nmod_poly"+ fq_zech_set_nmod_poly :: Ptr CFqZech -> Ptr CNModPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_get_nmod_mat/ /col/ /a/ /ctx/ +--+-- Convert @a@ to a column vector of length @degree(ctx)@.+foreign import ccall "fq_zech.h fq_zech_get_nmod_mat"+ fq_zech_get_nmod_mat :: Ptr CNModMat -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_set_nmod_mat/ /a/ /col/ /ctx/ +--+-- Convert a column vector @col@ of length @degree(ctx)@ to an element of+-- @ctx@.+foreign import ccall "fq_zech.h fq_zech_set_nmod_mat"+ fq_zech_set_nmod_mat :: Ptr CFqZech -> Ptr CNModMat -> Ptr CFqZechCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fq_zech_is_zero/ /op/ /ctx/ +--+-- Returns whether @op@ is equal to zero.+foreign import ccall "fq_zech.h fq_zech_is_zero"+ fq_zech_is_zero :: Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_is_one/ /op/ /ctx/ +--+-- Returns whether @op@ is equal to one.+foreign import ccall "fq_zech.h fq_zech_is_one"+ fq_zech_is_one :: Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_equal/ /op1/ /op2/ /ctx/ +--+-- Returns whether @op1@ and @op2@ are equal.+foreign import ccall "fq_zech.h fq_zech_equal"+ fq_zech_equal :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_is_invertible/ /op/ /ctx/ +--+-- Returns whether @op@ is an invertible element.+foreign import ccall "fq_zech.h fq_zech_is_invertible"+ fq_zech_is_invertible :: Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_is_invertible_f/ /f/ /op/ /ctx/ +--+-- Returns whether @op@ is an invertible element. If it is not, then @f@ is+-- set of a factor of the modulus. Since the modulus for an @fq_zech_ctx_t@+-- is always irreducible, then any non-zero @op@ will be invertible.+foreign import ccall "fq_zech.h fq_zech_is_invertible_f"+ fq_zech_is_invertible_f :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- Special functions -----------------------------------------------------------++-- | /fq_zech_trace/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the trace of @op@.+-- +-- For an element \(a \in \mathbf{F}_q\), multiplication by \(a\) defines a+-- \(\mathbf{F}_p\)-linear map on \(\mathbf{F}_q\). We define the trace of+-- \(a\) as the trace of this map. Equivalently, if \(\Sigma\) generates+-- \(\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)\) then the trace of+-- \(a\) is equal to \(\sum_{i=0}^{d-1} \Sigma^i (a)\), where \(d =+-- \log_{p} q\).+foreign import ccall "fq_zech.h fq_zech_trace"+ fq_zech_trace :: Ptr CFmpz -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_norm/ /rop/ /op/ /ctx/ +--+-- Computes the norm of @op@.+-- +-- For an element \(a \in \mathbf{F}_q\), multiplication by \(a\) defines a+-- \(\mathbf{F}_p\)-linear map on \(\mathbf{F}_q\). We define the norm of+-- \(a\) as the determinant of this map. Equivalently, if \(\Sigma\)+-- generates \(\operatorname{Gal}(\mathbf{F}_q / \mathbf{F}_p)\) then the+-- trace of \(a\) is equal to \(\prod_{i=0}^{d-1} \Sigma^i (a)\), where+-- \(d = \text{dim}_{\mathbf{F}_p}(\mathbf{F}_q)\).+-- +-- Algorithm selection is automatic depending on the input.+foreign import ccall "fq_zech.h fq_zech_norm"+ fq_zech_norm :: Ptr CFmpz -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_frobenius/ /rop/ /op/ /e/ /ctx/ +--+-- Evaluates the homomorphism \(\Sigma^e\) at @op@.+-- +-- Recall that \(\mathbf{F}_q / \mathbf{F}_p\) is Galois with Galois group+-- \(\langle \sigma \rangle\), which is also isomorphic to+-- \(\mathbf{Z}/d\mathbf{Z}\), where+-- \(\sigma \in \operatorname{Gal}(\mathbf{F}_q/\mathbf{F}_p)\) is the+-- Frobenius element \(\sigma \colon x \mapsto x^p\).+foreign import ccall "fq_zech.h fq_zech_frobenius"+ fq_zech_frobenius :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_multiplicative_order/ /ord/ /op/ /ctx/ +--+-- Computes the order of @op@ as an element of the multiplicative group of+-- @ctx@.+-- +-- Returns 0 if @op@ is 0, otherwise it returns 1 if @op@ is a generator of+-- the multiplicative group, and -1 if it is not.+-- +-- Note that @ctx@ must already correspond to a finite field defined by a+-- primitive polynomial and so this function cannot be used to check+-- primitivity of the generator, but can be used to check that other+-- elements are primitive.+foreign import ccall "fq_zech.h fq_zech_multiplicative_order"+ fq_zech_multiplicative_order :: Ptr CFmpz -> Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- -- | /fq_zech_is_primitive/ /op/ /ctx/ +-- --+-- -- Returns whether @op@ is primitive, i.e., whether it is a generator of+-- -- the multiplicative group of @ctx@.+-- foreign import ccall "fq_zech.h fq_zech_is_primitive"+-- fq_zech_is_primitive :: Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- Bit packing -----------------------------------------------------------------++-- | /fq_zech_bit_pack/ /f/ /op/ /bit_size/ /ctx/ +--+-- Packs @op@ into bitfields of size @bit_size@, writing the result to @f@.+foreign import ccall "fq_zech.h fq_zech_bit_pack"+ fq_zech_bit_pack :: Ptr CFmpz -> Ptr CFqZech -> CFBitCnt -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_bit_unpack/ /rop/ /f/ /bit_size/ /ctx/ +--+-- Unpacks into @rop@ the element with coefficients packed into fields of+-- size @bit_size@ as represented by the integer @f@.+foreign import ccall "fq_zech.h fq_zech_bit_unpack"+ fq_zech_bit_unpack :: Ptr CFqZech -> Ptr CFmpz -> CFBitCnt -> Ptr CFqZechCtx -> IO ()+
+ src/Data/Number/Flint/Fq/Zech/Mat.hs view
@@ -0,0 +1,12 @@+{- | +module : Data.Number.Flint.Fq.Zech.Mat+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Fq.Zech.Mat (+ module Data.Number.Flint.Fq.Zech.Mat.FFI,+) where++import Data.Number.Flint.Fq.Zech.Mat.FFI
+ src/Data/Number/Flint/Fq/Zech/Mat/FFI.hsc view
@@ -0,0 +1,726 @@+{-|+module : Data.Number.Flint.Fq.Zech.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Zech.Mat.FFI (+ -- * Matrices over finite fields (Zech logarithm representation)+ FqZechMat (..)+ , CFqZechMat (..)+ -- * Constructors+ , newFqZechMat+ , withFqZechMat+ -- * Memory management+ , fq_zech_mat_init+ , fq_zech_mat_init_set+ , fq_zech_mat_clear+ , fq_zech_mat_set+ -- * Basic properties and manipulation+ , fq_zech_mat_entry+ , fq_zech_mat_entry_set+ , fq_zech_mat_nrows+ , fq_zech_mat_ncols+ , fq_zech_mat_swap+ , fq_zech_mat_swap_entrywise+ , fq_zech_mat_zero+ , fq_zech_mat_one+ -- * Conversions+ , fq_zech_mat_set_nmod_mat+ , fq_zech_mat_set_fmpz_mod_mat+ -- * Concatenate+ , fq_zech_mat_concat_vertical+ , fq_zech_mat_concat_horizontal+ -- * Printing+ , fq_zech_mat_print_pretty+ , fq_zech_mat_fprint_pretty+ , fq_zech_mat_print+ , fq_zech_mat_fprint+ -- * Window+ , fq_zech_mat_window_init+ , fq_zech_mat_window_clear+ -- * Random matrix generation+ , fq_zech_mat_randtest+ , fq_zech_mat_randpermdiag+ , fq_zech_mat_randrank+ , fq_zech_mat_randops+ , fq_zech_mat_randtril+ , fq_zech_mat_randtriu+ -- * Comparison+ , fq_zech_mat_equal+ , fq_zech_mat_is_zero+ , fq_zech_mat_is_one+ , fq_zech_mat_is_empty+ , fq_zech_mat_is_square+ -- * Addition and subtraction+ , fq_zech_mat_add+ , fq_zech_mat_sub+ , fq_zech_mat_neg+ -- * Matrix multiplication+ , fq_zech_mat_mul+ , fq_zech_mat_mul_classical+ , fq_zech_mat_mul_KS+ , fq_zech_mat_submul+ , fq_zech_mat_mul_vec+ , fq_zech_mat_mul_vec_ptr+ , fq_zech_mat_vec_mul+ , fq_zech_mat_vec_mul_ptr+ -- * LU decomposition+ , fq_zech_mat_lu+ , fq_zech_mat_lu_classical+ , fq_zech_mat_lu_recursive+ -- * Reduced row echelon form+ , fq_zech_mat_rref+ , fq_zech_mat_reduce_row+ -- * Triangular solving+ , fq_zech_mat_solve_tril+ , fq_zech_mat_solve_tril_classical+ , fq_zech_mat_solve_tril_recursive+ , fq_zech_mat_solve_triu+ , fq_zech_mat_solve_triu_classical+ , fq_zech_mat_solve_triu_recursive+ -- * Solving+ , fq_zech_mat_solve+ , fq_zech_mat_can_solve+ -- * Transforms+ , fq_zech_mat_similarity+ -- * Characteristic polynomial+ , fq_zech_mat_charpoly_danilevsky+ , fq_zech_mat_charpoly+ -- * Minimal polynomial+ , fq_zech_mat_minpoly+) where ++-- Matrices over finite fields (Zech logarithm representation) -----------------++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr +import Foreign.Storable+import Foreign.Marshal+import Foreign.Marshal.Array++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mod.Mat+import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.NMod.Mat+import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Mat+import Data.Number.Flint.Fq.Zech+import Data.Number.Flint.Fq.Zech.Types++#include <flint/flint.h>+#include <flint/fq_zech.h>+#include <flint/fq_zech_mat.h>++-- fq_zech_mat_t ---------------------------------------------------------------++instance Storable CFqZechMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_zech_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_zech_mat_t}+ peek ptr = CFqZechMat+ <$> #{peek fq_zech_mat_struct, entries} ptr+ <*> #{peek fq_zech_mat_struct, r } ptr+ <*> #{peek fq_zech_mat_struct, c } ptr+ <*> #{peek fq_zech_mat_struct, rows } ptr+ poke = undefined++newFqZechMat rows cols ctx@(FqZechCtx ftx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqZechCtx ctx $ \ctx -> do+ fq_zech_mat_init x rows cols ctx+ addForeignPtrFinalizerEnv p_fq_zech_mat_clear x ftx+ return $ FqZechMat x++{-# INLINE withFqZechMat #-}+withFqZechMat (FqZechMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqZechMat x,)++-- Memory management -----------------------------------------------------------++-- | /fq_zech_mat_init/ /mat/ /rows/ /cols/ /ctx/ +--+-- Initialises @mat@ to a @rows@-by-@cols@ matrix with coefficients in+-- \(\mathbf{F}_{q}\) given by @ctx@. All elements are set to zero.+foreign import ccall "fq_zech_mat.h fq_zech_mat_init"+ fq_zech_mat_init :: Ptr CFqZechMat -> CLong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_init_set/ /mat/ /src/ /ctx/ +--+-- Initialises @mat@ and sets its dimensions and elements to those of+-- @src@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_init_set"+ fq_zech_mat_init_set :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_clear/ /mat/ /ctx/ +--+-- Clears the matrix and releases any memory it used. The matrix cannot be+-- used again until it is initialised. This function must be called exactly+-- once when finished using an @fq_zech_mat_t@ object.+foreign import ccall "fq_zech_mat.h fq_zech_mat_clear"+ fq_zech_mat_clear :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++foreign import ccall "fq_zech_mat.h &fq_zech_mat_clear"+ p_fq_zech_mat_clear :: FunPtr (Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ())++-- | /fq_zech_mat_set/ /mat/ /src/ /ctx/ +--+-- Sets @mat@ to a copy of @src@. It is assumed that @mat@ and @src@ have+-- identical dimensions.+foreign import ccall "fq_zech_mat.h fq_zech_mat_set"+ fq_zech_mat_set :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- Basic properties and manipulation -------------------------------------------++-- | /fq_zech_mat_entry/ /mat/ /i/ /j/ +--+-- Directly accesses the entry in @mat@ in row \(i\) and column \(j\),+-- indexed from zero. No bounds checking is performed.+fq_zech_mat_entry :: Ptr CFqZechMat -> CLong -> CLong -> IO (Ptr CFqZech)+fq_zech_mat_entry mat i j = do+ CFqZechMat entries r c rows <- peek mat+ return $ entries `advancePtr` (fromIntegral (i*c + j))+ +-- | /fq_zech_mat_entry_set/ /mat/ /i/ /j/ /x/ /ctx/ +--+-- Sets the entry in @mat@ in row \(i\) and column \(j\) to @x@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_entry_set"+ fq_zech_mat_entry_set :: Ptr CFqZechMat -> CLong -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_nrows/ /mat/ /ctx/ +--+-- Returns the number of rows in @mat@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_nrows"+ fq_zech_mat_nrows :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CLong++-- | /fq_zech_mat_ncols/ /mat/ /ctx/ +--+-- Returns the number of columns in @mat@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_ncols"+ fq_zech_mat_ncols :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CLong++-- | /fq_zech_mat_swap/ /mat1/ /mat2/ /ctx/ +--+-- Swaps two matrices. The dimensions of @mat1@ and @mat2@ are allowed to+-- be different.+foreign import ccall "fq_zech_mat.h fq_zech_mat_swap"+ fq_zech_mat_swap :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_swap_entrywise/ /mat1/ /mat2/ +--+-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "fq_zech_mat.h fq_zech_mat_swap_entrywise"+ fq_zech_mat_swap_entrywise :: Ptr CFqZechMat -> Ptr CFqZechMat -> IO ()++-- | /fq_zech_mat_zero/ /mat/ /ctx/ +--+-- Sets all entries of @mat@ to 0.+foreign import ccall "fq_zech_mat.h fq_zech_mat_zero"+ fq_zech_mat_zero :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_one/ /mat/ /ctx/ +--+-- Sets all diagonal entries of @mat@ to 1 and all other entries to 0.+foreign import ccall "fq_zech_mat.h fq_zech_mat_one"+ fq_zech_mat_one :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- Conversions -----------------------------------------------------------------++-- | /fq_zech_mat_set_nmod_mat/ /mat1/ /mat2/ /ctx/ +--+-- Sets the matrix @mat1@ to the matrix @mat2@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_set_nmod_mat"+ fq_zech_mat_set_nmod_mat :: Ptr CFqZechMat -> Ptr CNModMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_set_fmpz_mod_mat/ /mat1/ /mat2/ /ctx/ +--+-- Sets the matrix @mat1@ to the matrix @mat2@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_set_fmpz_mod_mat"+ fq_zech_mat_set_fmpz_mod_mat :: Ptr CFqZechMat -> Ptr CFmpzModMat -> Ptr CFqZechCtx -> IO ()++-- Concatenate -----------------------------------------------------------------++-- | /fq_zech_mat_concat_vertical/ /res/ /mat1/ /mat2/ /ctx/ +--+-- Sets @res@ to vertical concatenation of (@mat1@, @mat2@) in that order.+-- Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ : \(k \times n\),+-- @res@ : \((m + k) \times n\).+foreign import ccall "fq_zech_mat.h fq_zech_mat_concat_vertical"+ fq_zech_mat_concat_vertical :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_concat_horizontal/ /res/ /mat1/ /mat2/ /ctx/ +--+-- Sets @res@ to horizontal concatenation of (@mat1@, @mat2@) in that+-- order. Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ :+-- \(m \times k\), @res@ : \(m \times (n + k)\).+foreign import ccall "fq_zech_mat.h fq_zech_mat_concat_horizontal"+ fq_zech_mat_concat_horizontal :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- Printing --------------------------------------------------------------------++foreign import ccall "fq_zech_mat.h fq_zech_mat_get_str_pretty"+ fq_zech_mat_get_str_pretty :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CString++foreign import ccall "fq_zech_mat.h fq_zech_mat_get_str"+ fq_zech_mat_get_str :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CString+ +-- | /fq_zech_mat_print_pretty/ /mat/ /ctx/ +--+-- Pretty-prints @mat@ to @stdout@. A header is printed followed by the+-- rows enclosed in brackets.+fq_zech_mat_print_pretty :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()+fq_zech_mat_print_pretty mat ctx = do+ printCStr (\mat -> fq_zech_mat_get_str_pretty mat ctx) mat+ return ()+ +-- | /fq_zech_mat_fprint_pretty/ /file/ /mat/ /ctx/ +--+-- Pretty-prints @mat@ to @file@. A header is printed followed by the rows+-- enclosed in brackets.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_zech_mat.h fq_zech_mat_fprint_pretty"+ fq_zech_mat_fprint_pretty :: Ptr CFile -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_mat_print/ /mat/ /ctx/ +--+-- Prints @mat@ to @stdout@. A header is printed followed by the rows+-- enclosed in brackets.+fq_zech_mat_print :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()+fq_zech_mat_print mat ctx = do+ printCStr (\mat -> fq_zech_mat_get_str mat ctx) mat+ return ()+ +-- | /fq_zech_mat_fprint/ /file/ /mat/ /ctx/ +--+-- Prints @mat@ to @file@. A header is printed followed by the rows+-- enclosed in brackets.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_zech_mat.h fq_zech_mat_fprint"+ fq_zech_mat_fprint :: Ptr CFile -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CInt++-- Window ----------------------------------------------------------------------++-- | /fq_zech_mat_window_init/ /window/ /mat/ /r1/ /c1/ /r2/ /c2/ /ctx/ +--+-- Initializes the matrix @window@ to be an @r2 - r1@ by @c2 - c1@+-- submatrix of @mat@ whose @(0,0)@ entry is the @(r1, c1)@ entry of @mat@.+-- The memory for the elements of @window@ is shared with @mat@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_window_init"+ fq_zech_mat_window_init :: Ptr CFqZechMat -> Ptr CFqZechMat -> CLong -> CLong -> CLong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_window_clear/ /window/ /ctx/ +--+-- Clears the matrix @window@ and releases any memory that it uses. Note+-- that the memory to the underlying matrix that @window@ points to is not+-- freed.+foreign import ccall "fq_zech_mat.h fq_zech_mat_window_clear"+ fq_zech_mat_window_clear :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- Random matrix generation ----------------------------------------------------++-- | /fq_zech_mat_randtest/ /mat/ /state/ /ctx/ +--+-- Sets the elements of @mat@ to random elements of \(\mathbf{F}_{q}\),+-- given by @ctx@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_randtest"+ fq_zech_mat_randtest :: Ptr CFqZechMat -> Ptr CFRandState -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_randpermdiag/ /mat/ /state/ /diag/ /n/ /ctx/ +--+-- Sets @mat@ to a random permutation of the diagonal matrix with \(n\)+-- leading entries given by the vector @diag@. It is assumed that the main+-- diagonal of @mat@ has room for at least \(n\) entries.+-- +-- Returns \(0\) or \(1\), depending on whether the permutation is even or+-- odd respectively.+foreign import ccall "fq_zech_mat.h fq_zech_mat_randpermdiag"+ fq_zech_mat_randpermdiag :: Ptr CFqZechMat -> Ptr CFRandState -> Ptr (Ptr CFqZech) -> CLong -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_mat_randrank/ /mat/ /state/ /rank/ /ctx/ +--+-- Sets @mat@ to a random sparse matrix with the given rank, having exactly+-- as many non-zero elements as the rank, with the non-zero elements being+-- uniformly random elements of \(\mathbf{F}_{q}\).+-- +-- The matrix can be transformed into a dense matrix with unchanged rank by+-- subsequently calling @fq_zech_mat_randops@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_randrank"+ fq_zech_mat_randrank :: Ptr CFqZechMat -> Ptr CFRandState -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_randops/ /mat/ /count/ /state/ /ctx/ +--+-- Randomises @mat@ by performing elementary row or column operations. More+-- precisely, at most @count@ random additions or subtractions of distinct+-- rows and columns will be performed. This leaves the rank (and for square+-- matrices, determinant) unchanged.+foreign import ccall "fq_zech_mat.h fq_zech_mat_randops"+ fq_zech_mat_randops :: Ptr CFqZechMat -> CLong -> Ptr CFRandState -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_randtril/ /mat/ /state/ /unit/ /ctx/ +--+-- Sets @mat@ to a random lower triangular matrix. If @unit@ is 1, it will+-- have ones on the main diagonal, otherwise it will have random nonzero+-- entries on the main diagonal.+foreign import ccall "fq_zech_mat.h fq_zech_mat_randtril"+ fq_zech_mat_randtril :: Ptr CFqZechMat -> Ptr CFRandState -> CInt -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_randtriu/ /mat/ /state/ /unit/ /ctx/ +--+-- Sets @mat@ to a random upper triangular matrix. If @unit@ is 1, it will+-- have ones on the main diagonal, otherwise it will have random nonzero+-- entries on the main diagonal.+foreign import ccall "fq_zech_mat.h fq_zech_mat_randtriu"+ fq_zech_mat_randtriu :: Ptr CFqZechMat -> Ptr CFRandState -> CInt -> Ptr CFqZechCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fq_zech_mat_equal/ /mat1/ /mat2/ /ctx/ +--+-- Returns nonzero if mat1 and mat2 have the same dimensions and elements,+-- and zero otherwise.+foreign import ccall "fq_zech_mat.h fq_zech_mat_equal"+ fq_zech_mat_equal :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_mat_is_zero/ /mat/ /ctx/ +--+-- Returns a non-zero value if all entries @mat@ are zero, and otherwise+-- returns zero.+foreign import ccall "fq_zech_mat.h fq_zech_mat_is_zero"+ fq_zech_mat_is_zero :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_mat_is_one/ /mat/ /ctx/ +--+-- Returns a non-zero value if all entries @mat@ are zero except the+-- diagonal entries which must be one, otherwise returns zero.+foreign import ccall "fq_zech_mat.h fq_zech_mat_is_one"+ fq_zech_mat_is_one :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_mat_is_empty/ /mat/ /ctx/ +--+-- Returns a non-zero value if the number of rows or the number of columns+-- in @mat@ is zero, and otherwise returns zero.+foreign import ccall "fq_zech_mat.h fq_zech_mat_is_empty"+ fq_zech_mat_is_empty :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_mat_is_square/ /mat/ /ctx/ +--+-- Returns a non-zero value if the number of rows is equal to the number of+-- columns in @mat@, and otherwise returns zero.+foreign import ccall "fq_zech_mat.h fq_zech_mat_is_square"+ fq_zech_mat_is_square :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /fq_zech_mat_add/ /C/ /A/ /B/ /ctx/ +--+-- Computes \(C = A + B\). Dimensions must be identical.+foreign import ccall "fq_zech_mat.h fq_zech_mat_add"+ fq_zech_mat_add :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_sub/ /C/ /A/ /B/ /ctx/ +--+-- Computes \(C = A - B\). Dimensions must be identical.+foreign import ccall "fq_zech_mat.h fq_zech_mat_sub"+ fq_zech_mat_sub :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_neg/ /A/ /B/ /ctx/ +--+-- Sets \(B = -A\). Dimensions must be identical.+foreign import ccall "fq_zech_mat.h fq_zech_mat_neg"+ fq_zech_mat_neg :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- Matrix multiplication -------------------------------------------------------++-- | /fq_zech_mat_mul/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. \(C\) is not allowed to be aliased with \(A\) or \(B\).+-- This function automatically chooses between classical and KS+-- multiplication.+foreign import ccall "fq_zech_mat.h fq_zech_mat_mul"+ fq_zech_mat_mul :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_mul_classical/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. \(C\) is not allowed to be aliased with \(A\) or \(B\).+-- Uses classical matrix multiplication.+foreign import ccall "fq_zech_mat.h fq_zech_mat_mul_classical"+ fq_zech_mat_mul_classical :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_mul_KS/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. \(C\) is not allowed to be aliased with \(A\) or \(B\).+-- Uses Kronecker substitution to perform the multiplication over the+-- integers.+foreign import ccall "fq_zech_mat.h fq_zech_mat_mul_KS"+ fq_zech_mat_mul_KS :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_submul/ /D/ /C/ /A/ /B/ /ctx/ +--+-- Sets \(D = C + AB\). \(C\) and \(D\) may be aliased with each other but+-- not with \(A\) or \(B\).+foreign import ccall "fq_zech_mat.h fq_zech_mat_submul"+ fq_zech_mat_submul :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_mul_vec/ /c/ /A/ /b/ /blen/ +foreign import ccall "fq_zech_mat.h fq_zech_mat_mul_vec"+ fq_zech_mat_mul_vec :: Ptr (Ptr CFqZech) -> Ptr CFqZechMat -> Ptr (Ptr CFqZech) -> CLong -> IO ()+-- | /fq_zech_mat_mul_vec_ptr/ /c/ /A/ /b/ /blen/ +--+-- Compute a matrix-vector product of @A@ and @(b, blen)@ and store the+-- result in @c@. The vector @(b, blen)@ is either truncated or+-- zero-extended to the number of columns of @A@. The number entries+-- written to @c@ is always equal to the number of rows of @A@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_mul_vec_ptr"+ fq_zech_mat_mul_vec_ptr :: Ptr (Ptr (Ptr CFqZech)) -> Ptr CFqZechMat -> Ptr (Ptr (Ptr CFqZech)) -> CLong -> IO ()++-- | /fq_zech_mat_vec_mul/ /c/ /a/ /alen/ /B/ +foreign import ccall "fq_zech_mat.h fq_zech_mat_vec_mul"+ fq_zech_mat_vec_mul :: Ptr (Ptr CFqZech) -> Ptr (Ptr CFqZech) -> CLong -> Ptr CFqZechMat -> IO ()+-- | /fq_zech_mat_vec_mul_ptr/ /c/ /a/ /alen/ /B/ +--+-- Compute a vector-matrix product of @(a, alen)@ and @B@ and and store the+-- result in @c@. The vector @(a, alen)@ is either truncated or+-- zero-extended to the number of rows of @B@. The number entries written+-- to @c@ is always equal to the number of columns of @B@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_vec_mul_ptr"+ fq_zech_mat_vec_mul_ptr :: Ptr (Ptr (Ptr CFqZech)) -> Ptr (Ptr (Ptr CFqZech)) -> CLong -> Ptr CFqZechMat -> IO ()++-- LU decomposition ------------------------------------------------------------++-- | /fq_zech_mat_lu/ /P/ /A/ /rank_check/ /ctx/ +--+-- Computes a generalised LU decomposition \(LU = PA\) of a given matrix+-- \(A\), returning the rank of \(A\).+-- +-- If \(A\) is a nonsingular square matrix, it will be overwritten with a+-- unit diagonal lower triangular matrix \(L\) and an upper triangular+-- matrix \(U\) (the diagonal of \(L\) will not be stored explicitly).+-- +-- If \(A\) is an arbitrary matrix of rank \(r\), \(U\) will be in row+-- echelon form having \(r\) nonzero rows, and \(L\) will be lower+-- triangular but truncated to \(r\) columns, having implicit ones on the+-- \(r\) first entries of the main diagonal. All other entries will be+-- zero.+-- +-- If a nonzero value for @rank_check@ is passed, the function will abandon+-- the output matrix in an undefined state and return 0 if \(A\) is+-- detected to be rank-deficient.+-- +-- This function calls @fq_zech_mat_lu_recursive@.+foreign import ccall "fq_zech_mat.h fq_zech_mat_lu"+ fq_zech_mat_lu :: Ptr CLong -> Ptr CFqZechMat -> CInt -> Ptr CFqZechCtx -> IO CLong++-- | /fq_zech_mat_lu_classical/ /P/ /A/ /rank_check/ /ctx/ +--+-- Computes a generalised LU decomposition \(LU = PA\) of a given matrix+-- \(A\), returning the rank of \(A\). The behavior of this function is+-- identical to that of @fq_zech_mat_lu@. Uses Gaussian elimination.+foreign import ccall "fq_zech_mat.h fq_zech_mat_lu_classical"+ fq_zech_mat_lu_classical :: Ptr CLong -> Ptr CFqZechMat -> CInt -> Ptr CFqZechCtx -> IO CLong++-- | /fq_zech_mat_lu_recursive/ /P/ /A/ /rank_check/ /ctx/ +--+-- Computes a generalised LU decomposition \(LU = PA\) of a given matrix+-- \(A\), returning the rank of \(A\). The behavior of this function is+-- identical to that of @fq_zech_mat_lu@. Uses recursive block+-- decomposition, switching to classical Gaussian elimination for+-- sufficiently small blocks.+foreign import ccall "fq_zech_mat.h fq_zech_mat_lu_recursive"+ fq_zech_mat_lu_recursive :: Ptr CLong -> Ptr CFqZechMat -> CInt -> Ptr CFqZechCtx -> IO CLong++-- Reduced row echelon form ----------------------------------------------------++-- | /fq_zech_mat_rref/ /A/ /ctx/ +--+-- Puts \(A\) in reduced row echelon form and returns the rank of \(A\).+-- +-- The rref is computed by first obtaining an unreduced row echelon form+-- via LU decomposition and then solving an additional triangular system.+foreign import ccall "fq_zech_mat.h fq_zech_mat_rref"+ fq_zech_mat_rref :: Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CLong++-- | /fq_zech_mat_reduce_row/ /A/ /P/ /L/ /n/ /ctx/ +--+-- Reduce row n of the matrix \(A\), assuming the prior rows are in Gauss+-- form. However those rows may not be in order. The entry \(i\) of the+-- array \(P\) is the row of \(A\) which has a pivot in the \(i\)-th+-- column. If no such row exists, the entry of \(P\) will be \(-1\). The+-- function returns the column in which the \(n\)-th row has a pivot after+-- reduction. This will always be chosen to be the first available column+-- for a pivot from the left. This information is also updated in \(P\).+-- Entry \(i\) of the array \(L\) contains the number of possibly nonzero+-- columns of \(A\) row \(i\). This speeds up reduction in the case that+-- \(A\) is chambered on the right. Otherwise the entries of \(L\) can all+-- be set to the number of columns of \(A\). We require the entries of+-- \(L\) to be monotonic increasing.+foreign import ccall "fq_zech_mat.h fq_zech_mat_reduce_row"+ fq_zech_mat_reduce_row :: Ptr CFqZechMat -> Ptr CLong -> Ptr CLong -> CLong -> Ptr CFqZechCtx -> IO CLong++-- Triangular solving ----------------------------------------------------------++-- | /fq_zech_mat_solve_tril/ /X/ /L/ /B/ /unit/ /ctx/ +--+-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- Automatically chooses between the classical and recursive algorithms.+foreign import ccall "fq_zech_mat.h fq_zech_mat_solve_tril"+ fq_zech_mat_solve_tril :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> CInt -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_solve_tril_classical/ /X/ /L/ /B/ /unit/ /ctx/ +--+-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed. Uses+-- forward substitution.+foreign import ccall "fq_zech_mat.h fq_zech_mat_solve_tril_classical"+ fq_zech_mat_solve_tril_classical :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> CInt -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_solve_tril_recursive/ /X/ /L/ /B/ /unit/ /ctx/ +--+-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- +-- Uses the block inversion formula+-- +-- \[\begin{aligned}+-- `+-- \begin{pmatrix} A & 0 \\ C & D \end{pmatrix}^{-1}+-- \begin{pmatrix} X \\ Y \end{pmatrix} =+-- \begin{pmatrix} A^{-1} X \\ D^{-1} ( Y - C A^{-1} X ) \end{pmatrix}+-- \end{aligned}\]+-- +-- to reduce the problem to matrix multiplication and triangular solving of+-- smaller systems.+foreign import ccall "fq_zech_mat.h fq_zech_mat_solve_tril_recursive"+ fq_zech_mat_solve_tril_recursive :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> CInt -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_solve_triu/ /X/ /U/ /B/ /unit/ /ctx/ +--+-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- Automatically chooses between the classical and recursive algorithms.+foreign import ccall "fq_zech_mat.h fq_zech_mat_solve_triu"+ fq_zech_mat_solve_triu :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> CInt -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_solve_triu_classical/ /X/ /U/ /B/ /unit/ /ctx/ +--+-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed. Uses+-- forward substitution.+foreign import ccall "fq_zech_mat.h fq_zech_mat_solve_triu_classical"+ fq_zech_mat_solve_triu_classical :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> CInt -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_solve_triu_recursive/ /X/ /U/ /B/ /unit/ /ctx/ +--+-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- +-- Uses the block inversion formula+-- +-- \[\begin{aligned}+-- `+-- \begin{pmatrix} A & B \\ 0 & D \end{pmatrix}^{-1}+-- \begin{pmatrix} X \\ Y \end{pmatrix} =+-- \begin{pmatrix} A^{-1} (X - B D^{-1} Y) \\ D^{-1} Y \end{pmatrix}+-- \end{aligned}\]+-- +-- to reduce the problem to matrix multiplication and triangular solving of+-- smaller systems.+foreign import ccall "fq_zech_mat.h fq_zech_mat_solve_triu_recursive"+ fq_zech_mat_solve_triu_recursive :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> CInt -> Ptr CFqZechCtx -> IO ()++-- Solving ---------------------------------------------------------------------++-- | /fq_zech_mat_solve/ /X/ /A/ /B/ /ctx/ +--+-- Solves the matrix-matrix equation \(AX = B\).+-- +-- Returns \(1\) if \(A\) has full rank; otherwise returns \(0\) and sets+-- the elements of \(X\) to undefined values.+-- +-- The matrix \(A\) must be square.+foreign import ccall "fq_zech_mat.h fq_zech_mat_solve"+ fq_zech_mat_solve :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_mat_can_solve/ /X/ /A/ /B/ /ctx/ +--+-- Solves the matrix-matrix equation \(AX = B\) over \(Fq\).+-- +-- Returns \(1\) if a solution exists; otherwise returns \(0\) and sets the+-- elements of \(X\) to zero. If more than one solution exists, one of the+-- valid solutions is given.+-- +-- There are no restrictions on the shape of \(A\) and it may be singular.+foreign import ccall "fq_zech_mat.h fq_zech_mat_can_solve"+ fq_zech_mat_can_solve :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO CInt++-- Transforms ------------------------------------------------------------------++-- | /fq_zech_mat_similarity/ /M/ /r/ /d/ /ctx/ +--+-- Applies a similarity transform to the \(n\times n\) matrix \(M\)+-- in-place.+-- +-- If \(P\) is the \(n\times n\) identity matrix the zero entries of whose+-- row \(r\) (0-indexed) have been replaced by \(d\), this transform is+-- equivalent to \(M = P^{-1}MP\).+-- +-- Similarity transforms preserve the determinant, characteristic+-- polynomial and minimal polynomial.+-- +-- The value \(d\) is required to be reduced modulo the modulus of the+-- entries in the matrix.+foreign import ccall "fq_zech_mat.h fq_zech_mat_similarity"+ fq_zech_mat_similarity :: Ptr CFqZechMat -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- Characteristic polynomial ---------------------------------------------------++-- | /fq_zech_mat_charpoly_danilevsky/ /p/ /M/ /ctx/ +--+-- Compute the characteristic polynomial \(p\) of the matrix \(M\). The+-- matrix is assumed to be square.+foreign import ccall "fq_zech_mat.h fq_zech_mat_charpoly_danilevsky"+ fq_zech_mat_charpoly_danilevsky :: Ptr CFqZechPoly -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_mat_charpoly/ /p/ /M/ +--+-- Compute the characteristic polynomial \(p\) of the matrix \(M\). The+-- matrix is required to be square, otherwise an exception is raised.+foreign import ccall "fq_zech_mat.h fq_zech_mat_charpoly"+ fq_zech_mat_charpoly :: Ptr CFqZechPoly -> Ptr CFqZechMat -> IO ()++-- Minimal polynomial ----------------------------------------------------------++-- | /fq_zech_mat_minpoly/ /p/ /M/ /ctx/ +--+-- Compute the minimal polynomial \(p\) of the matrix \(M\). The matrix is+-- required to be square, otherwise an exception is raised.+foreign import ccall "fq_zech_mat.h fq_zech_mat_minpoly"+ fq_zech_mat_minpoly :: Ptr CFqZechPoly -> Ptr CFqZechMat -> Ptr CFqZechCtx -> IO ()+
+ src/Data/Number/Flint/Fq/Zech/Poly.hs view
@@ -0,0 +1,12 @@+{- | +module : Data.Number.Flint.Fq.Zech.Poly+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Fq.Zech.Poly (+ module Data.Number.Flint.Fq.Zech.Poly.FFI,+) where++import Data.Number.Flint.Fq.Zech.Poly.FFI
+ src/Data/Number/Flint/Fq/Zech/Poly/FFI.hsc view
@@ -0,0 +1,1916 @@+{-|+module : Data.Number.Flint.Fq.Zech.Poly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Zech.Poly.FFI (+ -- * Univariate polynomials over finite fields (Zech logarithm representation)+ FqZechPoly (..)+ , CFqZechPoly (..)+ , newFqZechPoly+ , withFqZechPoly+ -- * Memory management+ , fq_zech_poly_init+ , fq_zech_poly_init2+ , fq_zech_poly_realloc+ , fq_zech_poly_fit_length+ , _fq_zech_poly_set_length+ , fq_zech_poly_clear+ , _fq_zech_poly_normalise+ , _fq_zech_poly_normalise2+ , fq_zech_poly_truncate+ , fq_zech_poly_set_trunc+ , _fq_zech_poly_reverse+ , fq_zech_poly_reverse+ -- * Polynomial parameters+ , fq_zech_poly_degree+ , fq_zech_poly_length+ , fq_zech_poly_lead+ -- * Randomisation+ , fq_zech_poly_randtest+ , fq_zech_poly_randtest_not_zero+ , fq_zech_poly_randtest_monic+ , fq_zech_poly_randtest_irreducible+ -- * Assignment and basic manipulation+ , _fq_zech_poly_set+ , fq_zech_poly_set+ , fq_zech_poly_set_fq_zech+ , fq_zech_poly_set_fmpz_mod_poly+ , fq_zech_poly_set_nmod_poly+ , fq_zech_poly_swap+ , _fq_zech_poly_zero+ , fq_zech_poly_zero+ , fq_zech_poly_one+ , fq_zech_poly_gen+ , fq_zech_poly_make_monic+ , _fq_zech_poly_make_monic+ -- * Getting and setting coefficients+ , fq_zech_poly_get_coeff+ , fq_zech_poly_set_coeff+ , fq_zech_poly_set_coeff_fmpz+ -- * Comparison+ , fq_zech_poly_equal+ , fq_zech_poly_equal_trunc+ , fq_zech_poly_is_zero+ , fq_zech_poly_is_one+ , fq_zech_poly_is_gen+ , fq_zech_poly_is_unit+ , fq_zech_poly_equal_fq_zech+ -- * Addition and subtraction+ , _fq_zech_poly_add+ , fq_zech_poly_add+ , fq_zech_poly_add_si+ , fq_zech_poly_add_series+ , _fq_zech_poly_sub+ , fq_zech_poly_sub+ , fq_zech_poly_sub_series+ , _fq_zech_poly_neg+ , fq_zech_poly_neg+ -- * Scalar multiplication and division+ , _fq_zech_poly_scalar_mul_fq_zech+ , fq_zech_poly_scalar_mul_fq_zech+ , _fq_zech_poly_scalar_addmul_fq_zech+ , fq_zech_poly_scalar_addmul_fq_zech+ , _fq_zech_poly_scalar_submul_fq_zech+ , fq_zech_poly_scalar_submul_fq_zech+ --, _fq_zech_poly_scalar_div_fq+ --, fq_zech_poly_scalar_div_fq+ -- * Multiplication+ , _fq_zech_poly_mul_classical+ , fq_zech_poly_mul_classical+ --, _fq_zech_poly_mul_reorder+ --, fq_zech_poly_mul_reorder+ , _fq_zech_poly_mul_KS+ , fq_zech_poly_mul_KS+ , _fq_zech_poly_mul+ , fq_zech_poly_mul+ , _fq_zech_poly_mullow_classical+ , fq_zech_poly_mullow_classical+ , _fq_zech_poly_mullow_KS+ , fq_zech_poly_mullow_KS+ , _fq_zech_poly_mullow+ , fq_zech_poly_mullow+ , _fq_zech_poly_mulhigh_classical+ , fq_zech_poly_mulhigh_classical+ , _fq_zech_poly_mulhigh+ , fq_zech_poly_mulhigh+ , _fq_zech_poly_mulmod+ , fq_zech_poly_mulmod+ , _fq_zech_poly_mulmod_preinv+ , fq_zech_poly_mulmod_preinv+ -- * Squaring+ , _fq_zech_poly_sqr_classical+ , fq_zech_poly_sqr_classical+ , _fq_zech_poly_sqr_KS+ , fq_zech_poly_sqr_KS+ , _fq_zech_poly_sqr+ , fq_zech_poly_sqr+ -- * Powering+ , _fq_zech_poly_pow+ , fq_zech_poly_pow+ , _fq_zech_poly_powmod_ui_binexp+ , fq_zech_poly_powmod_ui_binexp+ , _fq_zech_poly_powmod_ui_binexp_preinv+ , fq_zech_poly_powmod_ui_binexp_preinv+ , _fq_zech_poly_powmod_fmpz_binexp+ , fq_zech_poly_powmod_fmpz_binexp+ , _fq_zech_poly_powmod_fmpz_binexp_preinv+ , fq_zech_poly_powmod_fmpz_binexp_preinv+ , _fq_zech_poly_powmod_fmpz_sliding_preinv+ , fq_zech_poly_powmod_fmpz_sliding_preinv+ , _fq_zech_poly_powmod_x_fmpz_preinv+ , fq_zech_poly_powmod_x_fmpz_preinv+ , _fq_zech_poly_pow_trunc_binexp+ , fq_zech_poly_pow_trunc_binexp+ , _fq_zech_poly_pow_trunc+ , fq_zech_poly_pow_trunc+ -- * Shifting+ , _fq_zech_poly_shift_left+ , fq_zech_poly_shift_left+ , _fq_zech_poly_shift_right+ , fq_zech_poly_shift_right+ -- * Norms+ , _fq_zech_poly_hamming_weight+ , fq_zech_poly_hamming_weight+ -- * Euclidean division+ , _fq_zech_poly_divrem+ , fq_zech_poly_divrem+ , fq_zech_poly_divrem_f+ , _fq_zech_poly_rem+ , fq_zech_poly_rem+ , _fq_zech_poly_div+ , fq_zech_poly_div+ , _fq_zech_poly_div_newton_n_preinv+ , fq_zech_poly_div_newton_n_preinv+ , _fq_zech_poly_divrem_newton_n_preinv+ , fq_zech_poly_divrem_newton_n_preinv+ , _fq_zech_poly_inv_series_newton+ , fq_zech_poly_inv_series_newton+ , _fq_zech_poly_inv_series+ , fq_zech_poly_inv_series+ , _fq_zech_poly_div_series+ , fq_zech_poly_div_series+ -- * Greatest common divisor+ , fq_zech_poly_gcd+ , _fq_zech_poly_gcd+ , _fq_zech_poly_gcd_euclidean_f+ , fq_zech_poly_gcd_euclidean_f+ , _fq_zech_poly_xgcd+ , fq_zech_poly_xgcd+ , _fq_zech_poly_xgcd_euclidean_f+ , fq_zech_poly_xgcd_euclidean_f+ -- * Divisibility testing+ , _fq_zech_poly_divides+ , fq_zech_poly_divides+ -- * Derivative+ , _fq_zech_poly_derivative+ , fq_zech_poly_derivative+ -- * Square root+ , _fq_zech_poly_invsqrt_series+ , fq_zech_poly_invsqrt_series+ , _fq_zech_poly_sqrt_series+ , fq_zech_poly_sqrt_series+ , _fq_zech_poly_sqrt+ , fq_zech_poly_sqrt+ -- * Evaluation+ , _fq_zech_poly_evaluate_fq_zech+ , fq_zech_poly_evaluate_fq_zech+ -- * Composition+ , _fq_zech_poly_compose+ , fq_zech_poly_compose+ , _fq_zech_poly_compose_mod_horner+ , fq_zech_poly_compose_mod_horner+ , _fq_zech_poly_compose_mod_horner_preinv+ , fq_zech_poly_compose_mod_horner_preinv+ , _fq_zech_poly_compose_mod_brent_kung+ , fq_zech_poly_compose_mod_brent_kung+ , _fq_zech_poly_compose_mod_brent_kung_preinv+ , fq_zech_poly_compose_mod_brent_kung_preinv+ , _fq_zech_poly_compose_mod+ , fq_zech_poly_compose_mod+ , _fq_zech_poly_compose_mod_preinv+ , fq_zech_poly_compose_mod_preinv+ , _fq_zech_poly_reduce_matrix_mod_poly+ , _fq_zech_poly_precompute_matrix+ , fq_zech_poly_precompute_matrix+ , _fq_zech_poly_compose_mod_brent_kung_precomp_preinv+ , fq_zech_poly_compose_mod_brent_kung_precomp_preinv+ -- * Output+ , _fq_zech_poly_fprint_pretty+ , fq_zech_poly_fprint_pretty+ , _fq_zech_poly_print_pretty+ , fq_zech_poly_print_pretty+ , _fq_zech_poly_fprint+ , fq_zech_poly_fprint+ , _fq_zech_poly_print+ , fq_zech_poly_print+ , _fq_zech_poly_get_str+ , fq_zech_poly_get_str+ , _fq_zech_poly_get_str_pretty+ , fq_zech_poly_get_str_pretty+ -- * Inflation and deflation+ , fq_zech_poly_inflate+ , fq_zech_poly_deflate+ , fq_zech_poly_deflation+) where ++-- Univariate polynomials over finite fields (Zech logarithm representation)++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mod.Poly+import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.NMod.Mat+import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.Poly+import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Mat++import Data.Number.Flint.Fq.Zech+import Data.Number.Flint.Fq.Zech.Types++#include <flint/flint.h>+#include <flint/fq_zech_poly.h>++-- fq_zech_poly_t --------------------------------------------------------------++instance Storable CFqZechPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_zech_poly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_zech_poly_t}+ peek = undefined+ poke = undefined++newFqZechPoly ctx@(FqZechCtx ftx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqZechCtx ctx $ \ctx -> do+ fq_zech_poly_init x ctx+ addForeignPtrFinalizerEnv p_fq_zech_poly_clear x ftx+ return $ FqZechPoly x++{-# INLINE withFqZechPoly #-}+withFqZechPoly (FqZechPoly x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqZechPoly x,)+ ++-- Memory management -----------------------------------------------------------++-- | /fq_zech_poly_init/ /poly/ /ctx/ +--+-- Initialises @poly@ for use, with context ctx, and setting its length to+-- zero. A corresponding call to @fq_zech_poly_clear@ must be made after+-- finishing with the @fq_zech_poly_t@ to free the memory used by the+-- polynomial.+foreign import ccall "fq_zech_poly.h fq_zech_poly_init"+ fq_zech_poly_init :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_init2/ /poly/ /alloc/ /ctx/ +--+-- Initialises @poly@ with space for at least @alloc@ coefficients and sets+-- the length to zero. The allocated coefficients are all set to zero. A+-- corresponding call to @fq_zech_poly_clear@ must be made after finishing+-- with the @fq_zech_poly_t@ to free the memory used by the polynomial.+foreign import ccall "fq_zech_poly.h fq_zech_poly_init2"+ fq_zech_poly_init2 :: Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_realloc/ /poly/ /alloc/ /ctx/ +--+-- Reallocates the given polynomial to have space for @alloc@ coefficients.+-- If @alloc@ is zero the polynomial is cleared and then reinitialised. If+-- the current length is greater than @alloc@ the polynomial is first+-- truncated to length @alloc@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_realloc"+ fq_zech_poly_realloc :: Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_fit_length/ /poly/ /len/ /ctx/ +--+-- If @len@ is greater than the number of coefficients currently allocated,+-- then the polynomial is reallocated to have space for at least @len@+-- coefficients. No data is lost when calling this function.+-- +-- The function efficiently deals with the case where @fit_length@ is+-- called many times in small increments by at least doubling the number of+-- allocated coefficients when length is larger than the number of+-- coefficients currently allocated.+foreign import ccall "fq_zech_poly.h fq_zech_poly_fit_length"+ fq_zech_poly_fit_length :: Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_set_length/ /poly/ /newlen/ /ctx/ +--+-- Sets the coefficients of @poly@ beyond @len@ to zero and sets the length+-- of @poly@ to @len@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_set_length"+ _fq_zech_poly_set_length :: Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_clear/ /poly/ /ctx/ +--+-- Clears the given polynomial, releasing any memory used. It must be+-- reinitialised in order to be used again.+foreign import ccall "fq_zech_poly.h fq_zech_poly_clear"+ fq_zech_poly_clear :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++foreign import ccall "fq_zech_poly.h &fq_zech_poly_clear"+ p_fq_zech_poly_clear :: FunPtr (Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ())++-- | /_fq_zech_poly_normalise/ /poly/ /ctx/ +--+-- Sets the length of @poly@ so that the top coefficient is non-zero. If+-- all coefficients are zero, the length is set to zero. This function is+-- mainly used internally, as all functions guarantee normalisation.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_normalise"+ _fq_zech_poly_normalise :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_normalise2/ /poly/ /length/ /ctx/ +--+-- Sets the length @length@ of @(poly,length)@ so that the top coefficient+-- is non-zero. If all coefficients are zero, the length is set to zero.+-- This function is mainly used internally, as all functions guarantee+-- normalisation.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_normalise2"+ _fq_zech_poly_normalise2 :: Ptr CFqZech -> Ptr CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_truncate/ /poly/ /newlen/ /ctx/ +--+-- Truncates the polynomial to length at most \(n\).+foreign import ccall "fq_zech_poly.h fq_zech_poly_truncate"+ fq_zech_poly_truncate :: Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_set_trunc/ /poly1/ /poly2/ /newlen/ /ctx/ +--+-- Sets @poly1@ to @poly2@ truncated to length \(n\).+foreign import ccall "fq_zech_poly.h fq_zech_poly_set_trunc"+ fq_zech_poly_set_trunc :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_zech_poly_reverse/ /output/ /input/ /len/ /m/ /ctx/ +--+-- Sets @output@ to the reverse of @input@, which is of length @len@, but+-- thinking of it as a polynomial of length @m@, notionally zero-padded if+-- necessary. The length @m@ must be non-negative, but there are no other+-- restrictions. The polynomial @output@ must have space for @m@+-- coefficients.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_reverse"+ _fq_zech_poly_reverse :: Ptr CFqZech -> Ptr CFqZech -> CLong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_reverse/ /output/ /input/ /m/ /ctx/ +--+-- Sets @output@ to the reverse of @input@, thinking of it as a polynomial+-- of length @m@, notionally zero-padded if necessary). The length @m@ must+-- be non-negative, but there are no other restrictions. The output+-- polynomial will be set to length @m@ and then normalised.+foreign import ccall "fq_zech_poly.h fq_zech_poly_reverse"+ fq_zech_poly_reverse :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- Polynomial parameters -------------------------------------------------------++-- | /fq_zech_poly_degree/ /poly/ /ctx/ +--+-- Returns the degree of the polynomial @poly@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_degree"+ fq_zech_poly_degree :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CLong++-- | /fq_zech_poly_length/ /poly/ /ctx/ +--+-- Returns the length of the polynomial @poly@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_length"+ fq_zech_poly_length :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CLong++-- | /fq_zech_poly_lead/ /poly/ /ctx/ +--+-- Returns a pointer to the leading coefficient of @poly@, or @NULL@ if+-- @poly@ is the zero polynomial.+foreign import ccall "fq_zech_poly.h fq_zech_poly_lead"+ fq_zech_poly_lead :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO (Ptr CFqZech)++-- Randomisation ---------------------------------------------------------------++-- | /fq_zech_poly_randtest/ /f/ /state/ /len/ /ctx/ +--+-- Sets \(f\) to a random polynomial of length at most @len@ with entries+-- in the field described by @ctx@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_randtest"+ fq_zech_poly_randtest :: Ptr CFqZechPoly -> Ptr CFRandState -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_randtest_not_zero/ /f/ /state/ /len/ /ctx/ +--+-- Same as @fq_zech_poly_randtest@ but guarantees that the polynomial is+-- not zero.+foreign import ccall "fq_zech_poly.h fq_zech_poly_randtest_not_zero"+ fq_zech_poly_randtest_not_zero :: Ptr CFqZechPoly -> Ptr CFRandState -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_randtest_monic/ /f/ /state/ /len/ /ctx/ +--+-- Sets \(f\) to a random monic polynomial of length @len@ with entries in+-- the field described by @ctx@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_randtest_monic"+ fq_zech_poly_randtest_monic :: Ptr CFqZechPoly -> Ptr CFRandState -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_randtest_irreducible/ /f/ /state/ /len/ /ctx/ +--+-- Sets \(f\) to a random monic, irreducible polynomial of length @len@+-- with entries in the field described by @ctx@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_randtest_irreducible"+ fq_zech_poly_randtest_irreducible :: Ptr CFqZechPoly -> Ptr CFRandState -> CLong -> Ptr CFqZechCtx -> IO ()++-- Assignment and basic manipulation -------------------------------------------++-- | /_fq_zech_poly_set/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, len@) to @(op, len)@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_set"+ _fq_zech_poly_set :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_set/ /poly1/ /poly2/ /ctx/ +--+-- Sets the polynomial @poly1@ to the polynomial @poly2@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_set"+ fq_zech_poly_set :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_set_fq_zech/ /poly/ /c/ /ctx/ +--+-- Sets the polynomial @poly@ to @c@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_set_fq_zech"+ fq_zech_poly_set_fq_zech :: Ptr CFqZechPoly -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_set_fmpz_mod_poly/ /rop/ /op/ /ctx/ +--+-- Sets the polynomial @rop@ to the polynomial @op@+foreign import ccall "fq_zech_poly.h fq_zech_poly_set_fmpz_mod_poly"+ fq_zech_poly_set_fmpz_mod_poly :: Ptr CFqZechPoly -> Ptr CFmpzModPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_set_nmod_poly/ /rop/ /op/ /ctx/ +--+-- Sets the polynomial @rop@ to the polynomial @op@+foreign import ccall "fq_zech_poly.h fq_zech_poly_set_nmod_poly"+ fq_zech_poly_set_nmod_poly :: Ptr CFqZechPoly -> Ptr CNModPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_swap/ /op1/ /op2/ /ctx/ +--+-- Swaps the two polynomials @op1@ and @op2@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_swap"+ fq_zech_poly_swap :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_zero/ /rop/ /len/ /ctx/ +--+-- Sets @(rop, len)@ to the zero polynomial.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_zero"+ _fq_zech_poly_zero :: Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_zero/ /poly/ /ctx/ +--+-- Sets @poly@ to the zero polynomial.+foreign import ccall "fq_zech_poly.h fq_zech_poly_zero"+ fq_zech_poly_zero :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_one/ /poly/ /ctx/ +--+-- Sets @poly@ to the constant polynomial \(1\).+foreign import ccall "fq_zech_poly.h fq_zech_poly_one"+ fq_zech_poly_one :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_gen/ /poly/ /ctx/ +--+-- Sets @poly@ to the polynomial \(x\).+foreign import ccall "fq_zech_poly.h fq_zech_poly_gen"+ fq_zech_poly_gen :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_make_monic/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to @op@, normed to have leading coefficient 1.+foreign import ccall "fq_zech_poly.h fq_zech_poly_make_monic"+ fq_zech_poly_make_monic :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_make_monic/ /rop/ /op/ /length/ /ctx/ +--+-- Sets @rop@ to @(op,length)@, normed to have leading coefficient 1.+-- Assumes that @rop@ has enough space for the polynomial, assumes that+-- @op@ is not zero (and thus has an invertible leading coefficient).+foreign import ccall "fq_zech_poly.h _fq_zech_poly_make_monic"+ _fq_zech_poly_make_monic :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- Getting and setting coefficients --------------------------------------------++-- | /fq_zech_poly_get_coeff/ /x/ /poly/ /n/ /ctx/ +--+-- Sets \(x\) to the coefficient of \(X^n\) in @poly@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_get_coeff"+ fq_zech_poly_get_coeff :: Ptr CFqZech -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_set_coeff/ /poly/ /n/ /x/ /ctx/ +--+-- Sets the coefficient of \(X^n\) in @poly@ to \(x\).+foreign import ccall "fq_zech_poly.h fq_zech_poly_set_coeff"+ fq_zech_poly_set_coeff :: Ptr CFqZechPoly -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_set_coeff_fmpz/ /poly/ /n/ /x/ /ctx/ +--+-- Sets the coefficient of \(X^n\) in the polynomial to \(x\), assuming+-- \(n \geq 0\).+foreign import ccall "fq_zech_poly.h fq_zech_poly_set_coeff_fmpz"+ fq_zech_poly_set_coeff_fmpz :: Ptr CFqZechPoly -> CLong -> Ptr CFmpz -> Ptr CFqZechCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /fq_zech_poly_equal/ /poly1/ /poly2/ /ctx/ +--+-- Returns nonzero if the two polynomials @poly1@ and @poly2@ are equal,+-- otherwise return zero.+foreign import ccall "fq_zech_poly.h fq_zech_poly_equal"+ fq_zech_poly_equal :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_equal_trunc/ /poly1/ /poly2/ /n/ /ctx/ +--+-- Notionally truncate @poly1@ and @poly2@ to length \(n\) and return+-- nonzero if they are equal, otherwise return zero.+foreign import ccall "fq_zech_poly.h fq_zech_poly_equal_trunc"+ fq_zech_poly_equal_trunc :: Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO CInt++-- | /fq_zech_poly_is_zero/ /poly/ /ctx/ +--+-- Returns whether the polynomial @poly@ is the zero polynomial.+foreign import ccall "fq_zech_poly.h fq_zech_poly_is_zero"+ fq_zech_poly_is_zero :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_is_one/ /op/ +--+-- Returns whether the polynomial @poly@ is equal to the constant+-- polynomial \(1\).+foreign import ccall "fq_zech_poly.h fq_zech_poly_is_one"+ fq_zech_poly_is_one :: Ptr CFqZechPoly -> IO CInt++-- | /fq_zech_poly_is_gen/ /op/ /ctx/ +--+-- Returns whether the polynomial @poly@ is equal to the polynomial \(x\).+foreign import ccall "fq_zech_poly.h fq_zech_poly_is_gen"+ fq_zech_poly_is_gen :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_is_unit/ /op/ /ctx/ +--+-- Returns whether the polynomial @poly@ is a unit in the polynomial ring+-- \(\mathbf{F}_q[X]\), i.e. if it has degree \(0\) and is non-zero.+foreign import ccall "fq_zech_poly.h fq_zech_poly_is_unit"+ fq_zech_poly_is_unit :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_equal_fq_zech/ /poly/ /c/ /ctx/ +--+-- Returns whether the polynomial @poly@ is equal the (constant)+-- \(\mathbf{F}_q\) element @c@+foreign import ccall "fq_zech_poly.h fq_zech_poly_equal_fq_zech"+ fq_zech_poly_equal_fq_zech :: Ptr CFqZechPoly -> Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /_fq_zech_poly_add/ /res/ /poly1/ /len1/ /poly2/ /len2/ /ctx/ +--+-- Sets @res@ to the sum of @(poly1,len1)@ and @(poly2,len2)@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_add"+ _fq_zech_poly_add :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_add/ /res/ /poly1/ /poly2/ /ctx/ +--+-- Sets @res@ to the sum of @poly1@ and @poly2@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_add"+ fq_zech_poly_add :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_add_si/ /res/ /poly1/ /c/ /ctx/ +--+-- Sets @res@ to the sum of @poly1@ and @c@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_add_si"+ fq_zech_poly_add_si :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_add_series/ /res/ /poly1/ /poly2/ /n/ /ctx/ +--+-- Notionally truncate @poly1@ and @poly2@ to length @n@ and set @res@ to+-- the sum.+foreign import ccall "fq_zech_poly.h fq_zech_poly_add_series"+ fq_zech_poly_add_series :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_zech_poly_sub/ /res/ /poly1/ /len1/ /poly2/ /len2/ /ctx/ +--+-- Sets @res@ to the difference of @(poly1,len1)@ and @(poly2,len2)@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_sub"+ _fq_zech_poly_sub :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_sub/ /res/ /poly1/ /poly2/ /ctx/ +--+-- Sets @res@ to the difference of @poly1@ and @poly2@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_sub"+ fq_zech_poly_sub :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_sub_series/ /res/ /poly1/ /poly2/ /n/ /ctx/ +--+-- Notionally truncate @poly1@ and @poly2@ to length @n@ and set @res@ to+-- the difference.+foreign import ccall "fq_zech_poly.h fq_zech_poly_sub_series"+ fq_zech_poly_sub_series :: Ptr CFqPoly -> Ptr CFqPoly -> Ptr CFqPoly -> CLong -> Ptr CFqCtx -> IO ()++-- | /_fq_zech_poly_neg/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @rop@ to the additive inverse of @(op,len)@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_neg"+ _fq_zech_poly_neg :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_neg/ /res/ /poly/ /ctx/ +--+-- Sets @res@ to the additive inverse of @poly@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_neg"+ fq_zech_poly_neg :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- Scalar multiplication and division ------------------------------------------++-- | /_fq_zech_poly_scalar_mul_fq_zech/ /rop/ /op/ /len/ /x/ /ctx/ +--+-- Sets @(rop,len)@ to the product of @(op,len)@ by the scalar @x@, in the+-- context defined by @ctx@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_scalar_mul_fq_zech"+ _fq_zech_poly_scalar_mul_fq_zech :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_scalar_mul_fq_zech/ /rop/ /op/ /x/ /ctx/ +--+-- Sets @rop@ to the product of @op@ by the scalar @x@, in the context+-- defined by @ctx@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_scalar_mul_fq_zech"+ fq_zech_poly_scalar_mul_fq_zech :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_scalar_addmul_fq_zech/ /rop/ /op/ /len/ /x/ /ctx/ +--+-- Adds to @(rop,len)@ the product of @(op,len)@ by the scalar @x@, in the+-- context defined by @ctx@. In particular, assumes the same length for+-- @op@ and @rop@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_scalar_addmul_fq_zech"+ _fq_zech_poly_scalar_addmul_fq_zech :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_scalar_addmul_fq_zech/ /rop/ /op/ /x/ /ctx/ +--+-- Adds to @rop@ the product of @op@ by the scalar @x@, in the context+-- defined by @ctx@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_scalar_addmul_fq_zech"+ fq_zech_poly_scalar_addmul_fq_zech :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_scalar_submul_fq_zech/ /rop/ /op/ /len/ /x/ /ctx/ +--+-- Subtracts from @(rop,len)@ the product of @(op,len)@ by the scalar @x@,+-- in the context defined by @ctx@. In particular, assumes the same length+-- for @op@ and @rop@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_scalar_submul_fq_zech"+ _fq_zech_poly_scalar_submul_fq_zech :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_scalar_submul_fq_zech/ /rop/ /op/ /x/ /ctx/ +--+-- Subtracts from @rop@ the product of @op@ by the scalar @x@, in the+-- context defined by @ctx@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_scalar_submul_fq_zech"+ fq_zech_poly_scalar_submul_fq_zech :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- -- | /_fq_zech_poly_scalar_div_fq/ /rop/ /op/ /len/ /x/ /ctx/ +-- --+-- -- Sets @(rop,len)@ to the quotient of @(op,len)@ by the scalar @x@, in the+-- -- context defined by @ctx@. An exception is raised if @x@ is zero.+-- foreign import ccall "fq_zech_poly.h _fq_zech_poly_scalar_div_fq"+-- _fq_zech_poly_scalar_div_fq :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- -- | /fq_zech_poly_scalar_div_fq/ /rop/ /op/ /x/ /ctx/ +-- --+-- -- Sets @rop@ to the quotient of @op@ by the scalar @x@, in the context+-- -- defined by @ctx@. An exception is raised if @x@ is zero.+-- foreign import ccall "fq_zech_poly.h fq_zech_poly_scalar_div_fq"+-- fq_zech_poly_scalar_div_fq :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /_fq_zech_poly_mul_classical/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@, assuming that @len1@ is at least @len2@ and neither is+-- zero.+-- +-- Permits zero padding. Does not support aliasing of @rop@ with either+-- @op1@ or @op2@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_mul_classical"+ _fq_zech_poly_mul_classical :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_mul_classical/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@ using classical polynomial+-- multiplication.+foreign import ccall "fq_zech_poly.h fq_zech_poly_mul_classical"+ fq_zech_poly_mul_classical :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- -- | /_fq_zech_poly_mul_reorder/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +-- --+-- -- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- -- @(op2, len2)@, assuming that @len1@ and @len2@ are non-zero.+-- -- +-- -- Permits zero padding. Supports aliasing.+-- foreign import ccall "fq_zech_poly.h _fq_zech_poly_mul_reorder"+-- _fq_zech_poly_mul_reorder :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- -- | /fq_zech_poly_mul_reorder/ /rop/ /op1/ /op2/ /ctx/ +-- --+-- -- Sets @rop@ to the product of @op1@ and @op2@, reordering the two+-- -- indeterminates \(X\) and \(Y\) when viewing the polynomials as elements+-- -- of \(\mathbf{F}_p[X,Y]\).+-- -- +-- -- Suppose \(\mathbf{F}_q = \mathbf{F}_p[X]/ (f(X))\) and recall that+-- -- elements of \(\mathbf{F}_q\) are internally represented by elements of+-- -- type @fmpz_poly@. For small degree extensions but polynomials in+-- -- \(\mathbf{F}_q[Y]\) of large degree \(n\), we change the representation+-- -- to+-- -- +-- -- \[`\]+-- -- \[\begin{aligned}+-- -- \begin{split}+-- -- g(Y) & = \sum_{i=0}^{n} a_i(X) Y^i \\+-- -- & = \sum_{j=0}^{d} \sum_{i=0}^{n} \text{Coeff}(a_i(X), j) Y^i.+-- -- \end{split}+-- -- \end{aligned}\]+-- -- +-- -- This allows us to use a poor algorithm (such as classical+-- -- multiplication) in the \(X\)-direction and leverage the existing fast+-- -- integer multiplication routines in the \(Y\)-direction where the+-- -- polynomial degree \(n\) is large.+-- foreign import ccall "fq_zech_poly.h fq_zech_poly_mul_reorder"+-- fq_zech_poly_mul_reorder :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_mul_KS/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@.+-- +-- Permits zero padding and places no assumptions on the lengths @len1@ and+-- @len2@. Supports aliasing.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_mul_KS"+ _fq_zech_poly_mul_KS :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_mul_KS/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@ using Kronecker+-- substitution, that is, by encoding each coefficient in+-- \(\mathbf{F}_{q}\) as an integer and reducing this problem to+-- multiplying two polynomials over the integers.+foreign import ccall "fq_zech_poly.h fq_zech_poly_mul_KS"+ fq_zech_poly_mul_KS :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_mul/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @(rop, len1 + len2 - 1)@ to the product of @(op1, len1)@ and+-- @(op2, len2)@, choosing an appropriate algorithm.+-- +-- Permits zero padding. Does not support aliasing.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_mul"+ _fq_zech_poly_mul :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_mul/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@, choosing an appropriate+-- algorithm.+foreign import ccall "fq_zech_poly.h fq_zech_poly_mul"+ fq_zech_poly_mul :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_mullow_classical/ /rop/ /op1/ /len1/ /op2/ /len2/ /n/ /ctx/ +--+-- Sets @(rop, n)@ to the first \(n\) coefficients of @(op1, len1)@+-- multiplied by @(op2, len2)@.+-- +-- Assumes @0 \< n \<= len1 + len2 - 1@. Assumes neither @len1@ nor @len2@+-- is zero.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_mullow_classical"+ _fq_zech_poly_mullow_classical :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_mullow_classical/ /rop/ /op1/ /op2/ /n/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@, computed using the+-- classical or schoolbook method.+foreign import ccall "fq_zech_poly.h fq_zech_poly_mullow_classical"+ fq_zech_poly_mullow_classical :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_mullow_KS/ /rop/ /op1/ /len1/ /op2/ /len2/ /n/ /ctx/ +--+-- Sets @(rop, n)@ to the lowest \(n\) coefficients of the product of+-- @(op1, len1)@ and @(op2, len2)@.+-- +-- Assumes that @len1@ and @len2@ are positive, but does allow for the+-- polynomials to be zero-padded. The polynomials may be zero, too. Assumes+-- \(n\) is positive. Supports aliasing between @rop@, @op1@ and @op2@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_mullow_KS"+ _fq_zech_poly_mullow_KS :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_mullow_KS/ /rop/ /op1/ /op2/ /n/ /ctx/ +--+-- Sets @rop@ to the product of @op1@ and @op2@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_mullow_KS"+ fq_zech_poly_mullow_KS :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_mullow/ /rop/ /op1/ /len1/ /op2/ /len2/ /n/ /ctx/ +--+-- Sets @(rop, n)@ to the lowest \(n\) coefficients of the product of+-- @(op1, len1)@ and @(op2, len2)@.+-- +-- Assumes @0 \< n \<= len1 + len2 - 1@. Allows for zero-padding in the+-- inputs. Does not support aliasing between the inputs and the output.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_mullow"+ _fq_zech_poly_mullow :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_mullow/ /rop/ /op1/ /op2/ /n/ /ctx/ +--+-- Sets @rop@ to the lowest \(n\) coefficients of the product of @op1@ and+-- @op2@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_mullow"+ fq_zech_poly_mullow :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_mulhigh_classical/ /res/ /poly1/ /len1/ /poly2/ /len2/ /start/ /ctx/ +--+-- Computes the product of @(poly1, len1)@ and @(poly2, len2)@ and writes+-- the coefficients from @start@ onwards into the high coefficients of+-- @res@, the remaining coefficients being arbitrary but reduced. Assumes+-- that @len1 >= len2 > 0@. Aliasing of inputs and output is not permitted.+-- Algorithm is classical multiplication.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_mulhigh_classical"+ _fq_zech_poly_mulhigh_classical :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_mulhigh_classical/ /res/ /poly1/ /poly2/ /start/ /ctx/ +--+-- Computes the product of @poly1@ and @poly2@ and writes the coefficients+-- from @start@ onwards into the high coefficients of @res@, the remaining+-- coefficients being arbitrary but reduced. Algorithm is classical+-- multiplication.+foreign import ccall "fq_zech_poly.h fq_zech_poly_mulhigh_classical"+ fq_zech_poly_mulhigh_classical :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_mulhigh/ /res/ /poly1/ /len1/ /poly2/ /len2/ /start/ /ctx/ +--+-- Computes the product of @(poly1, len1)@ and @(poly2, len2)@ and writes+-- the coefficients from @start@ onwards into the high coefficients of+-- @res@, the remaining coefficients being arbitrary but reduced. Assumes+-- that @len1 >= len2 > 0@. Aliasing of inputs and output is not permitted.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_mulhigh"+ _fq_zech_poly_mulhigh :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_mulhigh/ /res/ /poly1/ /poly2/ /start/ /ctx/ +--+-- Computes the product of @poly1@ and @poly2@ and writes the coefficients+-- from @start@ onwards into the high coefficients of @res@, the remaining+-- coefficients being arbitrary but reduced.+foreign import ccall "fq_zech_poly.h fq_zech_poly_mulhigh"+ fq_zech_poly_mulhigh :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_mulmod/ /res/ /poly1/ /len1/ /poly2/ /len2/ /f/ /lenf/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+-- +-- It is required that @len1 + len2 - lenf > 0@, which is equivalent to+-- requiring that the result will actually be reduced. Otherwise, simply+-- use @_fq_zech_poly_mul@ instead.+-- +-- Aliasing of @f@ and @res@ is not permitted.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_mulmod"+ _fq_zech_poly_mulmod :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_mulmod/ /res/ /poly1/ /poly2/ /f/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_mulmod"+ fq_zech_poly_mulmod :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_mulmod_preinv/ /res/ /poly1/ /len1/ /poly2/ /len2/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+-- +-- It is required that @finv@ is the inverse of the reverse of @f@ mod+-- @x^lenf@.+-- +-- Aliasing of @res@ with any of the inputs is not permitted.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_mulmod_preinv"+ _fq_zech_poly_mulmod_preinv :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_mulmod_preinv/ /res/ /poly1/ /poly2/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@. @finv@ is the inverse of the reverse of @f@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_mulmod_preinv"+ fq_zech_poly_mulmod_preinv :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- Squaring --------------------------------------------------------------------++-- | /_fq_zech_poly_sqr_classical/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, 2*len - 1)@ to the square of @(op, len)@, assuming that+-- @(op,len)@ is not zero and using classical polynomial multiplication.+-- +-- Permits zero padding. Does not support aliasing of @rop@ with either+-- @op1@ or @op2@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_sqr_classical"+ _fq_zech_poly_sqr_classical :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_sqr_classical/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the square of @op@ using classical polynomial+-- multiplication.+foreign import ccall "fq_zech_poly.h fq_zech_poly_sqr_classical"+ fq_zech_poly_sqr_classical :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_sqr_KS/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, 2*len - 1)@ to the square of @(op, len)@.+-- +-- Permits zero padding and places no assumptions on the lengths @len1@ and+-- @len2@. Supports aliasing.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_sqr_KS"+ _fq_zech_poly_sqr_KS :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_sqr_KS/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the square @op@ using Kronecker substitution, that is, by+-- encoding each coefficient in \(\mathbf{F}_{q}\) as an integer and+-- reducing this problem to multiplying two polynomials over the integers.+foreign import ccall "fq_zech_poly.h fq_zech_poly_sqr_KS"+ fq_zech_poly_sqr_KS :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_sqr/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, 2* len - 1)@ to the square of @(op, len)@, choosing an+-- appropriate algorithm.+-- +-- Permits zero padding. Does not support aliasing.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_sqr"+ _fq_zech_poly_sqr :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_sqr/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the square of @op@, choosing an appropriate algorithm.+foreign import ccall "fq_zech_poly.h fq_zech_poly_sqr"+ fq_zech_poly_sqr :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- Powering --------------------------------------------------------------------++-- | /_fq_zech_poly_pow/ /rop/ /op/ /len/ /e/ /ctx/ +--+-- Sets @rop = op^e@, assuming that @e, len > 0@ and that @res@ has space+-- for @e*(len - 1) + 1@ coefficients. Does not support aliasing.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_pow"+ _fq_zech_poly_pow :: Ptr CFqZech -> Ptr CFqZech -> CLong -> CULong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_pow/ /rop/ /op/ /e/ /ctx/ +--+-- Computes @rop = op^e@. If \(e\) is zero, returns one, so that in+-- particular @0^0 = 1@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_pow"+ fq_zech_poly_pow :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CULong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_powmod_ui_binexp/ /res/ /poly/ /e/ /f/ /lenf/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_powmod_ui_binexp"+ _fq_zech_poly_powmod_ui_binexp :: Ptr CFqZech -> Ptr CFqZech -> CULong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_powmod_ui_binexp/ /res/ /poly/ /e/ /f/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_powmod_ui_binexp"+ fq_zech_poly_powmod_ui_binexp :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CULong -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_powmod_ui_binexp_preinv/ /res/ /poly/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_powmod_ui_binexp_preinv"+ _fq_zech_poly_powmod_ui_binexp_preinv :: Ptr CFqZech -> Ptr CFqZech -> CULong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_powmod_ui_binexp_preinv/ /res/ /poly/ /e/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_powmod_ui_binexp_preinv"+ fq_zech_poly_powmod_ui_binexp_preinv :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CULong -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_powmod_fmpz_binexp/ /res/ /poly/ /e/ /f/ /lenf/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_powmod_fmpz_binexp"+ _fq_zech_poly_powmod_fmpz_binexp :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFmpz -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_powmod_fmpz_binexp/ /res/ /poly/ /e/ /f/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_powmod_fmpz_binexp"+ fq_zech_poly_powmod_fmpz_binexp :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFmpz -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_powmod_fmpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_powmod_fmpz_binexp_preinv"+ _fq_zech_poly_powmod_fmpz_binexp_preinv :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFmpz -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_powmod_fmpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_powmod_fmpz_binexp_preinv"+ fq_zech_poly_powmod_fmpz_binexp_preinv :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFmpz -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_powmod_fmpz_sliding_preinv/ /res/ /poly/ /e/ /k/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using+-- sliding-window exponentiation with window size @k@. We require @e > 0@.+-- We require @finv@ to be the inverse of the reverse of @f@. If @k@ is set+-- to zero, then an \"optimum\" size will be selected automatically base on+-- @e@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_powmod_fmpz_sliding_preinv"+ _fq_zech_poly_powmod_fmpz_sliding_preinv :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFmpz -> CULong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_powmod_fmpz_sliding_preinv/ /res/ /poly/ /e/ /k/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using+-- sliding-window exponentiation with window size @k@. We require @e >= 0@.+-- We require @finv@ to be the inverse of the reverse of @f@. If @k@ is set+-- to zero, then an \"optimum\" size will be selected automatically base on+-- @e@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_powmod_fmpz_sliding_preinv"+ fq_zech_poly_powmod_fmpz_sliding_preinv :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFmpz -> CULong -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_powmod_x_fmpz_preinv/ /res/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /ctx/ +--+-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e > 0@. We require @finv@ to be the+-- inverse of the reverse of @f@.+-- +-- We require @lenf > 2@. The output @res@ must have room for @lenf - 1@+-- coefficients.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_powmod_x_fmpz_preinv"+ _fq_zech_poly_powmod_x_fmpz_preinv :: Ptr CFqZech -> Ptr CFmpz -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_powmod_x_fmpz_preinv/ /res/ /e/ /f/ /finv/ /ctx/ +--+-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e >= 0@. We require @finv@ to be the+-- inverse of the reverse of @f@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_powmod_x_fmpz_preinv"+ fq_zech_poly_powmod_x_fmpz_preinv :: Ptr CFqZechPoly -> Ptr CFmpz -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_pow_trunc_binexp/ /res/ /poly/ /e/ /trunc/ /ctx/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ (assumed to be zero+-- padded if necessary to length @trunc@) to the power @e@. This is+-- equivalent to doing a powering followed by a truncation. We require that+-- @res@ has enough space for @trunc@ coefficients, that @trunc > 0@ and+-- that @e > 1@. Aliasing is not permitted. Uses the binary exponentiation+-- method.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_pow_trunc_binexp"+ _fq_zech_poly_pow_trunc_binexp :: Ptr CFqZech -> Ptr CFqZech -> CULong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_pow_trunc_binexp/ /res/ /poly/ /e/ /trunc/ /ctx/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ to the power @e@.+-- This is equivalent to doing a powering followed by a truncation. Uses+-- the binary exponentiation method.+foreign import ccall "fq_zech_poly.h fq_zech_poly_pow_trunc_binexp"+ fq_zech_poly_pow_trunc_binexp :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CULong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_pow_trunc/ /res/ /poly/ /e/ /trunc/ /mod/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ (assumed to be zero+-- padded if necessary to length @trunc@) to the power @e@. This is+-- equivalent to doing a powering followed by a truncation. We require that+-- @res@ has enough space for @trunc@ coefficients, that @trunc > 0@ and+-- that @e > 1@. Aliasing is not permitted.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_pow_trunc"+ _fq_zech_poly_pow_trunc :: Ptr CFqZech -> Ptr CFqZech -> CULong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_pow_trunc/ /res/ /poly/ /e/ /trunc/ /ctx/ +--+-- Sets @res@ to the low @trunc@ coefficients of @poly@ to the power @e@.+-- This is equivalent to doing a powering followed by a truncation.+foreign import ccall "fq_zech_poly.h fq_zech_poly_pow_trunc"+ fq_zech_poly_pow_trunc :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CULong -> CLong -> Ptr CFqZechCtx -> IO ()++-- Shifting --------------------------------------------------------------------++-- | /_fq_zech_poly_shift_left/ /rop/ /op/ /len/ /n/ /ctx/ +--+-- Sets @(rop, len + n)@ to @(op, len)@ shifted left by \(n\) coefficients.+-- +-- Inserts zero coefficients at the lower end. Assumes that @len@ and \(n\)+-- are positive, and that @rop@ fits @len + n@ elements. Supports aliasing+-- between @rop@ and @op@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_shift_left"+ _fq_zech_poly_shift_left :: Ptr CFqZech -> Ptr CFqZech -> CLong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_shift_left/ /rop/ /op/ /n/ /ctx/ +--+-- Sets @rop@ to @op@ shifted left by \(n\) coeffs. Zero coefficients are+-- inserted.+foreign import ccall "fq_zech_poly.h fq_zech_poly_shift_left"+ fq_zech_poly_shift_left :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_shift_right/ /rop/ /op/ /len/ /n/ /ctx/ +--+-- Sets @(rop, len - n)@ to @(op, len)@ shifted right by \(n\)+-- coefficients.+-- +-- Assumes that @len@ and \(n\) are positive, that @len > n@, and that+-- @rop@ fits @len - n@ elements. Supports aliasing between @rop@ and @op@,+-- although in this case the top coefficients of @op@ are not set to zero.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_shift_right"+ _fq_zech_poly_shift_right :: Ptr CFqZech -> Ptr CFqZech -> CLong -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_shift_right/ /rop/ /op/ /n/ /ctx/ +--+-- Sets @rop@ to @op@ shifted right by \(n\) coefficients. If \(n\) is+-- equal to or greater than the current length of @op@, @rop@ is set to the+-- zero polynomial.+foreign import ccall "fq_zech_poly.h fq_zech_poly_shift_right"+ fq_zech_poly_shift_right :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- Norms -----------------------------------------------------------------------++-- | /_fq_zech_poly_hamming_weight/ /op/ /len/ /ctx/ +--+-- Returns the number of non-zero entries in @(op, len)@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_hamming_weight"+ _fq_zech_poly_hamming_weight :: Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO CLong++-- | /fq_zech_poly_hamming_weight/ /op/ /ctx/ +--+-- Returns the number of non-zero entries in the polynomial @op@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_hamming_weight"+ fq_zech_poly_hamming_weight :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CLong++-- Euclidean division ----------------------------------------------------------++-- | /_fq_zech_poly_divrem/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Computes @(Q, lenA - lenB + 1)@, @(R, lenA)@ such that \(A = B Q + R\)+-- with \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- Assumes that the leading coefficient of \(B\) is invertible and that+-- @invB@ is its inverse.+-- +-- Assumes that \(\operatorname{len}(A), \operatorname{len}(B) > 0\).+-- Allows zero-padding in @(A, lenA)@. \(R\) and \(A\) may be aliased, but+-- apart from this no aliasing of input and output operands is allowed.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_divrem"+ _fq_zech_poly_divrem :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_divrem/ /Q/ /R/ /A/ /B/ /ctx/ +--+-- Computes \(Q\), \(R\) such that \(A = B Q + R\) with+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- Assumes that the leading coefficient of \(B\) is invertible. This can be+-- taken for granted the context is for a finite field, that is, when \(p\)+-- is prime and \(f(X)\) is irreducible.+foreign import ccall "fq_zech_poly.h fq_zech_poly_divrem"+ fq_zech_poly_divrem :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_divrem_f/ /f/ /Q/ /R/ /A/ /B/ /ctx/ +--+-- Either finds a non-trivial factor \(f\) of the modulus of @ctx@, or+-- computes \(Q\), \(R\) such that \(A = B Q + R\) and+-- \(0 \leq \operatorname{len}(R) < \operatorname{len}(B)\).+-- +-- If the leading coefficient of \(B\) is invertible, the division with+-- remainder operation is carried out, \(Q\) and \(R\) are computed+-- correctly, and \(f\) is set to \(1\). Otherwise, \(f\) is set to a+-- non-trivial factor of the modulus and \(Q\) and \(R\) are not touched.+-- +-- Assumes that \(B\) is non-zero.+foreign import ccall "fq_zech_poly.h fq_zech_poly_divrem_f"+ fq_zech_poly_divrem_f :: Ptr CFqZech -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_rem/ /R/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Sets @R@ to the remainder of the division of @(A,lenA)@ by @(B,lenB)@.+-- Assumes that the leading coefficient of @(B,lenB)@ is invertible and+-- that @invB@ is its inverse.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_rem"+ _fq_zech_poly_rem :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_rem/ /R/ /A/ /B/ /ctx/ +--+-- Sets @R@ to the remainder of the division of @A@ by @B@ in the context+-- described by @ctx@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_rem"+ fq_zech_poly_rem :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_div/ /Q/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Notationally, computes \(Q\), \(R\) such that \(A = B Q + R\) with \(0+-- \leq \operatorname{len}(R) < \operatorname{len}(B)\) but only sets+-- @(Q, lenA - lenB + 1)@.+-- +-- Allows zero-padding in \(A\) but not in \(B\). Assumes that the leading+-- coefficient of \(B\) is a unit.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_div"+ _fq_zech_poly_div :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_div/ /Q/ /A/ /B/ /ctx/ +--+-- Notionally finds polynomials \(Q\) and \(R\) such that \(A = B Q + R\)+-- with \(\operatorname{len}(R) < \operatorname{len}(B)\), but returns only+-- @Q@. If \(\operatorname{len}(B) = 0\) an exception is raised.+foreign import ccall "fq_zech_poly.h fq_zech_poly_div"+ fq_zech_poly_div :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_div_newton_n_preinv/ /Q/ /A/ /lenA/ /B/ /lenB/ /Binv/ /lenBinv/ /ctx_t/ +--+-- Notionally computes polynomials \(Q\) and \(R\) such that \(A = BQ + R\)+-- with \(\operatorname{len}(R)\) less than @lenB@, where @A@ is of length+-- @lenA@ and @B@ is of length @lenB@, but return only \(Q\).+-- +-- We require that \(Q\) have space for @lenA - lenB + 1@ coefficients and+-- assume that the leading coefficient of \(B\) is a unit. Furthermore, we+-- assume that \(Binv\) is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\).+-- +-- The algorithm used is to reverse the polynomials and divide the+-- resulting power series, then reverse the result.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_div_newton_n_preinv"+ _fq_zech_poly_div_newton_n_preinv :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> IO ()++-- | /fq_zech_poly_div_newton_n_preinv/ /Q/ /A/ /B/ /Binv/ /ctx/ +--+-- Notionally computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R) < \operatorname{len}(B)\), but returns only+-- \(Q\).+-- +-- We assume that the leading coefficient of \(B\) is a unit and that+-- \(Binv\) is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\).+-- +-- It is required that the length of \(A\) is less than or equal to 2*the+-- length of \(B\) - 2.+-- +-- The algorithm used is to reverse the polynomials and divide the+-- resulting power series, then reverse the result.+foreign import ccall "fq_zech_poly.h fq_zech_poly_div_newton_n_preinv"+ fq_zech_poly_div_newton_n_preinv :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_divrem_newton_n_preinv/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /Binv/ /lenBinv/ /ctx/ +--+-- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R)\) less than @lenB@, where \(A\) is of length+-- @lenA@ and \(B\) is of length @lenB@. We require that \(Q\) have space+-- for @lenA - lenB + 1@ coefficients. Furthermore, we assume that \(Binv\)+-- is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\). The algorithm used is to call+-- @div_newton_preinv@ and then multiply out and compute the remainder.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_divrem_newton_n_preinv"+ _fq_zech_poly_divrem_newton_n_preinv :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_divrem_newton_n_preinv/ /Q/ /R/ /A/ /B/ /Binv/ /ctx/ +--+-- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R) <+-- \operatorname{len}(B)\). We assume \(Binv\) is the inverse of the+-- reverse of \(B\) mod \(x^{\operatorname{len}(B)}\).+-- +-- It is required that the length of \(A\) is less than or equal to 2*the+-- length of \(B\) - 2.+-- +-- The algorithm used is to call @div_newton@ and then multiply out and+-- compute the remainder.+foreign import ccall "fq_zech_poly.h fq_zech_poly_divrem_newton_n_preinv"+ fq_zech_poly_divrem_newton_n_preinv :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_inv_series_newton/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ of length @n@ whose constant coefficient is invertible modulo+-- the given modulus, find a polynomial @Qinv@ of length @n@ such that+-- @Q * Qinv@ is @1@ modulo \(x^n\). Requires @n > 0@. This function can be+-- viewed as inverting a power series via Newton iteration.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_inv_series_newton"+ _fq_zech_poly_inv_series_newton :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_inv_series_newton/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ find @Qinv@ such that @Q * Qinv@ is @1@ modulo \(x^n\). The+-- constant coefficient of @Q@ must be invertible modulo the modulus of+-- @Q@. An exception is raised if this is not the case or if @n = 0@. This+-- function can be viewed as inverting a power series via Newton iteration.+foreign import ccall "fq_zech_poly.h fq_zech_poly_inv_series_newton"+ fq_zech_poly_inv_series_newton :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_inv_series/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ of length @n@ whose constant coefficient is invertible modulo+-- the given modulus, find a polynomial @Qinv@ of length @n@ such that+-- @Q * Qinv@ is @1@ modulo \(x^n\). Requires @n > 0@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_inv_series"+ _fq_zech_poly_inv_series :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_inv_series/ /Qinv/ /Q/ /n/ /ctx/ +--+-- Given @Q@ find @Qinv@ such that @Q * Qinv@ is @1@ modulo \(x^n\). The+-- constant coefficient of @Q@ must be invertible modulo the modulus of+-- @Q@. An exception is raised if this is not the case or if @n = 0@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_inv_series"+ fq_zech_poly_inv_series :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_div_series/ /Q/ /A/ /Alen/ /B/ /Blen/ /n/ /ctx/ +--+-- Set @(Q, n)@ to the quotient of the series @(A, Alen@) and @(B, Blen)@+-- assuming @Alen, Blen \<= n@. We assume the bottom coefficient of @B@ is+-- invertible.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_div_series"+ _fq_zech_poly_div_series :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CFqCtx -> IO ()++-- | /fq_zech_poly_div_series/ /Q/ /A/ /B/ /n/ /ctx/ +--+-- Set \(Q\) to the quotient of the series \(A\) by \(B\), thinking of the+-- series as though they were of length \(n\). We assume that the bottom+-- coefficient of \(B\) is invertible.+foreign import ccall "fq_zech_poly.h fq_zech_poly_div_series"+ fq_zech_poly_div_series :: Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> Ptr CFmpzModPoly -> CLong -> Ptr CFqCtx -> IO ()++-- Greatest common divisor -----------------------------------------------------++-- | /fq_zech_poly_gcd/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the greatest common divisor of @op1@ and @op2@, using the+-- either the Euclidean or HGCD algorithm. The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+foreign import ccall "fq_zech_poly.h fq_zech_poly_gcd"+ fq_zech_poly_gcd :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_gcd/ /G/ /A/ /lenA/ /B/ /lenB/ /ctx/ +--+-- Computes the GCD of \(A\) of length @lenA@ and \(B\) of length @lenB@,+-- where @lenA >= lenB > 0@ and sets \(G\) to it. The length of the GCD+-- \(G\) is returned by the function. No attempt is made to make the GCD+-- monic. It is required that \(G\) have space for @lenB@ coefficients.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_gcd"+ _fq_zech_poly_gcd :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO CLong++-- | /_fq_zech_poly_gcd_euclidean_f/ /f/ /G/ /A/ /lenA/ /B/ /lenB/ /ctx/ +--+-- Either sets \(f = 1\) and \(G\) to the greatest common divisor of+-- \((A,\operatorname{len}(A))\) and \((B, \operatorname{len}(B))\) and+-- returns its length, or sets \(f\) to a non-trivial factor of the modulus+-- of @ctx@ and leaves the contents of the vector \((G, lenB)\) undefined.+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\)+-- and that the vector \(G\) has space for sufficiently many coefficients.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_gcd_euclidean_f"+ _fq_zech_poly_gcd_euclidean_f :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO CLong++-- | /fq_zech_poly_gcd_euclidean_f/ /f/ /G/ /A/ /B/ /ctx/ +--+-- Either sets \(f = 1\) and \(G\) to the greatest common divisor of \(A\)+-- and \(B\) or sets \(f\) to a factor of the modulus of @ctx@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_gcd_euclidean_f"+ fq_zech_poly_gcd_euclidean_f :: Ptr CFqZech -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_xgcd/ /G/ /S/ /T/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Computes the GCD of \(A\) and \(B\) together with cofactors \(S\) and+-- \(T\) such that \(S A + T B = G\). Returns the length of \(G\).+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1\)+-- and \((\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)\).+-- +-- No attempt is made to make the GCD monic.+-- +-- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- coefficients. Writes \(\operatorname{len}(B)-1\) and+-- \(\operatorname{len}(A)-1\) coefficients to \(S\) and \(T\),+-- respectively. Note that, in fact,+-- \(\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)\)+-- and+-- \(\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)\).+-- +-- No aliasing of input and output operands is permitted.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_xgcd"+ _fq_zech_poly_xgcd :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFmpz -> Ptr CFqZechCtx -> IO CLong++-- | /fq_zech_poly_xgcd/ /G/ /S/ /T/ /A/ /B/ /ctx/ +--+-- Computes the GCD of \(A\) and \(B\). The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+-- +-- Polynomials @S@ and @T@ are computed such that @S*A + T*B = G@. The+-- length of @S@ will be at most @lenB@ and the length of @T@ will be at+-- most @lenA@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_xgcd"+ fq_zech_poly_xgcd :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_xgcd_euclidean_f/ /f/ /G/ /S/ /T/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Either sets \(f = 1\) and computes the GCD of \(A\) and \(B\) together+-- with cofactors \(S\) and \(T\) such that \(S A + T B = G\); otherwise,+-- sets \(f\) to a non-trivial factor of the modulus of @ctx@ and leaves+-- \(G\), \(S\), and \(T\) undefined. Returns the length of \(G\).+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1\)+-- and \((\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)\).+-- +-- No attempt is made to make the GCD monic.+-- +-- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- coefficients. Writes \(\operatorname{len}(B)-1\) and+-- \(\operatorname{len}(A)-1\) coefficients to \(S\) and \(T\),+-- respectively. Note that, in fact,+-- \(\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)\)+-- and+-- \(\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)\).+-- +-- No aliasing of input and output operands is permitted.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_xgcd_euclidean_f"+ _fq_zech_poly_xgcd_euclidean_f :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFmpz -> Ptr CFqZechCtx -> IO CLong++-- | /fq_zech_poly_xgcd_euclidean_f/ /f/ /G/ /S/ /T/ /A/ /B/ /ctx/ +--+-- Either sets \(f = 1\) and computes the GCD of \(A\) and \(B\) or sets+-- \(f\) to a non-trivial factor of the modulus of @ctx@.+-- +-- If the GCD is computed, polynomials @S@ and @T@ are computed such that+-- @S*A + T*B = G@; otherwise, they are undefined. The length of @S@ will+-- be at most @lenB@ and the length of @T@ will be at most @lenA@.+-- +-- The GCD of zero polynomials is defined to be zero, whereas the GCD of+-- the zero polynomial and some other polynomial \(P\) is defined to be+-- \(P\). Except in the case where the GCD is zero, the GCD \(G\) is made+-- monic.+foreign import ccall "fq_zech_poly.h fq_zech_poly_xgcd_euclidean_f"+ fq_zech_poly_xgcd_euclidean_f :: Ptr CFqZech -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- Divisibility testing --------------------------------------------------------++-- | /_fq_zech_poly_divides/ /Q/ /A/ /lenA/ /B/ /lenB/ /invB/ /ctx/ +--+-- Returns \(1\) if @(B, lenB)@ divides @(A, lenA)@ exactly and sets \(Q\)+-- to the quotient, otherwise returns \(0\).+-- +-- It is assumed that+-- \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\) and that \(Q\)+-- has space for \(\operatorname{len}(A) - \operatorname{len}(B) + 1\)+-- coefficients.+-- +-- Aliasing of \(Q\) with either of the inputs is not permitted.+-- +-- This function is currently unoptimised and provided for convenience+-- only.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_divides"+ _fq_zech_poly_divides :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_divides/ /Q/ /A/ /B/ /ctx/ +--+-- Returns \(1\) if \(B\) divides \(A\) exactly and sets \(Q\) to the+-- quotient, otherwise returns \(0\).+-- +-- This function is currently unoptimised and provided for convenience+-- only.+foreign import ccall "fq_zech_poly.h fq_zech_poly_divides"+ fq_zech_poly_divides :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt++-- Derivative ------------------------------------------------------------------++-- | /_fq_zech_poly_derivative/ /rop/ /op/ /len/ /ctx/ +--+-- Sets @(rop, len - 1)@ to the derivative of @(op, len)@. Also handles the+-- cases where @len@ is \(0\) or \(1\) correctly. Supports aliasing of+-- @rop@ and @op@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_derivative"+ _fq_zech_poly_derivative :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_derivative/ /rop/ /op/ /ctx/ +--+-- Sets @rop@ to the derivative of @op@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_derivative"+ fq_zech_poly_derivative :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- Square root -----------------------------------------------------------------++-- | /_fq_zech_poly_invsqrt_series/ /g/ /h/ /n/ /mod/ +--+-- Set the first \(n\) terms of \(g\) to the series expansion of+-- \(1/\sqrt{h}\). It is assumed that \(n > 0\), that \(h\) has constant+-- term 1 and that \(h\) is zero-padded as necessary to length \(n\).+-- Aliasing is not permitted.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_invsqrt_series"+ _fq_zech_poly_invsqrt_series :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_invsqrt_series/ /g/ /h/ /n/ /ctx/ +--+-- Set \(g\) to the series expansion of \(1/\sqrt{h}\) to order \(O(x^n)\).+-- It is assumed that \(h\) has constant term 1.+foreign import ccall "fq_zech_poly.h fq_zech_poly_invsqrt_series"+ fq_zech_poly_invsqrt_series :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_sqrt_series/ /g/ /h/ /n/ /ctx/ +--+-- Set the first \(n\) terms of \(g\) to the series expansion of+-- \(\sqrt{h}\). It is assumed that \(n > 0\), that \(h\) has constant term+-- 1 and that \(h\) is zero-padded as necessary to length \(n\). Aliasing+-- is not permitted.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_sqrt_series"+ _fq_zech_poly_sqrt_series :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_sqrt_series/ /g/ /h/ /n/ /ctx/ +--+-- Set \(g\) to the series expansion of \(\sqrt{h}\) to order \(O(x^n)\).+-- It is assumed that \(h\) has constant term 1.+foreign import ccall "fq_zech_poly.h fq_zech_poly_sqrt_series"+ fq_zech_poly_sqrt_series :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_sqrt/ /s/ /p/ /n/ /mod/ +--+-- If @(p, n)@ is a perfect square, sets @(s, n \/ 2 + 1)@ to a square root+-- of \(p\) and returns 1. Otherwise returns 0.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_sqrt"+ _fq_zech_poly_sqrt :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_sqrt/ /s/ /p/ /mod/ +--+-- If \(p\) is a perfect square, sets \(s\) to a square root of \(p\) and+-- returns 1. Otherwise returns 0.+foreign import ccall "fq_zech_poly.h fq_zech_poly_sqrt"+ fq_zech_poly_sqrt :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt++-- Evaluation ------------------------------------------------------------------++-- | /_fq_zech_poly_evaluate_fq_zech/ /rop/ /op/ /len/ /a/ /ctx/ +--+-- Sets @rop@ to @(op, len)@ evaluated at \(a\).+-- +-- Supports zero padding. There are no restrictions on @len@, that is,+-- @len@ is allowed to be zero, too.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_evaluate_fq_zech"+ _fq_zech_poly_evaluate_fq_zech :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_evaluate_fq_zech/ /rop/ /f/ /a/ /ctx/ +--+-- Sets @rop@ to the value of \(f(a)\).+-- +-- As the coefficient ring \(\mathbf{F}_q\) is finite, Horner\'s method is+-- sufficient.+foreign import ccall "fq_zech_poly.h fq_zech_poly_evaluate_fq_zech"+ fq_zech_poly_evaluate_fq_zech :: Ptr CFqZech -> Ptr CFqZechPoly -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- Composition -----------------------------------------------------------------++-- | /_fq_zech_poly_compose/ /rop/ /op1/ /len1/ /op2/ /len2/ /ctx/ +--+-- Sets @rop@ to the composition of @(op1, len1)@ and @(op2, len2)@.+-- +-- Assumes that @rop@ has space for @(len1-1)*(len2-1) + 1@ coefficients.+-- Assumes that @op1@ and @op2@ are non-zero polynomials. Does not support+-- aliasing between any of the inputs and the output.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_compose"+ _fq_zech_poly_compose :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_compose/ /rop/ /op1/ /op2/ /ctx/ +--+-- Sets @rop@ to the composition of @op1@ and @op2@. To be precise about+-- the order of composition, denoting @rop@, @op1@, and @op2@ by \(f\),+-- \(g\), and \(h\), respectively, sets \(f(t) = g(h(t))\).+foreign import ccall "fq_zech_poly.h fq_zech_poly_compose"+ fq_zech_poly_compose :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_compose_mod_horner/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). The output is not allowed+-- to be aliased with any of the inputs.+-- +-- The algorithm used is Horner\'s rule.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_compose_mod_horner"+ _fq_zech_poly_compose_mod_horner :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_compose_mod_horner/ /res/ /f/ /g/ /h/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero. The algorithm used is Horner\'s rule.+foreign import ccall "fq_zech_poly.h fq_zech_poly_compose_mod_horner"+ fq_zech_poly_compose_mod_horner :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_compose_mod_horner_preinv/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /hinv/ /lenhiv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+-- +-- The algorithm used is Horner\'s rule.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_compose_mod_horner_preinv"+ _fq_zech_poly_compose_mod_horner_preinv :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_compose_mod_horner_preinv/ /res/ /f/ /g/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+-- The algorithm used is Horner\'s rule.+foreign import ccall "fq_zech_poly.h fq_zech_poly_compose_mod_horner_preinv"+ fq_zech_poly_compose_mod_horner_preinv :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_compose_mod_brent_kung/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). The output is not+-- allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_compose_mod_brent_kung"+ _fq_zech_poly_compose_mod_brent_kung :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_compose_mod_brent_kung/ /res/ /f/ /g/ /h/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\). The+-- algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_zech_poly.h fq_zech_poly_compose_mod_brent_kung"+ fq_zech_poly_compose_mod_brent_kung :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_compose_mod_brent_kung_preinv/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /hinv/ /lenhiv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_compose_mod_brent_kung_preinv"+ _fq_zech_poly_compose_mod_brent_kung_preinv :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_compose_mod_brent_kung_preinv/ /res/ /f/ /g/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_zech_poly.h fq_zech_poly_compose_mod_brent_kung_preinv"+ fq_zech_poly_compose_mod_brent_kung_preinv :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_compose_mod/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). The output is not allowed+-- to be aliased with any of the inputs.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_compose_mod"+ _fq_zech_poly_compose_mod :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_compose_mod/ /res/ /f/ /g/ /h/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero.+foreign import ccall "fq_zech_poly.h fq_zech_poly_compose_mod"+ fq_zech_poly_compose_mod :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_compose_mod_preinv/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /hinv/ /lenhiv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_compose_mod_preinv"+ _fq_zech_poly_compose_mod_preinv :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_compose_mod_preinv/ /res/ /f/ /g/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_compose_mod_preinv"+ fq_zech_poly_compose_mod_preinv :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_reduce_matrix_mod_poly/ /A/ /B/ /f/ /ctx/ +--+-- Sets the ith row of @A@ to the reduction of the ith row of \(B\) modulo+-- \(f\) for \(i=1,\ldots,\sqrt{\deg(f)}\). We require \(B\) to be at least+-- a \(\sqrt{\deg(f)}\times \deg(f)\) matrix and \(f\) to be nonzero.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_reduce_matrix_mod_poly"+ _fq_zech_poly_reduce_matrix_mod_poly :: Ptr CFqZechMat -> Ptr CFqZechMat -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_precompute_matrix/ /A/ /f/ /g/ /leng/ /ginv/ /lenginv/ /ctx/ +--+-- Sets the ith row of @A@ to \(f^i\) modulo \(g\) for+-- \(i=1,\ldots,\sqrt{\deg(g)}\). We require \(A\) to be a+-- \(\sqrt{\deg(g)}\times \deg(g)\) matrix. We require @ginv@ to be the+-- inverse of the reverse of @g@ and \(g\) to be nonzero.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_precompute_matrix"+ _fq_zech_poly_precompute_matrix :: Ptr CFqZechMat -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_precompute_matrix/ /A/ /f/ /g/ /ginv/ /ctx/ +--+-- Sets the ith row of @A@ to \(f^i\) modulo \(g\) for+-- \(i=1,\ldots,\sqrt{\deg(g)}\). We require \(A\) to be a+-- \(\sqrt{\deg(g)}\times \deg(g)\) matrix. We require @ginv@ to be the+-- inverse of the reverse of @g@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_precompute_matrix"+ fq_zech_poly_precompute_matrix :: Ptr CFqZechMat -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_poly_compose_mod_brent_kung_precomp_preinv/ /res/ /f/ /lenf/ /A/ /h/ /lenh/ /hinv/ /lenhinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero. We require that the ith row of \(A\) contains \(g^i\)+-- for \(i=1,\ldots,\sqrt{\deg(h)}\), i.e. \(A\) is a+-- \(\sqrt{\deg(h)}\times \deg(h)\) matrix. We also require that the length+-- of \(f\) is less than the length of \(h\). Furthermore, we require+-- @hinv@ to be the inverse of the reverse of @h@. The output is not+-- allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_compose_mod_brent_kung_precomp_preinv"+ _fq_zech_poly_compose_mod_brent_kung_precomp_preinv :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechMat -> Ptr CFqZech -> CLong -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_compose_mod_brent_kung_precomp_preinv/ /res/ /f/ /A/ /h/ /hinv/ /ctx/ +--+-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that the+-- ith row of \(A\) contains \(g^i\) for \(i=1,\ldots,\sqrt{\deg(h)}\),+-- i.e. \(A\) is a \(\sqrt{\deg(h)}\times+-- \deg(h)\) matrix. We require that \(h\) is nonzero and that \(f\) has+-- smaller degree than \(h\). Furthermore, we require @hinv@ to be the+-- inverse of the reverse of @h@. This version of Brent-Kung modular+-- composition is particularly useful if one has to perform several modular+-- composition of the form \(f(g)\) modulo \(h\) for fixed \(g\) and \(h\).+foreign import ccall "fq_zech_poly.h fq_zech_poly_compose_mod_brent_kung_precomp_preinv"+ fq_zech_poly_compose_mod_brent_kung_precomp_preinv :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechMat -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- Output ----------------------------------------------------------------------++-- | /_fq_zech_poly_fprint_pretty/ /file/ /poly/ /len/ /x/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to the stream @file@,+-- using the string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_fprint_pretty"+ _fq_zech_poly_fprint_pretty :: Ptr CFile -> Ptr CFqZech -> CLong -> CString -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_fprint_pretty/ /file/ /poly/ /x/ /ctx/ +--+-- Prints the pretty representation of @poly@ to the stream @file@, using+-- the string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_zech_poly.h fq_zech_poly_fprint_pretty"+ fq_zech_poly_fprint_pretty :: Ptr CFile -> Ptr CFqZechPoly -> CString -> Ptr CFqZechCtx -> IO CInt++-- | /_fq_zech_poly_print_pretty/ /poly/ /len/ /x/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to @stdout@, using the+-- string @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_print_pretty"+ _fq_zech_poly_print_pretty :: Ptr CFqZech -> CLong -> CString -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_print_pretty/ /poly/ /x/ /ctx/ +--+-- Prints the pretty representation of @poly@ to @stdout@, using the string+-- @x@ to represent the indeterminate.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+fq_zech_poly_print_pretty :: Ptr CFqZechPoly -> CString -> Ptr CFqZechCtx -> IO CInt+fq_zech_poly_print_pretty poly x ctx = do+ printCStr (\poly -> fq_zech_poly_get_str_pretty poly x ctx) poly+++-- | /_fq_zech_poly_fprint/ /file/ /poly/ /len/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_fprint"+ _fq_zech_poly_fprint :: Ptr CFile -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_fprint/ /file/ /poly/ /ctx/ +--+-- Prints the pretty representation of @poly@ to the stream @file@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_zech_poly.h fq_zech_poly_fprint"+ fq_zech_poly_fprint :: Ptr CFile -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt++-- | /_fq_zech_poly_print/ /poly/ /len/ /ctx/ +--+-- Prints the pretty representation of @(poly, len)@ to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_print"+ _fq_zech_poly_print :: Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_print/ /poly/ /ctx/ +--+-- Prints the representation of @poly@ to @stdout@.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+fq_zech_poly_print :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt+fq_zech_poly_print poly ctx = do+ printCStr (\poly -> fq_zech_poly_get_str poly ctx) poly+ +-- | /_fq_zech_poly_get_str/ /poly/ /len/ /ctx/ +--+-- Returns the plain FLINT string representation of the polynomial+-- @(poly, len)@.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_get_str"+ _fq_zech_poly_get_str :: Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO CString++-- | /fq_zech_poly_get_str/ /poly/ /ctx/ +--+-- Returns the plain FLINT string representation of the polynomial @poly@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_get_str"+ fq_zech_poly_get_str :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CString++-- | /_fq_zech_poly_get_str_pretty/ /poly/ /len/ /x/ /ctx/ +--+-- Returns a pretty representation of the polynomial @(poly, len)@ using+-- the null-terminated string @x@ as the variable name.+foreign import ccall "fq_zech_poly.h _fq_zech_poly_get_str_pretty"+ _fq_zech_poly_get_str_pretty :: Ptr CFqZech -> CLong -> CString -> Ptr CFqZechCtx -> IO CString++-- | /fq_zech_poly_get_str_pretty/ /poly/ /x/ /ctx/ +--+-- Returns a pretty representation of the polynomial @poly@ using the+-- null-terminated string @x@ as the variable name+foreign import ccall "fq_zech_poly.h fq_zech_poly_get_str_pretty"+ fq_zech_poly_get_str_pretty :: Ptr CFqZechPoly -> CString -> Ptr CFqZechCtx -> IO CString++-- Inflation and deflation -----------------------------------------------------++-- | /fq_zech_poly_inflate/ /result/ /input/ /inflation/ /ctx/ +--+-- Sets @result@ to the inflated polynomial \(p(x^n)\) where \(p\) is given+-- by @input@ and \(n\) is given by @inflation@.+foreign import ccall "fq_zech_poly.h fq_zech_poly_inflate"+ fq_zech_poly_inflate :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CULong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_deflate/ /result/ /input/ /deflation/ /ctx/ +--+-- Sets @result@ to the deflated polynomial \(p(x^{1/n})\) where \(p\) is+-- given by @input@ and \(n\) is given by @deflation@. Requires \(n > 0\).+foreign import ccall "fq_zech_poly.h fq_zech_poly_deflate"+ fq_zech_poly_deflate :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> CULong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_deflation/ /input/ /ctx/ +--+-- Returns the largest integer by which @input@ can be deflated. As special+-- cases, returns 0 if @input@ is the zero polynomial and 1 of @input@ is a+-- constant polynomial.+foreign import ccall "fq_zech_poly.h fq_zech_poly_deflation"+ fq_zech_poly_deflation :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CULong+
+ src/Data/Number/Flint/Fq/Zech/Poly/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Fq.Zech.Poly.Factor (+ module Data.Number.Flint.Fq.Zech.Poly.Factor.FFI+ ) where++import Data.Number.Flint.Fq.Zech.Poly.Factor.FFI
+ src/Data/Number/Flint/Fq/Zech/Poly/Factor/FFI.hsc view
@@ -0,0 +1,389 @@+{-|+module : Data.Number.Flint.Fq.Zech.Poly.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Zech.Poly.Factor.FFI (+ -- * Factorisation of univariate polynomials over finite fields+ -- (Zech logarithm representation)+ FqZechPolyFactor (..)+ , CFqZechPolyFactor (..)+ , newFqZechPolyFactor+ , withFqZechPolyFactor+ -- Memory Management+ , fq_zech_poly_factor_init+ , fq_zech_poly_factor_clear+ , fq_zech_poly_factor_realloc+ , fq_zech_poly_factor_fit_length+ -- * Basic Operations+ , fq_zech_poly_factor_set+ , fq_zech_poly_factor_print_pretty+ , fq_zech_poly_factor_print+ , fq_zech_poly_factor_insert+ , fq_zech_poly_factor_concat+ , fq_zech_poly_factor_pow+ , fq_zech_poly_remove+ -- * Irreducibility Testing+ , fq_zech_poly_is_irreducible+ , fq_zech_poly_is_irreducible_ddf+ , fq_zech_poly_is_irreducible_ben_or+ , _fq_zech_poly_is_squarefree+ , fq_zech_poly_is_squarefree+ -- * Factorisation+ , fq_zech_poly_factor_equal_deg_prob+ , fq_zech_poly_factor_equal_deg+ , fq_zech_poly_factor_split_single+ , fq_zech_poly_factor_distinct_deg+ , fq_zech_poly_factor_squarefree+ , fq_zech_poly_factor+ , fq_zech_poly_factor_cantor_zassenhaus+ , fq_zech_poly_factor_kaltofen_shoup+ , fq_zech_poly_factor_berlekamp+ , fq_zech_poly_factor_with_berlekamp+ , fq_zech_poly_factor_with_cantor_zassenhaus+ , fq_zech_poly_factor_with_kaltofen_shoup+ , fq_zech_poly_iterated_frobenius_preinv+ -- * Root Finding+ , fq_zech_poly_roots+) where++-- Factorisation of univariate polynomials over finite fields (Zech+-- logarithm representation)++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Marshal.Array ( advancePtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint++import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mod.Poly++import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.NMod.Mat++import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.Types++import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Mat++import Data.Number.Flint.Fq.Zech+import Data.Number.Flint.Fq.Zech.Poly+import Data.Number.Flint.Fq.Zech.Types++#include <flint/flint.h>+#include <flint/fq_zech_poly.h>++-- fq_zech_poly_factor_t -------------------------------------------------------++instance Storable CFqZechPolyFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fq_zech_poly_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fq_zech_poly_factor_t}+ peek ptr = CFqZechPolyFactor+ <$> #{peek fq_zech_poly_factor_struct, poly } ptr+ <*> #{peek fq_zech_poly_factor_struct, exp } ptr+ <*> #{peek fq_zech_poly_factor_struct, num } ptr+ <*> #{peek fq_zech_poly_factor_struct, alloc} ptr+ poke = undefined++newFqZechPolyFactor ctx@(FqZechCtx ftx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFqZechCtx ctx $ \ctx -> do+ fq_zech_poly_factor_init x ctx+ addForeignPtrFinalizerEnv p_fq_zech_poly_factor_clear x ftx+ return $ FqZechPolyFactor x++{-# INLINE withFqZechPolyFactor #-}+withFqZechPolyFactor (FqZechPolyFactor x) f = do+ withForeignPtr x $ \px -> f px >>= return . (FqZechPolyFactor x,)++-- Memory Management -----------------------------------------------------------++-- | /fq_zech_poly_factor_init/ /fac/ /ctx/ +--+-- Initialises @fac@ for use. An @fq_zech_poly_factor_t@ represents a+-- polynomial in factorised form as a product of polynomials with+-- associated exponents.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_init"+ fq_zech_poly_factor_init :: Ptr CFqZechPolyFactor -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_clear/ /fac/ /ctx/ +--+-- Frees all memory associated with @fac@.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_clear"+ fq_zech_poly_factor_clear :: Ptr CFqZechPolyFactor -> Ptr CFqZechCtx -> IO ()++foreign import ccall "fq_zech_poly_factor.h &fq_zech_poly_factor_clear"+ p_fq_zech_poly_factor_clear :: FunPtr (Ptr CFqZechPolyFactor -> Ptr CFqZechCtx -> IO ())++-- | /fq_zech_poly_factor_realloc/ /fac/ /alloc/ /ctx/ +--+-- Reallocates the factor structure to provide space for precisely @alloc@+-- factors.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_realloc"+ fq_zech_poly_factor_realloc :: Ptr CFqZechPolyFactor -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_fit_length/ /fac/ /len/ /ctx/ +--+-- Ensures that the factor structure has space for at least @len@ factors.+-- This function takes care of the case of repeated calls by always at+-- least doubling the number of factors the structure can hold.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_fit_length"+ fq_zech_poly_factor_fit_length :: Ptr CFqZechPolyFactor -> CLong -> Ptr CFqZechCtx -> IO ()++-- Basic Operations ------------------------------------------------------------++-- | /fq_zech_poly_factor_set/ /res/ /fac/ /ctx/ +--+-- Sets @res@ to the same factorisation as @fac@.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_set"+ fq_zech_poly_factor_set :: Ptr CFqZechPolyFactor -> Ptr CFqZechPolyFactor -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_print_pretty/ /fac/ /var/ /ctx/ +--+-- Pretty-prints the entries of @fac@ to standard output.+fq_zech_poly_factor_print_pretty :: Ptr CFqZechPolyFactor -> CString -> Ptr CFqZechCtx -> IO ()+fq_zech_poly_factor_print_pretty fac var ctx = do+ CFqZechPolyFactor poly exp num alloc <- peek fac+ forM_ [0 .. fromIntegral num - 1] $ \j -> do+ fq_zech_poly_print_pretty (poly `advancePtr` j) var ctx+ putStr " ^ "+ e <- peek (exp `advancePtr` j)+ putStrLn $ show e + +-- | /fq_zech_poly_factor_print/ /fac/ /ctx/ +--+-- Prints the entries of @fac@ to standard output.+fq_zech_poly_factor_print :: Ptr CFqZechPolyFactor -> Ptr CFqZechCtx -> IO ()+fq_zech_poly_factor_print fac ctx = do+ CFqZechPolyFactor poly exp num alloc <- peek fac+ forM_ [0 .. fromIntegral num - 1] $ \j -> do+ fq_zech_poly_print (poly `advancePtr` j) ctx+ putStr " ^ "+ e <- peek (exp `advancePtr` j)+ putStrLn $ show e+ +-- | /fq_zech_poly_factor_insert/ /fac/ /poly/ /exp/ /ctx/ +--+-- Inserts the factor @poly@ with multiplicity @exp@ into the factorisation+-- @fac@.+-- +-- If @fac@ already contains @poly@, then @exp@ simply gets added to the+-- exponent of the existing entry.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_insert"+ fq_zech_poly_factor_insert :: Ptr CFqZechPolyFactor -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_concat/ /res/ /fac/ /ctx/ +--+-- Concatenates two factorisations.+-- +-- This is equivalent to calling @fq_zech_poly_factor_insert()@ repeatedly+-- with the individual factors of @fac@.+-- +-- Does not support aliasing between @res@ and @fac@.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_concat"+ fq_zech_poly_factor_concat :: Ptr CFqZechPolyFactor -> Ptr CFqZechPolyFactor -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_pow/ /fac/ /exp/ /ctx/ +--+-- Raises @fac@ to the power @exp@.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_pow"+ fq_zech_poly_factor_pow :: Ptr CFqZechPolyFactor -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_remove/ /f/ /p/ /ctx/ +--+-- Removes the highest possible power of @p@ from @f@ and returns the+-- exponent.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_remove"+ fq_zech_poly_remove :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CULong++-- Irreducibility Testing ------------------------------------------------------++-- | /fq_zech_poly_is_irreducible/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_is_irreducible"+ fq_zech_poly_is_irreducible :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_is_irreducible_ddf/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+-- Uses fast distinct-degree factorisation.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_is_irreducible_ddf"+ fq_zech_poly_is_irreducible_ddf :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_is_irreducible_ben_or/ /f/ /ctx/ +--+-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+-- Uses Ben-Or\'s irreducibility test.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_is_irreducible_ben_or"+ fq_zech_poly_is_irreducible_ben_or :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt++-- | /_fq_zech_poly_is_squarefree/ /f/ /len/ /ctx/ +--+-- Returns 1 if @(f, len)@ is squarefree, and 0 otherwise. As a special+-- case, the zero polynomial is not considered squarefree. There are no+-- restrictions on the length.+foreign import ccall "fq_zech_poly_factor.h _fq_zech_poly_is_squarefree"+ _fq_zech_poly_is_squarefree :: Ptr (Ptr CFqZech) -> CLong -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_is_squarefree/ /f/ /ctx/ +--+-- Returns 1 if @f@ is squarefree, and 0 otherwise. As a special case, the+-- zero polynomial is not considered squarefree.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_is_squarefree"+ fq_zech_poly_is_squarefree :: Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO CInt++-- Factorisation ---------------------------------------------------------------++-- | /fq_zech_poly_factor_equal_deg_prob/ /factor/ /state/ /pol/ /d/ /ctx/ +--+-- Probabilistic equal degree factorisation of @pol@ into irreducible+-- factors of degree @d@. If it passes, a factor is placed in factor and 1+-- is returned, otherwise 0 is returned and the value of factor is+-- undetermined.+-- +-- Requires that @pol@ be monic, non-constant and squarefree.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_equal_deg_prob"+ fq_zech_poly_factor_equal_deg_prob :: Ptr CFqZechPoly -> Ptr CFRandState -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO CInt++-- | /fq_zech_poly_factor_equal_deg/ /factors/ /pol/ /d/ /ctx/ +--+-- Assuming @pol@ is a product of irreducible factors all of degree @d@,+-- finds all those factors and places them in factors. Requires that @pol@+-- be monic, non-constant and squarefree.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_equal_deg"+ fq_zech_poly_factor_equal_deg :: Ptr CFqZechPolyFactor -> Ptr CFqZechPoly -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_split_single/ /linfactor/ /input/ /ctx/ +--+-- Assuming @input@ is a product of factors all of degree 1, finds a single+-- linear factor of @input@ and places it in @linfactor@. Requires that+-- @input@ be monic and non-constant.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_split_single"+ fq_zech_poly_factor_split_single :: Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_distinct_deg/ /res/ /poly/ /degs/ /ctx/ +--+-- Factorises a monic non-constant squarefree polynomial @poly@ of degree+-- \(n\) into factors \(f[d]\) such that for \(1 \leq d \leq n\) \(f[d]\)+-- is the product of the monic irreducible factors of @poly@ of degree+-- \(d\). Factors are stored in @res@, associated powers of irreducible+-- polynomials are stored in @degs@ in the same order as factors.+-- +-- Requires that @degs@ have enough space for irreducible polynomials\'+-- powers (maximum space required is \(n * sizeof(slong)\)).+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_distinct_deg"+ fq_zech_poly_factor_distinct_deg :: Ptr CFqZechPolyFactor -> Ptr CFqZechPoly -> Ptr (Ptr CLong) -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_squarefree/ /res/ /f/ /ctx/ +--+-- Sets @res@ to a squarefree factorization of @f@.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_squarefree"+ fq_zech_poly_factor_squarefree :: Ptr CFqZechPolyFactor -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor/ /res/ /lead/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- choosing the best algorithm for given modulo and degree. The output+-- @lead@ is set to the leading coefficient of \(f\) upon return. Choice of+-- algorithm is based on heuristic measurements.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor"+ fq_zech_poly_factor :: Ptr CFqZechPolyFactor -> Ptr CFqZech -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_cantor_zassenhaus/ /res/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the Cantor-Zassenhaus algorithm.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_cantor_zassenhaus"+ fq_zech_poly_factor_cantor_zassenhaus :: Ptr CFqZechPolyFactor -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_kaltofen_shoup/ /res/ /poly/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the fast version of Cantor-Zassenhaus algorithm proposed by+-- Kaltofen and Shoup (1998). More precisely this algorithm uses a “baby+-- step\/giant step” strategy for the distinct-degree factorization step.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_kaltofen_shoup"+ fq_zech_poly_factor_kaltofen_shoup :: Ptr CFqZechPolyFactor -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_berlekamp/ /factors/ /f/ /ctx/ +--+-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the Berlekamp algorithm.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_berlekamp"+ fq_zech_poly_factor_berlekamp :: Ptr CFqZechPolyFactor -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_with_berlekamp/ /res/ /leading_coeff/ /f/ /ctx/ +--+-- Factorises a general polynomial @f@ into monic irreducible factors and+-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is+-- the zero polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Berlekamp on all the+-- individual square-free factors.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_with_berlekamp"+ fq_zech_poly_factor_with_berlekamp :: Ptr CFqZechPolyFactor -> Ptr CFqZech -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_with_cantor_zassenhaus/ /res/ /leading_coeff/ /f/ /ctx/ +--+-- Factorises a general polynomial @f@ into monic irreducible factors and+-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is+-- the zero polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Cantor-Zassenhaus on all the+-- individual square-free factors.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_with_cantor_zassenhaus"+ fq_zech_poly_factor_with_cantor_zassenhaus :: Ptr CFqZechPolyFactor -> Ptr CFqZech -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_factor_with_kaltofen_shoup/ /res/ /leading_coeff/ /f/ /ctx/ +--+-- Factorises a general polynomial @f@ into monic irreducible factors and+-- sets @leading_coeff@ to the leading coefficient of @f@, or 0 if @f@ is+-- the zero polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Kaltofen-Shoup on all the+-- individual square-free factors.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_factor_with_kaltofen_shoup"+ fq_zech_poly_factor_with_kaltofen_shoup :: Ptr CFqZechPolyFactor -> Ptr CFqZech -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- | /fq_zech_poly_iterated_frobenius_preinv/ /rop/ /n/ /v/ /vinv/ /ctx/ +--+-- Sets @rop[i]@ to be \(x^{q^i} \bmod v\) for \(0 \le i < n\).+-- +-- It is required that @vinv@ is the inverse of the reverse of @v@ mod+-- @x^lenv@.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_iterated_frobenius_preinv"+ fq_zech_poly_iterated_frobenius_preinv :: Ptr (Ptr CFqZechPoly) -> CLong -> Ptr CFqZechPoly -> Ptr CFqZechPoly -> Ptr CFqZechCtx -> IO ()++-- Root Finding ----------------------------------------------------------------++-- | /fq_zech_poly_roots/ /r/ /f/ /with_multiplicity/ /ctx/ +--+-- Fill \(r\) with factors of the form \(x - r_i\) where the \(r_i\) are+-- the distinct roots of a nonzero \(f\) in \(F_q\). If+-- \(with\_multiplicity\) is zero, the exponent \(e_i\) of the factor+-- \(x - r_i\) is \(1\). Otherwise, it is the largest \(e_i\) such that+-- \((x-r_i)^e_i\) divides \(f\). This function throws if \(f\) is zero,+-- but is otherwise always successful.+foreign import ccall "fq_zech_poly_factor.h fq_zech_poly_roots"+ fq_zech_poly_roots :: Ptr CFqZechPolyFactor -> Ptr CFqZechPoly -> CInt -> Ptr CFqZechCtx -> IO ()+
+ src/Data/Number/Flint/Fq/Zech/Types.hs view
@@ -0,0 +1,13 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+{- | +module : Data.Number.Flint.Fq.Zech.Types+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Fq.Zech.Types (+ module Data.Number.Flint.Fq.Zech.Types.FFI,+) where++import Data.Number.Flint.Fq.Zech.Types.FFI
+ src/Data/Number/Flint/Fq/Zech/Types/FFI.hsc view
@@ -0,0 +1,39 @@+{-|+module : Data.Number.Flint.Fq.Zech.Types.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Zech.Types.FFI where++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types++import Data.Number.Flint.Flint++-- fq_zech_t -------------------------------------------------------------------++data FqZech = FqZech {-# UNPACK #-} !(ForeignPtr CFqZech)+type CFqZech = CFlint FqZech++-- fq_zech_ctx_t ---------------------------------------------------------------++data FqZechCtx = FqZechCtx {-# UNPACK #-} !(ForeignPtr CFqZechCtx)+type CFqZechCtx = CFlint FqZechCtx++-- fq_zech_poly_t --------------------------------------------------------------++data FqZechPoly = FqZechPoly {-# UNPACK #-} !(ForeignPtr CFqZechPoly)+type CFqZechPoly = CFlint FqZechPoly++-- fq_zech_poly_factor_t -------------------------------------------------------++data FqZechPolyFactor = FqZechPolyFactor {-# UNPACK #-} !(ForeignPtr CFqZechPolyFactor)+data CFqZechPolyFactor = CFqZechPolyFactor (Ptr CFqZechPoly) (Ptr CLong) CLong CLong++-- fq_zech_mat_t ---------------------------------------------------------------++data FqZechMat = FqZechMat {-# UNPACK #-} !(ForeignPtr CFqZechMat)+data CFqZechMat = CFqZechMat (Ptr CFqZech) CLong CLong (Ptr (Ptr CFqZech))+
+ src/Data/Number/Flint/Fq/Zech/Vec.hs view
@@ -0,0 +1,12 @@+{- | +module : Data.Number.Flint.Fq.Zech.Vec+copyright : (c) 2022 Hartmut Monien+license : MIT-style (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Fq.Zech.Vec (+ module Data.Number.Flint.Fq.Zech.Vec.FFI,+) where++import Data.Number.Flint.Fq.Zech.Vec.FFI
+ src/Data/Number/Flint/Fq/Zech/Vec/FFI.hsc view
@@ -0,0 +1,180 @@+{-|+module : Data.Number.Flint.Fq.Zech.Vec.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Fq.Zech.Vec.FFI (+ -- * Vectors over finite fields (Zech logarithm representation)+ -- * Memory management+ _fq_zech_vec_init+ , _fq_zech_vec_clear+ -- * Randomisation+ , _fq_zech_vec_randtest+ -- * Input and output+ , _fq_zech_vec_fprint+ , _fq_zech_vec_print+ -- * Assignment and basic manipulation+ , _fq_zech_vec_set+ , _fq_zech_vec_swap+ , _fq_zech_vec_zero+ , _fq_zech_vec_neg+ -- * Comparison+ , _fq_zech_vec_equal+ , _fq_zech_vec_is_zero+ -- * Addition and subtraction+ , _fq_zech_vec_add+ , _fq_zech_vec_sub+ -- * Scalar multiplication and division+ , _fq_zech_vec_scalar_addmul_fq_zech+ , _fq_zech_vec_scalar_submul_fq_zech+ -- * Dot products+ , _fq_zech_vec_dot+) where ++-- Vectors over finite fields (Zech logarithm representation) ------------------++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr )+import Foreign.Storable++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.NMod.Mat+import Data.Number.Flint.Fq+import Data.Number.Flint.Fq.NMod+import Data.Number.Flint.Fq.NMod.Mat+import Data.Number.Flint.Fq.Zech++#include <flint/flint.h>+#include <flint/fq_zech.h>+#include <flint/fq_zech_vec.h>++-- Memory management -----------------------------------------------------------++-- | /_fq_zech_vec_init/ /len/ /ctx/ +--+-- Returns an initialised vector of @fq_zech@\'s of given length.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_init"+ _fq_zech_vec_init :: CLong -> Ptr CFqZechCtx -> IO (Ptr CFqZech)++-- | /_fq_zech_vec_clear/ /vec/ /len/ /ctx/ +--+-- Clears the entries of @(vec, len)@ and frees the space allocated for+-- @vec@.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_clear"+ _fq_zech_vec_clear :: Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- Randomisation ---------------------------------------------------------------++-- | /_fq_zech_vec_randtest/ /f/ /state/ /len/ /ctx/ +--+-- Sets the entries of a vector of the given length to elements of the+-- finite field.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_randtest"+ _fq_zech_vec_randtest :: Ptr CFqZech -> Ptr CFRandState -> CLong -> Ptr CFqZechCtx -> IO ()++-- Input and output ------------------------------------------------------------++-- | /_fq_zech_vec_fprint/ /file/ /vec/ /len/ /ctx/ +--+-- Prints the vector of given length to the stream @file@. The format is+-- the length followed by two spaces, then a space separated list of+-- coefficients. If the length is zero, only \(0\) is printed.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_fprint"+ _fq_zech_vec_fprint :: Ptr CFile -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO CInt++-- | /_fq_zech_vec_print/ /vec/ /len/ /ctx/ +--+-- Prints the vector of given length to @stdout@.+-- +-- For further details, see @_fq_zech_vec_fprint()@.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_print"+ _fq_zech_vec_print :: Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO CInt++-- Assignment and basic manipulation -------------------------------------------++-- | /_fq_zech_vec_set/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Makes a copy of @(vec2, len2)@ into @vec1@.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_set"+ _fq_zech_vec_set :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_vec_swap/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Swaps the elements in @(vec1, len2)@ and @(vec2, len2)@.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_swap"+ _fq_zech_vec_swap :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_vec_zero/ /vec/ /len/ /ctx/ +--+-- Zeros the entries of @(vec, len)@.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_zero"+ _fq_zech_vec_zero :: Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_vec_neg/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Negates @(vec2, len2)@ and places it into @vec1@.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_neg"+ _fq_zech_vec_neg :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /_fq_zech_vec_equal/ /vec1/ /vec2/ /len/ /ctx/ +--+-- Compares two vectors of the given length and returns \(1\) if they are+-- equal, otherwise returns \(0\).+foreign import ccall "fq_zech_vec.h _fq_zech_vec_equal"+ _fq_zech_vec_equal :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO CInt++-- | /_fq_zech_vec_is_zero/ /vec/ /len/ /ctx/ +--+-- Returns \(1\) if @(vec, len)@ is zero, and \(0\) otherwise.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_is_zero"+ _fq_zech_vec_is_zero :: Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /_fq_zech_vec_add/ /res/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Sets @(res, len2)@ to the sum of @(vec1, len2)@ and @(vec2, len2)@.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_add"+ _fq_zech_vec_add :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_vec_sub/ /res/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Sets @(res, len2)@ to @(vec1, len2)@ minus @(vec2, len2)@.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_sub"+ _fq_zech_vec_sub :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()++-- Scalar multiplication and division ------------------------------------------++-- | /_fq_zech_vec_scalar_addmul_fq_zech/ /vec1/ /vec2/ /len2/ /c/ /ctx/ +--+-- Adds @(vec2, len2)@ times \(c\) to @(vec1, len2)@, where \(c\) is a+-- @fq_zech_t@.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_scalar_addmul_fq_zech"+ _fq_zech_vec_scalar_addmul_fq_zech :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- | /_fq_zech_vec_scalar_submul_fq_zech/ /vec1/ /vec2/ /len2/ /c/ /ctx/ +--+-- Subtracts @(vec2, len2)@ times \(c\) from @(vec1, len2)@, where \(c\) is+-- a @fq_zech_t@.+foreign import ccall "fq_zech_vec.h _fq_zech_vec_scalar_submul_fq_zech"+ _fq_zech_vec_scalar_submul_fq_zech :: Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZech -> Ptr CFqZechCtx -> IO ()++-- Dot products ----------------------------------------------------------------++-- | /_fq_zech_vec_dot/ /res/ /vec1/ /vec2/ /len2/ /ctx/ +--+-- Sets @res@ to the dot product of (@vec1@, @len@) and (@vec2@, @len@).+foreign import ccall "fq_zech_vec.h _fq_zech_vec_dot"+ _fq_zech_vec_dot :: Ptr CFqZech -> Ptr CFqZech -> Ptr CFqZech -> CLong -> Ptr CFqZechCtx -> IO ()+
+ src/Data/Number/Flint/Groups/Bool/Mat.hs view
@@ -0,0 +1,45 @@+{-|+module : Data.Number.Flint.Groups.Bool.Mat+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++A `BoolMat` represents a dense matrix over the boolean +semiring \(\left<\{0,1\},\vee,\wedge\right>\),+implemented as an array of entries of type `CInt`.++The dimension (number of rows and columns) of a matrix is fixed at+initialization, and the user must ensure that inputs and outputs to an+operation have compatible dimensions. The number of rows or columns in+a matrix can be zero.++== Example++@+import Control.Monad++import Data.Number.Flint++main = do+ a <- newBoolMat 3 5+ withBoolMat a $ \\a -> do+ forM_ [0..2] $ \\j -> do+ bool_mat_set_entry a j j 1+ bool_mat_set_entry a j (j+2) 1+ print a+@++Running main yields:++>>> main +[1, 0, 1, 0, 0]+[0, 1, 0, 1, 0]+[0, 0, 1, 0, 1]+-}++module Data.Number.Flint.Groups.Bool.Mat (+ module Data.Number.Flint.Groups.Bool.Mat.FFI+) where++import Data.Number.Flint.Groups.Bool.Mat.FFI+
+ src/Data/Number/Flint/Groups/Bool/Mat/FFI.hsc view
@@ -0,0 +1,427 @@+{-|+module : Data.Number.Flint.Groups.Bool.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Groups.Bool.Mat.FFI (+ -- * Matrices over booleans+ BoolMat (..)+ , CBoolMat (..)+ , newBoolMat+ , withBoolMat+ , withNewBoolMat+ -- * Entries+ , bool_mat_get_entry+ , bool_mat_set_entry+ -- * Memory management+ , bool_mat_init+ , bool_mat_clear+ , bool_mat_is_empty+ , bool_mat_is_square+ -- * Conversions+ , bool_mat_entry+ , bool_mat_set+ -- * Input and output+ , bool_mat_get_str+ , bool_mat_print+ , bool_mat_fprint+ -- * Value comparisons+ , bool_mat_equal+ , bool_mat_any+ , bool_mat_all+ , bool_mat_is_diagonal+ , bool_mat_is_lower_triangular+ , bool_mat_is_transitive+ , bool_mat_is_nilpotent+ -- * Random generation+ , bool_mat_randtest+ , bool_mat_randtest_diagonal+ , bool_mat_randtest_nilpotent+ -- * Special matrices+ , bool_mat_zero+ , bool_mat_one+ , bool_mat_directed_path+ , bool_mat_directed_cycle+ -- * Transpose+ , bool_mat_transpose+ -- * Arithmetic+ , bool_mat_complement+ , bool_mat_add+ , bool_mat_mul+ , bool_mat_mul_entrywise+ , bool_mat_sqr+ , bool_mat_pow_ui+ -- * Special functions+ , bool_mat_trace+ , bool_mat_nilpotency_degree+ , bool_mat_transitive_closure+ , bool_mat_get_strongly_connected_components+ , bool_mat_all_pairs_longest_walk+) where ++-- Matrices over booleans ------------------------------------------------------++-- A @bool_mat_t@ represents a dense matrix over the boolean semiring+-- \(\langle \left\{0, 1\right\}, \vee, \wedge \rangle\), implemented as an+-- array of entries of type @int@.+--+-- The dimension (number of rows and columns) of a matrix is fixed at+-- initialization, and the user must ensure that inputs and outputs to an+-- operation have compatible dimensions. The number of rows or columns in a+-- matrix can be zero.+--++import System.IO.Unsafe++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Marshal.Array ( advancePtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpq+import Data.Number.Flint.NMod.Types+import Data.Number.Flint.Support.D.Mat+import Data.Number.Flint.Support.Mpf.Mat++#include <flint/flint.h>+#include <flint/bool_mat.h>++--------------------------------------------------------------------------------++data BoolMat = BoolMat {-# UNPACK #-} !(ForeignPtr CBoolMat) +data CBoolMat = CBoolMat (Ptr CInt) CLong CLong (Ptr (Ptr CInt)) ++instance Storable CBoolMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size bool_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment bool_mat_t}+ peek ptr = CBoolMat+ <$> #{peek bool_mat_struct, entries} ptr+ <*> #{peek bool_mat_struct, r } ptr+ <*> #{peek bool_mat_struct, c } ptr+ <*> #{peek bool_mat_struct, rows } ptr + poke = error "CBoolMat.poke: Not defined."+ +newBoolMat rows cols = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> bool_mat_init x rows cols+ addForeignPtrFinalizer p_bool_mat_clear x+ return $ BoolMat x++{-# INLINE withBoolMat #-}+withBoolMat (BoolMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (BoolMat x,)++{-# INLINE withNewBoolMat #-}+withNewBoolMat rows cols f = do+ x <- newBoolMat rows cols+ withBoolMat x f+ +--------------------------------------------------------------------------------++-- | /bool_mat_get_entry/ /mat/ /i/ /j/ +--+-- Returns the entry of matrix /mat/ at row /i/ and column /j/.+-- foreign import ccall "bool_mat.h bool_mat_get_entry"+bool_mat_get_entry :: Ptr CBoolMat -> CLong -> CLong -> IO CInt+bool_mat_get_entry mat i j = do+ CBoolMat p r c _ <- peek mat+ result <- peek (p `advancePtr` (fromIntegral (i*c + j)))+ return result+ +-- | /bool_mat_set_entry/ /mat/ /i/ /j/ /x/ +--+-- Sets the entry of matrix /mat/ at row /i/ and column /j/ to /x/.+bool_mat_set_entry :: Ptr CBoolMat -> CLong -> CLong -> CInt -> IO ()+bool_mat_set_entry mat i j x = do + CBoolMat p r c _ <- peek mat+ poke (p `advancePtr` (fromIntegral (i*c + j))) x+ +-- Memory management -----------------------------------------------------------++-- | /bool_mat_init/ /mat/ /r/ /c/ +--+-- Initializes the matrix, setting it to the zero matrix with /r/ rows and+-- /c/ columns.+foreign import ccall "bool_mat.h bool_mat_init"+ bool_mat_init :: Ptr CBoolMat -> CLong -> CLong -> IO ()++-- | /bool_mat_clear/ /mat/ +--+-- Clears the matrix, deallocating all entries.+foreign import ccall "bool_mat.h bool_mat_clear"+ bool_mat_clear :: Ptr CBoolMat -> IO ()++foreign import ccall "bool_mat.h &bool_mat_clear"+ p_bool_mat_clear :: FunPtr (Ptr CBoolMat -> IO ())++-- | /bool_mat_is_empty/ /mat/ +--+-- Returns nonzero iff the number of rows or the number of columns in /mat/+-- is zero. Note that this does not depend on the entry values of /mat/.+bool_mat_is_empty :: Ptr CBoolMat -> IO CInt+bool_mat_is_empty mat = do+ CBoolMat _ r c _ <- peek mat+ return $ if r == 0 || c == 0 then 1 else 0+ +-- | /bool_mat_is_square/ /mat/ +--+-- Returns nonzero iff the number of rows is equal to the number of columns+-- in /mat/.+bool_mat_is_square :: Ptr CBoolMat -> IO CInt+bool_mat_is_square mat = do+ CBoolMat _ r c _ <- peek mat+ return $ if r == c then 1 else 0++-- Conversions -----------------------------------------------------------------++bool_mat_entry mat i j = do+ CBoolMat entries r c rows <- peek mat+ return $ entries `advancePtr` (fromIntegral (i*c + j))+ +-- | /bool_mat_set/ /dest/ /src/ +--+-- Sets /dest/ to /src/. The operands must have identical dimensions.+foreign import ccall "bool_mat.h bool_mat_set"+ bool_mat_set :: Ptr CBoolMat -> Ptr CBoolMat -> IO ()++-- Input and output ------------------------------------------------------------++foreign import ccall "bool_mat.h bool_mat_get_str"+ bool_mat_get_str :: Ptr CBoolMat -> IO CString+ +-- | /bool_mat_print/ /mat/ +--+-- Prints each entry in the matrix.+bool_mat_print :: Ptr CBoolMat -> IO ()+bool_mat_print mat = do+ printCStr bool_mat_get_str mat+ return ()++-- | /bool_mat_fprint/ /file/ /mat/ +--+-- Prints each entry in the matrix to the stream /file/.+foreign import ccall "bool_mat.h bool_mat_fprint"+ bool_mat_fprint :: Ptr CFile -> Ptr CBoolMat -> IO ()++-- Value comparisons -----------------------------------------------------------++-- | /bool_mat_equal/ /mat1/ /mat2/ +--+-- Returns nonzero iff the matrices have the same dimensions and identical+-- entries.+foreign import ccall "bool_mat.h bool_mat_equal"+ bool_mat_equal :: Ptr CBoolMat -> Ptr CBoolMat -> IO CInt++-- | /bool_mat_any/ /mat/ +--+-- Returns nonzero iff /mat/ has a nonzero entry.+foreign import ccall "bool_mat.h bool_mat_any"+ bool_mat_any :: Ptr CBoolMat -> IO CInt++-- | /bool_mat_all/ /mat/ +--+-- Returns nonzero iff all entries of /mat/ are nonzero.+foreign import ccall "bool_mat.h bool_mat_all"+ bool_mat_all :: Ptr CBoolMat -> IO CInt++-- | /bool_mat_is_diagonal/ /A/ +--+-- Returns nonzero iff \(i \ne j \implies \bar{A_{ij}}\).+foreign import ccall "bool_mat.h bool_mat_is_diagonal"+ bool_mat_is_diagonal :: Ptr CBoolMat -> IO CInt++-- | /bool_mat_is_lower_triangular/ /A/ +--+-- Returns nonzero iff \(i < j \implies \bar{A_{ij}}\).+foreign import ccall "bool_mat.h bool_mat_is_lower_triangular"+ bool_mat_is_lower_triangular :: Ptr CBoolMat -> IO CInt++-- | /bool_mat_is_transitive/ /mat/ +--+-- Returns nonzero iff \(A_{ij} \wedge A_{jk} \implies A_{ik}\).+foreign import ccall "bool_mat.h bool_mat_is_transitive"+ bool_mat_is_transitive :: Ptr CBoolMat -> IO CInt++-- | /bool_mat_is_nilpotent/ /A/ +--+-- Returns nonzero iff some positive matrix power of \(A\) is zero.+foreign import ccall "bool_mat.h bool_mat_is_nilpotent"+ bool_mat_is_nilpotent :: Ptr CBoolMat -> IO CInt++-- Random generation -----------------------------------------------------------++-- | /bool_mat_randtest/ /mat/ /state/ +--+-- Sets /mat/ to a random matrix.+foreign import ccall "bool_mat.h bool_mat_randtest"+ bool_mat_randtest :: Ptr CBoolMat -> Ptr CFRandState -> IO ()++-- | /bool_mat_randtest_diagonal/ /mat/ /state/ +--+-- Sets /mat/ to a random diagonal matrix.+foreign import ccall "bool_mat.h bool_mat_randtest_diagonal"+ bool_mat_randtest_diagonal :: Ptr CBoolMat -> Ptr CFRandState -> IO ()++-- | /bool_mat_randtest_nilpotent/ /mat/ /state/ +--+-- Sets /mat/ to a random nilpotent matrix.+foreign import ccall "bool_mat.h bool_mat_randtest_nilpotent"+ bool_mat_randtest_nilpotent :: Ptr CBoolMat -> Ptr CFRandState -> IO ()++-- Special matrices ------------------------------------------------------------++-- | /bool_mat_zero/ /mat/ +--+-- Sets all entries in mat to zero.+foreign import ccall "bool_mat.h bool_mat_zero"+ bool_mat_zero :: Ptr CBoolMat -> IO ()++-- | /bool_mat_one/ /mat/ +--+-- Sets the entries on the main diagonal to ones, and all other entries to+-- zero.+foreign import ccall "bool_mat.h bool_mat_one"+ bool_mat_one :: Ptr CBoolMat -> IO ()++-- | /bool_mat_directed_path/ /A/ +--+-- Sets \(A_{ij}\) to \(j = i + 1\). Requires that \(A\) is a square+-- matrix.+foreign import ccall "bool_mat.h bool_mat_directed_path"+ bool_mat_directed_path :: Ptr CBoolMat -> IO ()++-- | /bool_mat_directed_cycle/ /A/ +--+-- Sets \(A_{ij}\) to \(j = (i + 1) \mod n\) where \(n\) is the order of+-- the square matrix \(A\).+foreign import ccall "bool_mat.h bool_mat_directed_cycle"+ bool_mat_directed_cycle :: Ptr CBoolMat -> IO ()++-- Transpose -------------------------------------------------------------------++-- | /bool_mat_transpose/ /dest/ /src/ +--+-- Sets /dest/ to the transpose of /src/. The operands must have compatible+-- dimensions. Aliasing is allowed.+foreign import ccall "bool_mat.h bool_mat_transpose"+ bool_mat_transpose :: Ptr CBoolMat -> Ptr CBoolMat -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- | /bool_mat_complement/ /B/ /A/ +--+-- Sets /B/ to the logical complement of /A/. That is \(B_{ij}\) is set to+-- \(\bar{A_{ij}}\). The operands must have the same dimensions.+foreign import ccall "bool_mat.h bool_mat_complement"+ bool_mat_complement :: Ptr CBoolMat -> Ptr CBoolMat -> IO ()++-- | /bool_mat_add/ /res/ /mat1/ /mat2/ +--+-- Sets /res/ to the sum of /mat1/ and /mat2/. The operands must have the+-- same dimensions.+foreign import ccall "bool_mat.h bool_mat_add"+ bool_mat_add :: Ptr CBoolMat -> Ptr CBoolMat -> Ptr CBoolMat -> IO ()++-- | /bool_mat_mul/ /res/ /mat1/ /mat2/ +--+-- Sets /res/ to the matrix product of /mat1/ and /mat2/. The operands must+-- have compatible dimensions for matrix multiplication.+foreign import ccall "bool_mat.h bool_mat_mul"+ bool_mat_mul :: Ptr CBoolMat -> Ptr CBoolMat -> Ptr CBoolMat -> IO ()++-- | /bool_mat_mul_entrywise/ /res/ /mat1/ /mat2/ +--+-- Sets /res/ to the entrywise product of /mat1/ and /mat2/. The operands+-- must have the same dimensions.+foreign import ccall "bool_mat.h bool_mat_mul_entrywise"+ bool_mat_mul_entrywise :: Ptr CBoolMat -> Ptr CBoolMat -> Ptr CBoolMat -> IO ()++-- | /bool_mat_sqr/ /B/ /A/ +--+-- Sets /B/ to the matrix square of /A/. The operands must both be square+-- with the same dimensions.+bool_mat_sqr :: Ptr CBoolMat -> Ptr CBoolMat -> IO ()+bool_mat_sqr b a = bool_mat_mul b a a+ +-- | /bool_mat_pow_ui/ /B/ /A/ /exp/ +--+-- Sets /B/ to /A/ raised to the power /exp/. Requires that /A/ is a square+-- matrix.+foreign import ccall "bool_mat.h bool_mat_pow_ui"+ bool_mat_pow_ui :: Ptr CBoolMat -> Ptr CBoolMat -> CULong -> IO ()++-- Special functions -----------------------------------------------------------++-- | /bool_mat_trace/ /mat/ +--+-- Returns the trace of the matrix, i.e. the sum of entries on the main+-- diagonal of /mat/. The matrix is required to be square. The sum is in+-- the boolean semiring, so this function returns nonzero iff any entry on+-- the diagonal of /mat/ is nonzero.+foreign import ccall "bool_mat.h bool_mat_trace"+ bool_mat_trace :: Ptr CBoolMat -> IO CInt++-- | /bool_mat_nilpotency_degree/ /A/ +--+-- Returns the nilpotency degree of the \(n \times n\) matrix /A/. It+-- returns the smallest positive \(k\) such that \(A^k = 0\). If no such+-- \(k\) exists then the function returns \(-1\) if \(n\) is positive, and+-- otherwise it returns \(0\).+foreign import ccall "bool_mat.h bool_mat_nilpotency_degree"+ bool_mat_nilpotency_degree :: Ptr CBoolMat -> IO CLong++-- | /bool_mat_transitive_closure/ /B/ /A/ +--+-- Sets /B/ to the transitive closure \(\sum_{k=1}^\infty A^k\). The matrix+-- /A/ is required to be square.+foreign import ccall "bool_mat.h bool_mat_transitive_closure"+ bool_mat_transitive_closure :: Ptr CBoolMat -> Ptr CBoolMat -> IO ()++-- | /bool_mat_get_strongly_connected_components/ /p/ /A/ +--+-- Partitions the \(n\) row and column indices of the \(n \times n\) matrix+-- /A/ according to the strongly connected components (SCC) of the graph+-- for which /A/ is the adjacency matrix. If the graph has \(k\) SCCs then+-- the function returns \(k\), and for each vertex \(i \in [0, n-1]\),+-- \(p_i\) is set to the index of the SCC to which the vertex belongs. The+-- SCCs themselves can be considered as nodes in a directed acyclic graph+-- (DAG), and the SCCs are indexed in postorder with respect to that DAG.+foreign import ccall "bool_mat.h bool_mat_get_strongly_connected_components"+ bool_mat_get_strongly_connected_components :: Ptr CLong -> Ptr CBoolMat -> IO CLong++-- | /bool_mat_all_pairs_longest_walk/ /B/ /A/ +--+-- Sets \(B_{ij}\) to the length of the longest walk with endpoint vertices+-- \(i\) and \(j\) in the graph whose adjacency matrix is /A/. The matrix+-- /A/ must be square. Empty walks with zero length which begin and end at+-- the same vertex are allowed. If \(j\) is not reachable from \(i\) then+-- no walk from \(i\) to \(j\) exists and \(B_{ij}\) is set to the special+-- value \(-1\). If arbitrarily long walks from \(i\) to \(j\) exist then+-- \(B_{ij}\) is set to the special value \(-2\).+-- +-- The function returns \(-2\) if any entry of \(B_{ij}\) is \(-2\), and+-- otherwise it returns the maximum entry in \(B\), except if \(A\) is+-- empty in which case \(-1\) is returned. Note that the returned value is+-- one less than that of @nilpotency_degree@.+-- +-- This function can help quantify entrywise errors in a truncated+-- evaluation of a matrix power series. If /A/ is an indicator matrix with+-- the same sparsity pattern as a matrix \(M\) over the real or complex+-- numbers, and if \(B_{ij}\) does not take the special value \(-2\), then+-- the tail \(\left[ \sum_{k=N}^\infty a_k M^k \right]_{ij}\) vanishes when+-- \(N > B_{ij}\).+foreign import ccall "bool_mat.h bool_mat_all_pairs_longest_walk"+ bool_mat_all_pairs_longest_walk :: Ptr CFmpzMat -> Ptr CBoolMat -> IO CLong+
+ src/Data/Number/Flint/Groups/Bool/Mat/Instances.hs view
@@ -0,0 +1,14 @@+module Data.Number.Flint.Groups.Bool.Mat.Instances where++import System.IO.Unsafe+import Foreign.C.String+import Foreign.Marshal.Alloc ( free )++import Data.Number.Flint.Groups.Bool.Mat++instance Show BoolMat where+ show x = unsafePerformIO $ do+ (_, cs) <- withBoolMat x bool_mat_get_str+ s <- peekCString cs+ free cs+ return s
+ src/Data/Number/Flint/Groups/DLog.hs view
@@ -0,0 +1,32 @@+{-|+module : Data.Number.Flint.Fq+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++-- This module implements discrete logarithms, with the application to+Dirichlet characters in mind.++In particular, this module defines a @dlog_precomp_t@ structure+permitting to describe a discrete log problem in some subgroup of+\((\mathbb Z/p^e \mathbb Z)^\times\) for primepower moduli \(p^e\), and+store precomputed data for faster computation of several such discrete+logarithms.++When initializing this data, the user provides both a group description+and the expected number of subsequent discrete logarithms calls. The+choice of algorithm and the amount of stored data depend both on the+structure of the group and this number.++No particular effort has been made towards single discrete logarithm+computation. Currently only machine size primepower moduli are+supported.++-}++module Data.Number.Flint.Groups.DLog (+ module Data.Number.Flint.Groups.DLog.FFI,+) where++import Data.Number.Flint.Groups.DLog.FFI+
+ src/Data/Number/Flint/Groups/DLog/FFI.hsc view
@@ -0,0 +1,271 @@+{-|+module : Data.Number.Flint.Groups.DLog.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Groups.DLog.FFI (+ -- * Discrete logarithms mod ulong primes+ -- * Single evaluation+ dlog_once+ -- * Precomputations+ , DLogPrecomp (..)+ , CDLogPrecomp (..)+ , newDLogPrecompN+ , newDLogPrecompModpe+ , newDLogPrecompP+ , newDLogPrecompPE+ , newDLogPrecompSmall+ , withDLogPrecomp+ , dlog_precomp_n_init+ , dlog_precomp+ , dlog_precomp_clear+ , dlog_precomp_modpe_init+ , dlog_precomp_p_init+ , dlog_precomp_pe_init+ , dlog_precomp_small_init+ -- * Vector evaluations+ , dlog_vec_fill+ , dlog_vec_set_not_found+ , dlog_vec+ , dlog_vec_add+ , dlog_vec_loop+ , dlog_vec_loop_add+ , dlog_vec_eratos+ , dlog_vec_eratos_add+ , dlog_vec_sieve_add+ , dlog_vec_sieve+) where++-- Discrete logarithms mod ulong primes ----------------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.Storable++import Data.Number.Flint.Flint+import Data.Number.Flint.NMod++#define DLOG_INLINES_C+#include <flint/dlog.h>++-- Single evaluation -----------------------------------------------------------++-- | /dlog_once/ /b/ /a/ /mod/ /n/ +--+-- Return \(x\) such that \(b = a^x\) in+-- \((\mathbb Z/mod \mathbb Z)^\times\), where /a/ is known to have order+-- /n/.+foreign import ccall "dlog.h dlog_once"+ dlog_once :: CULong -> CULong -> Ptr CNMod -> CULong -> IO CULong++-- Precomputations -------------------------------------------------------------++data DLogPrecomp = DLogPrecomp {-# UNPACK #-} !(ForeignPtr CDLogPrecomp)+type CDLogPrecomp = CFlint DLogPrecomp++instance Storable CDLogPrecomp where+ sizeOf _ = #{size dlog_precomp_t}+ alignment _ = #{alignment dlog_precomp_t}+ peek = undefined+ poke = undefined+ +newDLogPrecompN a mod n num = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ dlog_precomp_n_init x a mod n num+ addForeignPtrFinalizer p_dlog_precomp_clear x+ return $ DLogPrecomp x++newDLogPrecompModpe a p e pe num = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ dlog_precomp_modpe_init x a p e pe num+ addForeignPtrFinalizer p_dlog_precomp_clear x+ return $ DLogPrecomp x++newDLogPrecompP a mod n num = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ dlog_precomp_p_init x a mod n num+ addForeignPtrFinalizer p_dlog_precomp_clear x+ return $ DLogPrecomp x++newDLogPrecompPE a mod p e pe num = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ dlog_precomp_pe_init x a mod p e pe num+ addForeignPtrFinalizer p_dlog_precomp_clear x+ return $ DLogPrecomp x++newDLogPrecompSmall a mod n num = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ dlog_precomp_small_init x a mod n num+ addForeignPtrFinalizer p_dlog_precomp_clear x+ return $ DLogPrecomp x++{-# INLINE withDLogPrecomp #-}+withDLogPrecomp (DLogPrecomp x) f = do+ withForeignPtr x $ \px -> f px >>= return . (DLogPrecomp x,)++--------------------------------------------------------------------------------++-- | /dlog_precomp_n_init/ /pre/ /a/ /mod/ /n/ /num/ +--+-- Precompute data for /num/ discrete logarithms evaluations in the+-- subgroup generated by /a/ modulo /mod/, where /a/ is known to have order+-- /n/.+foreign import ccall "dlog.h dlog_precomp_n_init"+ dlog_precomp_n_init :: Ptr CDLogPrecomp+ -> CULong -> CULong+ -> CULong+ -> CULong+ -> IO ()++-- | /dlog_precomp/ /pre/ /b/ +--+-- Return \(\log(b)\) for the group described in /pre/.+foreign import ccall "dlog.h dlog_precomp"+ dlog_precomp :: Ptr CDLogPrecomp -> CULong -> IO CULong++-- | /dlog_precomp_clear/ /pre/ +--+-- Clears /t/.+foreign import ccall "dlog.h dlog_precomp_clear"+ dlog_precomp_clear :: Ptr CDLogPrecomp -> IO ()++foreign import ccall "dlog.h &dlog_precomp_clear"+ p_dlog_precomp_clear :: FunPtr (Ptr CDLogPrecomp -> IO ())++-- Specialized versions of @dlog_precomp_n_init@ are available when+-- specific information is known about the group:+--+-- | /dlog_precomp_modpe_init/ /pre/ /a/ /p/ /e/ /pe/ /num/ +--+-- Assume that /a/ generates the group of residues modulo /pe/ equal+-- \(p^e\) for prime /p/.+foreign import ccall "dlog.h dlog_precomp_modpe_init"+ dlog_precomp_modpe_init :: Ptr CDLogPrecomp+ -> CULong+ -> CULong+ -> CULong+ -> CULong+ -> CULong+ -> IO ()++-- | /dlog_precomp_p_init/ /pre/ /a/ /mod/ /p/ /num/ +--+-- Assume that /a/ has prime order /p/.+foreign import ccall "dlog.h dlog_precomp_p_init"+ dlog_precomp_p_init :: Ptr CDLogPrecomp+ -> CULong+ -> CULong+ -> CULong+ -> CULong+ -> IO ()++-- | /dlog_precomp_pe_init/ /pre/ /a/ /mod/ /p/ /e/ /pe/ /num/ +--+-- Assume that /a/ has primepower order /pe/ \(p^e\).+foreign import ccall "dlog.h dlog_precomp_pe_init"+ dlog_precomp_pe_init :: Ptr CDLogPrecomp+ -> CULong+ -> CULong+ -> CULong+ -> CULong+ -> CULong+ -> CULong+ -> IO ()++-- | /dlog_precomp_small_init/ /pre/ /a/ /mod/ /n/ /num/ +--+-- Make a complete lookup table of size /n/. If /mod/ is small, this is+-- done using an element-indexed array (see @dlog_table_t@), otherwise with+-- a sorted array allowing binary search.+foreign import ccall "dlog.h dlog_precomp_small_init"+ dlog_precomp_small_init :: Ptr CDLogPrecomp+ -> CULong+ -> CULong+ -> CULong+ -> CULong+ -> IO ()++-- Vector evaluations ----------------------------------------------------------++-- These functions compute all logarithms of successive integers+-- \(1\dots n\).+--+-- | /dlog_vec_fill/ /v/ /nv/ /x/ +--+-- Sets values /v[k]/ to /x/ for all /k/ less than /nv/.+foreign import ccall "dlog.h dlog_vec_fill"+ dlog_vec_fill :: Ptr CULong -> CULong -> CULong -> IO ()++-- | /dlog_vec_set_not_found/ /v/ /nv/ /mod/ +--+-- Sets values /v[k]/ to @DLOG_NONE@ for all /k/ not coprime to /mod/.+foreign import ccall "dlog.h dlog_vec_set_not_found"+ dlog_vec_set_not_found :: Ptr CULong -> CULong -> Ptr CNMod -> IO ()++-- | /dlog_vec/ /v/ /nv/ /a/ /va/ /mod/ /na/ /order/ +--+-- Sets /v[k]/ to \(\log(k,a)\) times value /va/ for \(0\leq k < nv\),+-- where /a/ has order /na/. /va/ should be /1/ for usual log computation.+foreign import ccall "dlog.h dlog_vec"+ dlog_vec :: Ptr CULong -> CULong -> CULong -> CULong -> Ptr CNMod -> CULong -> Ptr CNMod -> IO ()++-- | /dlog_vec_add/ /v/ /nv/ /a/ /va/ /mod/ /na/ /order/ +--+-- Same parameters as before, but adds \(\log(k,a)\times v_a\) to /v[k]/+-- and reduce modulo /order/ instead of replacing the value. Indices /k/+-- such that /v[k]/ equals /DLOG_NONE/ are ignored.+foreign import ccall "dlog.h dlog_vec_add"+ dlog_vec_add :: Ptr CULong -> CULong -> CULong -> CULong -> Ptr CNMod -> CULong -> Ptr CNMod -> IO ()++-- Depending on the relative size of /nv/ and /na/, these two /dlog_vec/+-- functions call one of the following functions.+--+-- | /dlog_vec_loop/ /v/ /nv/ /a/ /va/ /mod/ /na/ /order/ +--+foreign import ccall "dlog.h dlog_vec_loop"+ dlog_vec_loop :: Ptr CULong -> CULong -> CULong -> CULong -> Ptr CNMod -> CULong -> Ptr CNMod -> IO ()++-- | /dlog_vec_loop_add/ /v/ /nv/ /a/ /va/ /mod/ /na/ /order/ +--+-- Perform a complete loop of size /na/ on powers of /a/ to fill the+-- logarithm values, discarding powers outside the bounds of /v/. This+-- requires no discrete logarithm computation.+foreign import ccall "dlog.h dlog_vec_loop_add"+ dlog_vec_loop_add :: Ptr CULong -> CULong -> CULong -> CULong -> Ptr CNMod -> CULong -> Ptr CNMod -> IO ()++-- | /dlog_vec_eratos/ /v/ /nv/ /a/ /va/ /mod/ /na/ /order/ +--+foreign import ccall "dlog.h dlog_vec_eratos"+ dlog_vec_eratos :: Ptr CULong -> CULong -> CULong -> CULong -> Ptr CNMod -> CULong -> Ptr CNMod -> IO ()++-- | /dlog_vec_eratos_add/ /v/ /nv/ /a/ /va/ /mod/ /na/ /order/ +--+-- Compute discrete logarithms of prime numbers less than /nv/ and+-- propagate to composite numbers.+foreign import ccall "dlog.h dlog_vec_eratos_add"+ dlog_vec_eratos_add :: Ptr CULong -> CULong -> CULong -> CULong -> Ptr CNMod -> CULong -> Ptr CNMod -> IO ()++-- | /dlog_vec_sieve_add/ /v/ /nv/ /a/ /va/ /mod/ /na/ /order/ +--+foreign import ccall "dlog.h dlog_vec_sieve_add"+ dlog_vec_sieve_add :: Ptr CULong -> CULong -> CULong -> CULong -> Ptr CNMod -> CULong -> Ptr CNMod -> IO ()++-- | /dlog_vec_sieve/ /v/ /nv/ /a/ /va/ /mod/ /na/ /order/ +--+-- Compute the discrete logarithms of the first few prime numbers, then use+-- them as a factor base to obtain the logarithms of larger primes by+-- sieving techniques.+-- +-- In the the present implementation, the full index-calculus method is not+-- implemented.+foreign import ccall "dlog.h dlog_vec_sieve"+ dlog_vec_sieve :: Ptr CULong -> CULong -> CULong -> CULong -> Ptr CNMod -> CULong -> Ptr CNMod -> IO ()++
+ src/Data/Number/Flint/Groups/Dirichlet.hs view
@@ -0,0 +1,46 @@+{-|+module : Data.Number.Flint.Groups.Dirichlet+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+++__Warning: the interfaces in this module are experimental and may change without notice.__++This module allows working with Dirichlet characters algebraically. For+evaluations of characters as complex numbers, see @acb-dirichlet@.++= Dirichlet characters ++Working with Dirichlet characters mod /q/ consists mainly in going from+residue classes mod /q/ to exponents on a set of generators of the+group.++This implementation relies on the Conrey numbering scheme introduced in+the+<http://www.lmfdb.org/Character/Dirichlet L-functions and Modular Forms DataBase>,+which is an explicit choice of generators allowing to represent+Dirichlet characters via the pairing++\[\begin{aligned}+\begin{array}{ccccc}+(\mathbb Z/q\mathbb Z)^\times \times (\mathbb Z/q\mathbb Z)^\times & \to & \bigoplus_i \mathbb Z/\phi_i\mathbb Z \times \mathbb Z/\phi_i\mathbb Z & \to &\mathbb C \\+(m,n) & \mapsto& (a_i,b_i) &\mapsto& \chi_q(m,n) = \exp(2i\pi\sum \frac{a_ib_i}{\phi_i} )+\end{array}+\end{aligned}\]++We call /number/ a residue class \(m\) modulo /q/, and /log/ the+corresponding vector \((a_i)\) of exponents of Conrey generators.++Going from a /log/ to the corresponding /number/ is a cheap operation we+call exponential, while the converse requires computing discrete+logarithms.++-}++module Data.Number.Flint.Groups.Dirichlet (+ module Data.Number.Flint.Groups.Dirichlet.FFI,+) where++import Data.Number.Flint.Groups.Dirichlet.FFI+
+ src/Data/Number/Flint/Groups/Dirichlet/FFI.hsc view
@@ -0,0 +1,464 @@+{-|+module : Data.Number.Flint.Groups.Dirichlet.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Groups.Dirichlet.FFI (+ -- * Dirichlet characters+ -- * Multiplicative group modulo /q/+ DirichletGroup (..)+ , CDirichletGroup (..)+ , newDirichletGroup+ , withDirichletGroup+ , withNewDirichletGroup+ , dirichlet_group_init+ , dirichlet_subgroup_init+ , dirichlet_group_clear+ , dirichlet_group_size+ , dirichlet_group_num_primitive+ , dirichlet_group_dlog_precompute+ , dirichlet_group_dlog_clear+ -- * Character type+ , DirichletChar (..)+ , CDirichletChar (..)+ , newDirichletChar + , withDirichletChar+ , withNewDirichletChar+ , dirichlet_char_init+ , dirichlet_char_clear+ , dirichlet_char_print+ , dirichlet_char_log+ , dirichlet_char_exp+ , _dirichlet_char_exp+ , dirichlet_char_one+ , dirichlet_char_first_primitive+ , dirichlet_char_set+ , dirichlet_char_next+ , dirichlet_char_next_primitive+ , dirichlet_index_char+ , dirichlet_char_index+ , dirichlet_char_eq+ , dirichlet_char_eq_deep+ -- * Character properties+ , dirichlet_char_is_principal+ , dirichlet_conductor_ui+ , dirichlet_conductor_char+ , dirichlet_parity_ui+ , dirichlet_parity_char+ , dirichlet_order_ui+ , dirichlet_order_char+ , dirichlet_char_is_real+ , dirichlet_char_is_primitive+ -- * Character evaluation+ , dirichlet_pairing+ , dirichlet_pairing_char+ , dirichlet_chi+ , dirichlet_chi_vec+ , dirichlet_chi_vec_order+ -- * Character operations+ , dirichlet_char_mul+ , dirichlet_char_pow+ , dirichlet_char_lift+ , dirichlet_char_lower+) where++-- Dirichlet characters --------------------------------------------------------++import Foreign.C.Types+import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable++#include <flint/dirichlet.h>++-- dirichlet_group_t -----------------------------------------------------------++data DirichletGroup =+ DirichletGroup {-# UNPACK #-} !(ForeignPtr CDirichletGroup)+data CDirichletGroup = CFlint DirichletGroup++newDirichletGroup n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ dirichlet_group_init x (fromIntegral n)+ addForeignPtrFinalizer p_dirichlet_group_clear x+ return $ DirichletGroup x++-- | Use DirichletGroup in `f`.+{-# INLINE withDirichletGroup #-}+withDirichletGroup (DirichletGroup p) f = do+ withForeignPtr p $ \fp -> (DirichletGroup p,) <$> f fp++-- | Apply `f` to new DirichletGroup.+{-# INLINE withNewDirichletGroup #-}+withNewDirichletGroup n f = do+ x <- newDirichletGroup n+ withDirichletGroup x f++instance Storable CDirichletGroup where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size dirichlet_group_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment dirichlet_group_t}+ peek = undefined+ poke = undefined++-- Multiplicative group modulo /q/ ---------------------------------------------++-- | /dirichlet_group_init/ /G/ /q/ +-- +-- Initializes /G/ to the group of Dirichlet characters mod /q/.+-- +-- This method computes a canonical decomposition of /G/ in terms of cyclic+-- groups, which are the mod \(p^e\) subgroups for \(p^e\|q\), plus the+-- specific generator described by Conrey for each subgroup.+-- +-- In particular /G/ contains:+-- +-- - the number /num/ of components+-- - the generators+-- - the exponent /expo/ of the group+-- +-- It does /not/ automatically precompute lookup tables of discrete+-- logarithms or numerical roots of unity, and can therefore safely be+-- called even with large /q/.+-- +-- For implementation reasons, the largest prime factor of /q/ must not+-- exceed \(10^{16}\). This restriction could be removed in the future. The+-- function returns 1 on success and 0 if a factor is too large.+foreign import ccall "dirichlet.h dirichlet_group_init"+ dirichlet_group_init :: Ptr CDirichletGroup -> CULong -> IO CInt++-- | /dirichlet_subgroup_init/ /H/ /G/ /h/ +-- +-- Given an already computed group /G/ mod \(q\), initialize its subgroup+-- /H/ defined mod \(h\mid q\). Precomputed discrete log tables are+-- inherited.+foreign import ccall "dirichlet.h dirichlet_subgroup_init"+ dirichlet_subgroup_init :: Ptr CDirichletGroup -> Ptr CDirichletGroup -> CULong -> IO ()++-- | /dirichlet_group_clear/ /G/ +-- +-- Clears /G/. Remark this function does /not/ clear the discrete logarithm+-- tables stored in /G/ (which may be shared with another group).+foreign import ccall "dirichlet.h dirichlet_group_clear"+ dirichlet_group_clear :: Ptr CDirichletGroup -> IO ()++foreign import ccall "dirichlet.h &dirichlet_group_clear"+ p_dirichlet_group_clear :: FunPtr (Ptr CDirichletGroup -> IO ())++-- | /dirichlet_group_size/ /G/ +-- +-- Returns the number of elements in /G/, i.e. \(\varphi(q)\).+foreign import ccall "dirichlet.h dirichlet_group_size"+ dirichlet_group_size :: Ptr CDirichletGroup -> IO CULong++-- | /dirichlet_group_num_primitive/ /G/ +-- +-- Returns the number of primitive elements in /G/.+foreign import ccall "dirichlet.h dirichlet_group_num_primitive"+ dirichlet_group_num_primitive :: Ptr CDirichletGroup -> IO CULong++-- | /dirichlet_group_dlog_precompute/ /G/ /num/ +-- +-- Precompute decomposition and tables for discrete log computations in+-- /G/, so as to minimize the complexity of /num/ calls to discrete+-- logarithms.+-- +-- If /num/ gets very large, the entire group may be indexed.+foreign import ccall "dirichlet.h dirichlet_group_dlog_precompute"+ dirichlet_group_dlog_precompute :: Ptr CDirichletGroup -> CULong -> IO ()++-- | /dirichlet_group_dlog_clear/ /G/ /num/ +-- +-- Clear discrete logarithm tables in /G/. When discrete logarithm tables+-- are shared with subgroups, those subgroups must be cleared before+-- clearing the tables.+foreign import ccall "dirichlet.h dirichlet_group_dlog_clear"+ dirichlet_group_dlog_clear :: Ptr CDirichletGroup -> CULong -> IO ()++-- Character type --------------------------------------------------------------++data DirichletChar = DirichletChar {-# UNPACK #-} !(ForeignPtr CDirichletChar)+data CDirichletChar = CDirichletChar CULong (Ptr CULong)++newDirichletChar group = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ dirichlet_char_init x group+ addForeignPtrFinalizer p_dirichlet_char_clear x+ return $ DirichletChar x++-- | Use DirichletChar in `f`.+{-# INLINE withDirichletChar #-}+withDirichletChar (DirichletChar p) f = do+ withForeignPtr p $ \fp -> (DirichletChar p,) <$> f fp++-- | Apply `f` to new DirichletChar.+{-# INLINE withNewDirichletChar #-}+withNewDirichletChar group f = do+ x <- newDirichletChar group+ withDirichletChar x f++instance Storable CDirichletChar where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size dirichlet_char_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment dirichlet_char_t}+ peek ptr = CDirichletChar+ <$> #{peek dirichlet_char_struct, n } ptr+ <*> #{peek dirichlet_char_struct, log} ptr+ poke ptr (CDirichletChar n log) = do+ #{poke dirichlet_char_struct, n } ptr n+ #{poke dirichlet_char_struct, log } ptr log++--------------------------------------------------------------------------------++-- | /dirichlet_char_init/ /chi/ /G/ +-- +-- Initializes /chi/ to an element of the group /G/ and sets its value to+-- the principal character.+foreign import ccall "dirichlet.h dirichlet_char_init"+ dirichlet_char_init :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO ()++-- | /dirichlet_char_clear/ /chi/ +-- +-- Clears /chi/.+foreign import ccall "dirichlet.h dirichlet_char_clear"+ dirichlet_char_clear :: Ptr CDirichletChar -> IO ()++foreign import ccall "dirichlet.h &dirichlet_char_clear"+ p_dirichlet_char_clear :: FunPtr (Ptr CDirichletChar -> IO ())++-- | /dirichlet_char_print/ /G/ /chi/ +-- +-- Prints the array of exponents representing this character.+foreign import ccall "dirichlet.h dirichlet_char_print"+ dirichlet_char_print :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO ()++-- | /dirichlet_char_log/ /x/ /G/ /m/ +-- +-- Sets /x/ to the character of number /m/, computing its log using+-- discrete logarithm in /G/.+foreign import ccall "dirichlet.h dirichlet_char_log"+ dirichlet_char_log :: Ptr CDirichletChar -> Ptr CDirichletGroup -> CULong -> IO ()++-- | /dirichlet_char_exp/ /G/ /x/ +-- +-- Returns the number /m/ corresponding to exponents in /x/.+foreign import ccall "dirichlet.h dirichlet_char_exp"+ dirichlet_char_exp :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CULong++-- | /_dirichlet_char_exp/ /x/ /G/ +-- +-- Computes and returns the number /m/ corresponding to exponents in /x/.+-- This function is for internal use.+foreign import ccall "dirichlet.h _dirichlet_char_exp"+ _dirichlet_char_exp :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO CULong++-- | /dirichlet_char_one/ /x/ /G/ +-- +-- Sets /x/ to the principal character in /G/, having /log/+-- \([0,\dots 0]\).+foreign import ccall "dirichlet.h dirichlet_char_one"+ dirichlet_char_one :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO ()++-- | /dirichlet_char_first_primitive/ /x/ /G/ +-- +-- Sets /x/ to the first primitive character of /G/, having /log/+-- \([1,\dots 1]\), or \([0, 1, \dots 1]\) if \(8\mid q\).+foreign import ccall "dirichlet.h dirichlet_char_first_primitive"+ dirichlet_char_first_primitive :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO ()++-- | /dirichlet_char_set/ /x/ /G/ /y/ +-- +-- Sets /x/ to the element /y/.+foreign import ccall "dirichlet.h dirichlet_char_set"+ dirichlet_char_set :: Ptr CDirichletChar -> Ptr CDirichletGroup -> Ptr CDirichletChar -> IO ()++-- | /dirichlet_char_next/ /x/ /G/ +-- +-- Sets /x/ to the next character in /G/ according to lexicographic+-- ordering of /log/.+-- +-- The return value is the index of the last updated exponent of /x/, or+-- /-1/ if the last element has been reached.+-- +-- This function allows to iterate on all elements of /G/ looping on their+-- /log/. Note that it produces elements in seemingly random /number/+-- order.+-- +-- The following template can be used for such a loop:+-- +-- > dirichlet_char_one(chi, G);+-- > do {+-- > /* use character chi */+-- > } while (dirichlet_char_next(chi, G) >= 0);+foreign import ccall "dirichlet.h dirichlet_char_next"+ dirichlet_char_next :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO CInt++-- | /dirichlet_char_next_primitive/ /x/ /G/ +-- +-- Same as @dirichlet_char_next@, but jumps to the next primitive character+-- of /G/.+foreign import ccall "dirichlet.h dirichlet_char_next_primitive"+ dirichlet_char_next_primitive :: Ptr CDirichletChar -> Ptr CDirichletGroup -> IO CInt++-- | /dirichlet_index_char/ /G/ /x/ +-- +-- Returns the lexicographic index of the /log/ of /x/ as an integer in+-- \(0\dots \varphi(q)\).+foreign import ccall "dirichlet.h dirichlet_index_char"+ dirichlet_index_char :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CULong++-- | /dirichlet_char_index/ /x/ /G/ /j/ +-- +-- Sets /x/ to the character whose /log/ has lexicographic index /j/.+foreign import ccall "dirichlet.h dirichlet_char_index"+ dirichlet_char_index :: Ptr CDirichletChar -> Ptr CDirichletGroup -> CULong -> IO ()++foreign import ccall "dirichlet.h dirichlet_char_eq"+ dirichlet_char_eq :: Ptr CDirichletChar -> Ptr CDirichletChar -> IO CInt++-- | /dirichlet_char_eq_deep/ /G/ /x/ /y/ +-- +-- Return 1 if /x/ equals /y/.+-- +-- The second version checks every byte of the representation and is+-- intended for testing only.+foreign import ccall "dirichlet.h dirichlet_char_eq_deep"+ dirichlet_char_eq_deep :: Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletChar -> IO CInt++-- Character properties --------------------------------------------------------++-- As a consequence of the Conrey numbering, all these numbers are+-- available at the level of /number/ and /char/ object. Both case require+-- no discrete log computation.+--+-- | /dirichlet_char_is_principal/ /G/ /chi/ +-- +-- Returns 1 if /chi/ is the principal character mod /q/.+foreign import ccall "dirichlet.h dirichlet_char_is_principal"+ dirichlet_char_is_principal :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CInt++foreign import ccall "dirichlet.h dirichlet_conductor_ui"+ dirichlet_conductor_ui :: Ptr CDirichletGroup -> CULong -> IO CULong++-- | /dirichlet_conductor_char/ /G/ /x/ +-- +-- Returns the /conductor/ of \(\chi_q(a,\cdot)\), that is the smallest+-- \(r\) dividing \(q\) such \(\chi_q(a,\cdot)\) can be obtained as a+-- character mod \(r\).+foreign import ccall "dirichlet.h dirichlet_conductor_char"+ dirichlet_conductor_char :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CULong++foreign import ccall "dirichlet.h dirichlet_parity_ui"+ dirichlet_parity_ui :: Ptr CDirichletGroup -> CULong -> IO CInt++-- | /dirichlet_parity_char/ /G/ /x/ +-- +-- Returns the /parity/ \(\lambda\) in \(\{0,1\}\) of \(\chi_q(a,\cdot)\),+-- such that \(\chi_q(a,-1)=(-1)^\lambda\).+foreign import ccall "dirichlet.h dirichlet_parity_char"+ dirichlet_parity_char :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CInt++foreign import ccall "dirichlet.h dirichlet_order_ui"+ dirichlet_order_ui :: Ptr CDirichletGroup -> CULong -> IO CULong++-- | /dirichlet_order_char/ /G/ /x/ +-- +-- Returns the order of \(\chi_q(a,\cdot)\) which is the order of+-- \(a\bmod q\).+foreign import ccall "dirichlet.h dirichlet_order_char"+ dirichlet_order_char :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CULong++-- | /dirichlet_char_is_real/ /G/ /chi/ +-- +-- Returns 1 if /chi/ is a real character (iff it has order \(\leq 2\)).+foreign import ccall "dirichlet.h dirichlet_char_is_real"+ dirichlet_char_is_real :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CInt++-- | /dirichlet_char_is_primitive/ /G/ /chi/ +-- +-- Returns 1 if /chi/ is primitive (iff its conductor is exactly /q/).+foreign import ccall "dirichlet.h dirichlet_char_is_primitive"+ dirichlet_char_is_primitive :: Ptr CDirichletGroup -> Ptr CDirichletChar -> IO CInt++-- Character evaluation --------------------------------------------------------++-- Dirichlet characters take value in a finite cyclic group of roots of+-- unity plus zero.+--+-- Evaluation functions return a /ulong/, this number corresponds to the+-- power of a primitive root of unity, the special value+-- /DIRICHLET_CHI_NULL/ encoding the zero value.+--+foreign import ccall "dirichlet.h dirichlet_pairing"+ dirichlet_pairing :: Ptr CDirichletGroup -> CULong -> CULong -> IO CULong++-- | /dirichlet_pairing_char/ /G/ /chi/ /psi/ +-- +-- Compute the value of the Dirichlet pairing on numbers /m/ and /n/, as+-- exponent modulo /G->expo/.+-- +-- The /char/ variant takes as input two characters, so that no discrete+-- logarithm is computed.+-- +-- The returned value is the numerator of the actual value exponent mod the+-- group exponent /G->expo/.+foreign import ccall "dirichlet.h dirichlet_pairing_char"+ dirichlet_pairing_char :: Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletChar -> IO CULong++-- | /dirichlet_chi/ /G/ /chi/ /n/ +-- +-- Compute the value \(\chi(n)\) as the exponent modulo /G->expo/.+foreign import ccall "dirichlet.h dirichlet_chi"+ dirichlet_chi :: Ptr CDirichletGroup -> Ptr CDirichletChar -> CULong -> IO CULong++-- | /dirichlet_chi_vec/ /v/ /G/ /chi/ /nv/ +-- +-- Compute the list of exponent values /v[k]/ for \(0\leq k < nv\), as+-- exponents modulo /G->expo/.+foreign import ccall "dirichlet.h dirichlet_chi_vec"+ dirichlet_chi_vec :: Ptr CULong -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CLong -> IO ()++-- | /dirichlet_chi_vec_order/ /v/ /G/ /chi/ /order/ /nv/ +-- +-- Compute the list of exponent values /v[k]/ for \(0\leq k < nv\), as+-- exponents modulo /order/, which is assumed to be a multiple of the order+-- of /chi/.+foreign import ccall "dirichlet.h dirichlet_chi_vec_order"+ dirichlet_chi_vec_order :: Ptr CULong -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CULong -> CLong -> IO ()++-- Character operations --------------------------------------------------------++-- | /dirichlet_char_mul/ /chi12/ /G/ /chi1/ /chi2/ +-- +-- Multiply two characters of the same group /G/.+foreign import ccall "dirichlet.h dirichlet_char_mul"+ dirichlet_char_mul :: Ptr CDirichletChar -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletChar -> IO ()++-- | /dirichlet_char_pow/ /c/ /G/ /a/ /n/ +-- +-- Take the power of a character.+foreign import ccall "dirichlet.h dirichlet_char_pow"+ dirichlet_char_pow :: Ptr CDirichletChar -> Ptr CDirichletGroup -> Ptr CDirichletChar -> CULong -> IO ()++-- | /dirichlet_char_lift/ /chi_G/ /G/ /chi_H/ /H/ +-- +-- If /H/ is a subgroup of /G/, computes the character in /G/ corresponding+-- to /chi_H/ in /H/.+foreign import ccall "dirichlet.h dirichlet_char_lift"+ dirichlet_char_lift :: Ptr CDirichletChar -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletGroup -> IO ()++-- | /dirichlet_char_lower/ /chi_H/ /H/ /chi_G/ /G/ +-- +-- If /chi_G/ is a character of /G/ which factors through /H/, sets /chi_H/+-- to the corresponding restriction in /H/.+-- +-- This requires \(c(\chi_G)\mid q_H\mid q_G\), where \(c(\chi_G)\) is the+-- conductor of \(\chi_G\) and \(q_G, q_H\) are the moduli of G and H.+foreign import ccall "dirichlet.h dirichlet_char_lower"+ dirichlet_char_lower :: Ptr CDirichletChar -> Ptr CDirichletGroup -> Ptr CDirichletChar -> Ptr CDirichletGroup -> IO ()+
+ src/Data/Number/Flint/Groups/Perm.hs view
@@ -0,0 +1,13 @@+{-|+module : Data.Number.Flint.Groups.Perm+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Groups.Perm (+ module Data.Number.Flint.Groups.Perm.FFI,+) where++import Data.Number.Flint.Groups.Perm.FFI+
+ src/Data/Number/Flint/Groups/Perm/FFI.hsc view
@@ -0,0 +1,158 @@+{-|+module : Data.Number.Flint.Groups.Perm.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Groups.Perm.FFI (+ -- * Permutations+ _perm_init+ , _perm_clear+ -- * Assignment+ , _perm_set+ , _perm_set_one+ , _perm_inv+ -- * Composition+ , _perm_compose+ , _perm_power+ -- * Randomisation+ , _perm_randtest+ -- * Input and output+ , _perm_print+ , _perm_print_pretty+ , _perm_fprint_pretty+ , _perm_get_str_pretty+ -- * Properties+ , _perm_order+ , _perm_parity+ , _perm_mat+) where ++-- permutations ----------------------------------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free, peekArray )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mat++#include <flint/flint.h>+#include <flint/perm.h>++--------------------------------------------------------------------------------++-- | /_perm_init/ /n/ +-- +-- Initialises the permutation for use.+foreign import ccall "perm.h _perm_init"+ _perm_init :: CLong -> IO (Ptr CLong)++-- | /_perm_clear/ /vec/ +-- +-- Clears the permutation.+foreign import ccall "perm.h _perm_clear"+ _perm_clear :: Ptr CLong -> IO ()++-- Assignment ------------------------------------------------------------------++-- | /_perm_set/ /res/ /vec/ /n/ +-- +-- Sets the permutation @res@ to the same as the permutation @vec@.+foreign import ccall "perm.h _perm_set"+ _perm_set :: Ptr CLong -> Ptr CLong -> CLong -> IO ()++-- | /_perm_set_one/ /vec/ /n/ +-- +-- Sets the permutation to the identity permutation.+foreign import ccall "perm.h _perm_set_one"+ _perm_set_one :: Ptr CLong -> CLong -> IO ()++-- | /_perm_inv/ /res/ /vec/ /n/ +-- +-- Sets @res@ to the inverse permutation of @vec@. Allows aliasing of @res@+-- and @vec@.+foreign import ccall "perm.h _perm_inv"+ _perm_inv :: Ptr CLong -> Ptr CLong -> CLong -> IO ()++-- Composition -----------------------------------------------------------------++-- | /_perm_compose/ /res/ /vec1/ /vec2/ /n/ +-- +-- Forms the composition \(\pi_1 \circ \pi_2\) of two permutations+-- \(\pi_1\) and \(\pi_2\). Here, \(\pi_2\) is applied first, that is,+-- \((\pi_1 \circ \pi_2)(i) = \pi_1(\pi_2(i))\).+-- +-- Allows aliasing of @res@, @vec1@ and @vec2@.+foreign import ccall "perm.h _perm_compose"+ _perm_compose :: Ptr CLong -> Ptr CLong -> Ptr CLong -> CLong -> IO ()++foreign import ccall "perm.h _perm_power"+ _perm_power :: Ptr CLong -> Ptr CLong -> CLong -> CLong -> IO ()++-- Parity ----------------------------------------------------------------------++-- | /_perm_parity/ /vec/ /n/ +-- +-- Returns the parity of @vec@, 0 if the permutation is even and 1 if the+-- permutation is odd.+foreign import ccall "perm.h _perm_parity"+ _perm_parity :: Ptr CLong -> CLong -> IO CInt++foreign import ccall "perm.h _perm_order"+ _perm_order :: Ptr CFmpz -> Ptr CLong -> CLong -> IO ()++foreign import ccall "perm.h _perm_mat"+ _perm_mat :: Ptr CFmpzMat -> Ptr CLong -> CLong -> IO ()++-- Randomisation ---------------------------------------------------------------++-- | /_perm_randtest/ /vec/ /n/ /state/ +-- +-- Generates a random permutation vector of length \(n\) and returns its+-- parity, 0 or 1.+-- +-- This function uses the Knuth shuffle algorithm to generate a uniformly+-- random permutation without retries.+foreign import ccall "perm.h _perm_randtest"+ _perm_randtest :: Ptr CLong -> CLong -> Ptr CFRandState -> IO CInt++-- Input and output ------------------------------------------------------------++-- | /_perm_print/ /vec/ /n/ +-- +-- Prints the permutation vector of length \(n\) to @stdout@.+_perm_print :: Ptr CLong -> CLong -> IO CInt+_perm_print p n = do+ a <- peekArray (fromIntegral n) p+ putStr $ show n ++ " "+ forM_ a $ \x -> putStr $ " " ++ show x+ return 1++-- | /_perm_get_str_pretty/ /vec/ /n/ +--+-- Return a string representation of permutation vector of length \(n\)+-- in cycle representation.+foreign import ccall "perm.h _perm_get_str_pretty"+ _perm_get_str_pretty :: Ptr CLong -> CLong -> IO CString+++-- | /_perm_print_pretty/ /vec/ /n/ +--+-- Prints permutation vector of length \(n\) in cycle representation+-- to @stdout@.+_perm_print_pretty :: Ptr CLong -> CLong -> IO CInt+_perm_print_pretty p n = printCStr (flip _perm_get_str_pretty n) p++-- | /_perm_fprint_pretty/ /vec/ /n/ +--+-- Prints permutation vector of length \(n\) in cycle representation+-- to @file@.+foreign import ccall "perm.h _perm_fprint_pretty"+ _perm_fprint_pretty :: Ptr CFile -> Ptr CLong -> CLong -> IO ()
+ src/Data/Number/Flint/Groups/Qfb.hs view
@@ -0,0 +1,13 @@+{-|+module : Data.Number.Flint.Groups.Qfb+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.Groups.Qfb (+ module Data.Number.Flint.Groups.Qfb.FFI,+) where++import Data.Number.Flint.Groups.Qfb.FFI+
+ src/Data/Number/Flint/Groups/Qfb/FFI.hsc view
@@ -0,0 +1,383 @@+{-|+module : Data.Number.Flint.Groups.Qfb.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Groups.Qfb.FFI (+ -- * Binary quadratic forms+ Qfb (..)+ , CQfb (..)+ , newQfb+ , withQfb+ , withNewQfb+ -- * Memory management+ , qfb_init+ , qfb_clear+ , qfb_array_clear+ -- * Hash table+ , qfb_hash_init+ , qfb_hash_clear+ , qfb_hash_insert+ , qfb_hash_find+ -- * Basic manipulation+ , qfb_set+ -- * Comparison+ , qfb_equal+ -- * Input\/output+ , qfb_get_str+ , qfb_fprint+ , qfb_print+ -- * Computing with forms+ , qfb_discriminant+ , qfb_reduce+ , qfb_is_reduced+ , qfb_reduced_forms+ , qfb_reduced_forms_large+ , qfb_nucomp+ , qfb_nudupl+ , qfb_pow_ui+ , qfb_pow+ , qfb_inverse+ , qfb_is_principal_form+ , qfb_principal_form+ , qfb_is_primitive+ , qfb_prime_form+ , qfb_exponent_element+ , qfb_exponent+ , qfb_exponent_grh+) where ++-- Binary quadratic forms ------------------------------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable+import Foreign.C.Types+import Foreign.C.String+import Foreign.Marshal.Array+import Foreign.Marshal.Alloc++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.MPoly++import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fmpq.Poly++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb.Types++#include <flint/qfb.h>++-- qfb_t -----------------------------------------------------------------------++data Qfb = Qfb {-# UNPACK #-} !(ForeignPtr CQfb)+data CQfb = CQfb (Ptr CFmpz) (Ptr CFmpz) (Ptr CFmpz)++instance Storable CQfb where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size qfb_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment qfb_t}+ peek ptr = do+ let q = castPtr ptr :: Ptr CFmpz+ return $ CQfb q (q `advancePtr` 1) (q `advancePtr` 2)+ + poke = error "CQfb.poke: undefined."++-- | Create a Qfb.+newQfb a b c = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p -> do+ qfb_init p+ CQfb ap bp cp <- peek p+ withFmpz a $ \a -> fmpz_set ap a+ withFmpz b $ \b -> fmpz_set bp b+ withFmpz c $ \c -> fmpz_set cp c+ addForeignPtrFinalizer p_qfb_clear p+ return $ Qfb p++-- | Use Qfb in `f`.+{-# INLINE withQfb #-}+withQfb (Qfb p) f = do+ withForeignPtr p $ \fp -> (Qfb p,) <$> f fp++-- | Apply `f` to new Qfb.+{-# INLINE withNewQfb #-}+withNewQfb a b c f = do+ x <- newQfb a b c+ withQfb x f++-- Memory management -----------------------------------------------------------++-- | /qfb_init/ /q/ +-- +-- Initialise a code{qfb_t} \(q\) for use.+foreign import ccall "qbf.h qfb_init"+ qfb_init :: Ptr CQfb -> IO ()++-- | /qfb_clear/ /q/ +-- +-- Clear a code{qfb_t} after use. This releases any memory allocated for+-- \(q\) back to flint.+foreign import ccall "qbf.h qfb_clear"+ qfb_clear :: Ptr CQfb -> IO ()++foreign import ccall "qbf.h &qfb_clear"+ p_qfb_clear :: FunPtr (Ptr CQfb -> IO ())++-- | /qfb_array_clear/ /forms/ /num/ +-- +-- Clean up an array of code{qfb} structs allocated by a qfb function. The+-- parameter code{num} must be set to the length of the array.+foreign import ccall "qbf.h qfb_array_clear"+ qfb_array_clear :: Ptr (Ptr CQfb) -> CLong -> IO ()++-- Hash table ------------------------------------------------------------------++data QfbHash = QfbHash {-# UNPACK #-} !(ForeignPtr CQfbHash)+type CQfbHash = CFlint QfbHash++-- | /qfb_hash_init/ /depth/ +-- +-- Initialises a hash table of size \(2^{depth}\).+foreign import ccall "qbf.h qfb_hash_init"+ qfb_hash_init :: CLong -> IO (Ptr (Ptr CQfbHash))++-- | /qfb_hash_clear/ /qhash/ /depth/ +-- +-- Frees all memory used by a hash table of size \(2^{depth}\).+foreign import ccall "qbf.h qfb_hash_clear"+ qfb_hash_clear :: Ptr (Ptr CQfbHash) -> CLong -> IO ()++-- | /qfb_hash_insert/ /qhash/ /q/ /q2/ /iter/ /depth/ +-- +-- Insert the binary quadratic form code{q} into the given hash table of+-- size \(2^{depth}\) in the field code{q} of the hash structure. Also+-- store the second binary quadratic form code{q2} (if not code{NULL}) in+-- the similarly named field and code{iter} in the similarly named field of+-- the hash structure.+foreign import ccall "qbf.h qfb_hash_insert"+ qfb_hash_insert :: Ptr (Ptr CQfbHash) -> Ptr CQfb -> Ptr CQfb -> CLong -> CLong -> IO ()++-- | /qfb_hash_find/ /qhash/ /q/ /depth/ +-- +-- Search for the given binary quadratic form or its inverse in the given+-- hash table of size \(2^{depth}\). If it is found, return the index in+-- the table (which is an array of code{qfb_hash_t} structs, otherwise+-- return code{-1L}.+foreign import ccall "qbf.h qfb_hash_find"+ qfb_hash_find :: Ptr (Ptr CQfbHash) -> Ptr CQfb -> CLong -> IO CLong++-- Basic manipulation ----------------------------------------------------------++-- | /qfb_set/ /f/ /g/ +-- +-- Set the binary quadratic form \(f\) to be equal to \(g\).+foreign import ccall "qbf.h qfb_set"+ qfb_set :: Ptr CQfb -> Ptr CQfb -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /qfb_equal/ /f/ /g/ +-- +-- Returns \(1\) if \(f\) and \(g\) are identical binary quadratic forms,+-- otherwise returns \(0\).+foreign import ccall "qbf.h qfb_equal"+ qfb_equal :: Ptr CQfb -> Ptr CQfb -> IO CInt++-- Input\/output ---------------------------------------------------------------++foreign import ccall "qfb.h qfb_get_str"+ qfb_get_str :: Ptr CQfb -> IO CString++foreign import ccall "qfb.h qfb_fprint"+ qfb_fprint :: Ptr CFile -> Ptr CQfb -> IO CString++-- | /qfb_print/ /q/ +-- +-- Print a binary quadratic form \(q\) in the format \((a, b, c)\) where+-- \(a\), \(b\), \(c\) are the entries of \(q\).+qfb_print :: Ptr CQfb -> IO ()+qfb_print x = do+ cs <- qfb_get_str x+ s <- peekCString cs+ free cs+ putStr s+ +-- Computing with forms --------------------------------------------------------++-- | /qfb_discriminant/ /D/ /f/ +-- +-- Set \(D\) to the discriminant of the binary quadratic form \(f\), i.e.+-- to \(b^2 - 4ac\), where \(f = (a, b, c)\).+foreign import ccall "qbf.h qfb_discriminant"+ qfb_discriminant :: Ptr CFmpz -> Ptr CQfb -> IO ()++-- | /qfb_reduce/ /r/ /f/ /D/ +-- +-- Set \(r\) to the reduced form equivalent to the binary quadratic form+-- \(f\) of discriminant \(D\).+foreign import ccall "qbf.h qfb_reduce"+ qfb_reduce :: Ptr CQfb -> Ptr CQfb -> Ptr CFmpz -> IO ()++-- | /qfb_is_reduced/ /r/ +-- +-- Returns \(1\) if \(q\) is a reduced binary quadratic form. Otherwise+-- returns \(1\).+foreign import ccall "qbf.h qfb_is_reduced"+ qfb_is_reduced :: Ptr CQfb -> IO CInt++-- | /qfb_reduced_forms/ /forms/ /d/ +-- +-- Given a discriminant \(d\) (negative for negative definite forms),+-- compute all the reduced binary quadratic forms of that discriminant. The+-- function allocates space for these and returns it in the variable+-- code{forms} (the user is responsible for cleaning this up by a single+-- call to code{qfb_array_clear} on code{forms}, after use. The function+-- returns the number of forms generated (the form class number). The forms+-- are stored in an array of code{qfb} structs, which contain fields+-- code{a, b, c} corresponding to forms \((a, b, c)\).+foreign import ccall "qbf.h qfb_reduced_forms"+ qfb_reduced_forms :: Ptr (Ptr CQfb) -> CLong -> IO CLong++-- | /qfb_reduced_forms_large/ /forms/ /d/ +-- +-- As for @qfb_reduced_forms@. However, for small \(|d|\) it requires fewer+-- primes to be computed at a small cost in speed. It is called+-- automatically by code{qfb_reduced_forms} for large \(|d|\) so that+-- @flint_primes@ is not exhausted.+foreign import ccall "qbf.h qfb_reduced_forms_large"+ qfb_reduced_forms_large :: Ptr (Ptr CQfb) -> CLong -> IO CLong++-- | /qfb_nucomp/ /r/ /f/ /g/ /D/ /L/ +-- +-- Shanks\' NUCOMP as described in~citep{JacvdP}+-- +-- % Computational aspects of NUCOMP\", Michael J. Jacobson Jr., % Alfred+-- J. van der Poorten, ANTS 2002, LNCS 2369, pp. 120--133.+-- +-- Computes the near reduced composition of forms \(f\) and \(g\) given+-- \(L = \lfloor |D|^{1/4} \rfloor\) where \(D\) is the common discriminant+-- of \(f\) and \(g\). The result is returned in \(r\).+-- +-- We require that that \(f\) is a primitive form.+foreign import ccall "qbf.h qfb_nucomp"+ qfb_nucomp :: Ptr CQfb -> Ptr CQfb -> Ptr CQfb -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /qfb_nudupl/ /r/ /f/ /D/ /L/ +-- +-- As for code{nucomp} except that the form \(f\) is composed with itself.+-- We require that that \(f\) is a primitive form.+foreign import ccall "qbf.h qfb_nudupl"+ qfb_nudupl :: Ptr CQfb -> Ptr CQfb -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /qfb_pow_ui/ /r/ /f/ /D/ /exp/ +-- +-- Compute the near reduced form \(r\) which is the result of composing the+-- principal form (identity) with \(f\) code{exp} times.+-- +-- We require \(D\) to be set to the discriminant of \(f\) and that \(f\)+-- is a primitive form.+foreign import ccall "qbf.h qfb_pow_ui"+ qfb_pow_ui :: Ptr CQfb -> Ptr CQfb -> Ptr CFmpz -> CULong -> IO ()++-- | /qfb_pow/ /r/ /f/ /D/ /exp/ +-- +-- As per code{qfb_pow_ui}.+foreign import ccall "qbf.h qfb_pow"+ qfb_pow :: Ptr CQfb -> Ptr CQfb -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /qfb_inverse/ /r/ /f/ +-- +-- Set \(r\) to the inverse of the binary quadratic form \(f\).+foreign import ccall "qbf.h qfb_inverse"+ qfb_inverse :: Ptr CQfb -> Ptr CQfb -> IO ()++-- | /qfb_is_principal_form/ /f/ /D/ +-- +-- Return \(1\) if \(f\) is the reduced principal form of discriminant+-- \(D\), i.e. the identity in the form class group.+foreign import ccall "qbf.h qfb_is_principal_form"+ qfb_is_principal_form :: Ptr CQfb -> Ptr CFmpz -> IO CInt++-- | /qfb_principal_form/ /f/ /D/ +-- +-- Set \(f\) to the principal form of discriminant \(D\), i.e. the identity+-- in the form class group.+foreign import ccall "qbf.h qfb_principal_form"+ qfb_principal_form :: Ptr CQfb -> Ptr CFmpz -> IO ()++-- | /qfb_is_primitive/ /f/ +-- +-- Return \(1\) if \(f\) is primitive, i.e. the greatest common divisor of+-- its three coefficients is \(1\). Otherwise the function returns \(0\).+foreign import ccall "qbf.h qfb_is_primitive"+ qfb_is_primitive :: Ptr CQfb -> IO CInt++-- | /qfb_prime_form/ /r/ /D/ /p/ +-- +-- Sets \(r\) to the unique prime \((p, b, c)\) of discriminant \(D\), i.e.+-- with \(0 < b \leq p\). We require that \(p\) is a prime.+foreign import ccall "qbf.h qfb_prime_form"+ qfb_prime_form :: Ptr CQfb -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- | /qfb_exponent_element/ /exponent/ /f/ /n/ /B1/ /B2_sqrt/ +-- +-- Find the exponent of the element \(f\) in the form class group of forms+-- of discriminant \(n\), doing a stage \(1\) with primes up to at least+-- code{B1} and a stage \(2\) for a single large prime up to at least the+-- square of code{B2}. If the function fails to find the exponent it+-- returns \(0\), otherwise the function returns \(1\) and code{exponent}+-- is set to the exponent of \(f\), i.e. the minimum power of \(f\) which+-- gives the identity.+-- +-- It is assumed that the form \(f\) is reduced. We require that+-- code{iters} is a power of \(2\) and that code{iters} >= 1024.+-- +-- The function performs a stage \(2\) which stores up to \(4\times\)+-- code{iters} binary quadratic forms, and \(12\times\) code{iters}+-- additional limbs of data in a hash table, where code{iters} is the+-- square root of code{B2}.+foreign import ccall "qbf.h qfb_exponent_element"+ qfb_exponent_element :: Ptr CFmpz -> Ptr CQfb -> Ptr CFmpz -> CULong -> CULong -> IO CInt++-- | /qfb_exponent/ /exponent/ /n/ /B1/ /B2_sqrt/ /c/ +-- +-- Compute the exponent of the class group of discriminant \(n\), doing a+-- stage \(1\) with primes up to at least code{B1} and a stage \(2\) for a+-- single large prime up to at least the square of code{B2_sqrt}, and with+-- probability at least \(1 - 2^{-c}\). If the prime limits are exhausted+-- without finding the exponent, the function returns \(0\), otherwise it+-- returns \(1\) and code{exponent} is set to the computed exponent, i.e.+-- the minimum power which every element of the class group has to be+-- raised to give the identity.+-- +-- The function performs a stage \(2\) which stores up to \(4\times\)+-- code{iters} binary quadratic forms, and \(12\times\) code{iters}+-- additional limbs of data in a hash table, where code{iters} is the+-- square root of code{B2}.+-- +-- We use algorithm 8.1 of~citep{SuthThesis}+-- +-- % \"Order Computations in Generic Groups\", Andrew Sutherland, % MIT+-- Thesis 2007. %+-- <http://groups.csail.mit.edu/cis/theses/sutherland-phd.pdf>+foreign import ccall "qbf.h qfb_exponent"+ qfb_exponent :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CULong -> CLong -> IO CInt++-- | /qfb_exponent_grh/ /exponent/ /n/ /iters/ /B1/ /B2_sqrt/ +-- +-- As per code{qfb_exponent} except that the bound code{c} is automatically+-- generated such that the exponent it guaranteed to be correct, if found,+-- assuming the GRH, namely that the class group is generated by primes+-- less than \(6\log^2(|n|)\) as per~citep{BuchDull1992}+-- +-- % \"Distributed Class Group Computation\", Johannes Buchmann, Stephan %+-- D\"{u}llman, Informatik 1 (1992), pp. 69--79.+foreign import ccall "qbf.h qfb_exponent_grh"+ qfb_exponent_grh :: Ptr CFmpz -> Ptr CFmpz -> CULong -> CULong -> CULong -> IO CInt+
+ src/Data/Number/Flint/Groups/Qfb/Instances.hs view
@@ -0,0 +1,16 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Groups.Qfb.Instances where++import System.IO.Unsafe+import Foreign.C.String+import Foreign.Marshal.Alloc ( free )++import Data.Number.Flint.Groups.Qfb++instance Show Qfb where+ show x = unsafePerformIO $ do+ (_, cs) <- withQfb x qfb_get_str+ s <- peekCString cs+ free cs+ return s+
+ src/Data/Number/Flint/Hypgeom.hs view
@@ -0,0 +1,125 @@+{-|+module : Data.Number.Flint.Hypgeom+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de ++== Support for hypergeometric series++This module provides functions for high-precision evaluation of series+of the form++\[+ \sum_{k=0}^{n-1} \frac{A(k)}{B(k)} \prod_{j=1}^k \frac{P(k)}{Q(k)} z^k+\]++where \(A, B, P, Q\) are polynomials. The present version only supports+A, B, P, Q in mathbb{Z}[k] (represented using the FLINT /fmpz_poly_t/+type). This module also provides functions for high-precision evaluation+of infinite series (n to infty), with automatic, rigorous error+bounding.++Note that we can standardize to \(A = B = 1\) by+setting \(\tilde P(k) = P(k) A(k) B(k-1), \tilde Q(k) = Q(k) A(k-1) B(k)\).+However, separating out \(A\) and \(B\) is convenient and improves+efficiency during evaluation.++== Strategy for error bounding ++We wish to evaluate \(S(z) = \sum_{k=0}^{\infty} T(k) z^k\) where \(T(k)\) +satisfies \(T(0) = 1\) and++\[+ T(k) = R(k) T(k-1) = \left( \frac{P(k)}{Q(k)} \right) T(k-1)+\]++for given polynomials++\[\begin{align}+ P(k) &= a_p k^p + a_{p-1} k^{p-1} + \ldots a_0\\+ Q(k) &= b_q k^q + b_{q-1} k^{q-1} + \ldots b_0.+\end{align}\]++For convergence, we require \(p < q\), or \(p = q\) with \(|z| |a_p| < |b_q|\).+We also assume that \(P(k)\) and \(Q(k)\) have no+roots among the positive integers (if there are positive integer roots,+the sum is either finite or undefined). With these conditions satisfied,+our goal is to find a parameter \(n \ge 0\) such that++\[+ {\left\lvert \sum_{k=n}^{\infty} T(k) z^k \right\rvert} \le 2^{\\-d}.+\]++We can rewrite the hypergeometric term ratio as++\[+ \[z R(k) = z \frac{P(k)}{Q(k)} =+ z \left( \frac{a_p}{b_q} \right) \frac{1}{k^{q-p}} F(k)+\]++where++\[+ F(k) = \frac{+ 1 + \tilde a_{1} / k + \tilde a_{2} / k^2 + \ldots + \tilde a_q / k^p+ }{+ 1 + \tilde b_{1} / k + \tilde b_{2} / k^2 + \ldots + \tilde b_q / k^q+ } = 1 + O(1/k)+\]++and where \(\tilde a_i = a_{p-i} / a_p\), \(\tilde b_i = b_{q-i} / b_q\). +Next, we define++\[+ C = \max_{1 \le i \le p} |\tilde a_i|^{(1/i)},+ \quad D = \max_{1 \le i \le q} |\tilde b_i|^{(1/i)}.+\]++Now, if \(k > C\), the magnitude of the numerator of \(F(k)\) is bounded+from above by++\[+ 1 + \sum_{i=1}^p \left(\frac{C}{k}\right)^i \le 1 + \frac{C}{k-C}+\]++and if \(k > 2D\), the magnitude of the denominator of \(F(k)\) is+bounded from below by++\[+ 1 - \sum_{i=1}^q \left(\frac{D}{k}\right)^i \ge 1 + \frac{D}{D-k}.+\]++Putting the inequalities together gives the following bound, +valid for \(k > K = \max(C, 2D)\):++\[+ |F(k)| \le \frac{k (k-D)}{(k-C)(k-2D)} = \left(1 + \frac{C}{k-C} \right)+ \left(1 + \frac{D}{k-2D} \right).+\]++Let \(r = q-p\) and \(\tilde z = |z a_p / b_q|\).+Assuming \(k > max(C,2D, {\tilde z}^{1/r})\), we have++\[+ |z R(k)| \le G(k) = \frac{\tilde z F(k)}{k^r}+\]++where \(G(k)\) is monotonically decreasing. Now we just need to find an+n such that \(G(n) < 1\) and for +which \(|T(n)| / (1 - G(n)) \le 2^{\\-d}\). This can be done by computing a+floating-point guess for \(n\) then trying successively larger values.++This strategy leaves room for some improvement. For example, +if \(\tilde b_1\) is positive and large, the bound \(B\) becomes +very pessimistic (a+larger positive \(\tilde b_1\) causes faster convergence, not slower+convergence).+-}+++module Data.Number.Flint.Hypgeom (+ module Data.Number.Flint.Hypgeom.FFI+) where++import Data.Number.Flint.Hypgeom.FFI+
+ src/Data/Number/Flint/Hypgeom/FFI.hsc view
@@ -0,0 +1,143 @@+{-|+module : Data.Number.Flint.Hypgeom.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Hypgeom.FFI (+ -- * Support for hypergeometric series+ -- * Types+ Hypgeom (..)+ , CHypgeom (..)+ , newHypgeom+ , withHypgeom+ , withNewHypgeom+ -- * Memory management+ , hypgeom_init+ , hypgeom_clear+ -- * Error bounding+ , hypgeom_estimate_terms+ , hypgeom_bound+ , hypgeom_precompute+ -- * Summation+ , arb_hypgeom_sum+ , arb_hypgeom_infsum+) where++-- Support for hypergeometric series -------------------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable+import Foreign.C.Types++import Data.Number.Flint.Flint+import Data.Number.Flint.Arb.Types++#include <flint/hypgeom.h>++-- hypgeom_t -------------------------------------------------------------------++data Hypgeom = Hypgeom {-# UNPACK #-} !(ForeignPtr CHypgeom)+type CHypgeom = CFlint Hypgeom++instance Storable CHypgeom where+ sizeOf _ = #{size hypgeom_t}+ alignment _ = #{alignment hypgeom_t}+ peek = undefined+ poke = undefined++newHypgeom = do+ x <- mallocForeignPtr+ withForeignPtr x hypgeom_init+ addForeignPtrFinalizer p_hypgeom_clear x+ return $ Hypgeom x++withHypgeom (Hypgeom p) f = do+ withForeignPtr p $ \fp -> (Hypgeom p,) <$> f fp++withNewHypgeom f = do+ x <- newHypgeom+ withHypgeom x f+ +-- Memory management -----------------------------------------------------------++-- | /hypgeom_init/ /hyp/ +--+foreign import ccall "hypgeom.h hypgeom_init"+ hypgeom_init :: Ptr CHypgeom -> IO ()++-- | /hypgeom_clear/ /hyp/ +--+foreign import ccall "hypgeom.h hypgeom_clear"+ hypgeom_clear :: Ptr CHypgeom -> IO ()++foreign import ccall "hypgeom.h &hypgeom_clear"+ p_hypgeom_clear :: FunPtr (Ptr CHypgeom -> IO ())++-- Error bounding --------------------------------------------------------------++-- | /hypgeom_estimate_terms/ /z/ /r/ /d/ +--+-- Computes an approximation of the largest \(n\) such that+-- \(|z|^n/(n!)^r = 2^{-d}\), giving a first-order estimate of the number+-- of terms needed to approximate the sum of a hypergeometric series of+-- weight \(r \ge 0\) and argument \(z\) to an absolute precision of+-- \(d \ge 0\) bits. If \(r = 0\), the direct solution of the equation is+-- given by \(n = (\log(1-z) - d \log 2) / \log z\). If \(r > 0\), using+-- \(\log n! \approx n \log n - n\) gives an equation that can be solved in+-- terms of the Lambert /W/-function as \(n = (d \log 2) / (r\,W\!(t))\)+-- where \(t = (d \log 2) / (e r z^{1/r})\).+-- +-- The evaluation is done using double precision arithmetic. The function+-- aborts if the computed value of \(n\) is greater than or equal to+-- LONG_MAX \/ 2.+foreign import ccall "hypgeom.h hypgeom_estimate_terms"+ hypgeom_estimate_terms :: Ptr CMag -> CInt -> CLong -> IO CLong++-- | /hypgeom_bound/ /error/ /r/ /C/ /D/ /K/ /TK/ /z/ /prec/ +--+-- Computes a truncation parameter sufficient to achieve /prec/ bits of+-- absolute accuracy, according to the strategy described above. The input+-- consists of \(r\), \(C\), \(D\), \(K\), precomputed bound for \(T(K)\),+-- and \(\tilde z = z (a_p / b_q)\), such that for \(k > K\), the+-- hypergeometric term ratio is bounded by+-- +-- \[`\]+-- \[\frac{\tilde z}{k^r} \frac{k(k-D)}{(k-C)(k-2D)}.\]+-- +-- Given this information, we compute a \(\varepsilon\) and an integer+-- \(n\) such that+-- \(\left| \sum_{k=n}^{\infty} T(k) \right| \le \varepsilon \le 2^{-\mathrm{prec}}\).+-- The output variable /error/ is set to the value of \(\varepsilon\), and+-- \(n\) is returned.+foreign import ccall "hypgeom.h hypgeom_bound"+ hypgeom_bound :: Ptr CMag -> CInt -> CLong -> CLong -> CLong -> Ptr CMag -> Ptr CMag -> CLong -> IO CLong++-- | /hypgeom_precompute/ /hyp/ +--+-- Precomputes the bounds data \(C\), \(D\), \(K\) and an upper bound for+-- \(T(K)\).+foreign import ccall "hypgeom.h hypgeom_precompute"+ hypgeom_precompute :: Ptr CHypgeom -> IO ()++-- Summation -------------------------------------------------------------------++-- | /arb_hypgeom_sum/ /P/ /Q/ /hyp/ /n/ /prec/ +--+-- Computes \(P, Q\) such that \(P / Q = \sum_{k=0}^{n-1} T(k)\) where+-- \(T(k)\) is defined by /hyp/, using binary splitting and a working+-- precision of /prec/ bits.+foreign import ccall "hypgeom.h arb_hypgeom_sum"+ arb_hypgeom_sum :: Ptr CArb -> Ptr CArb -> Ptr CHypgeom -> CLong -> CLong -> IO ()++-- | /arb_hypgeom_infsum/ /P/ /Q/ /hyp/ /tol/ /prec/ +--+-- Computes \(P, Q\) such that \(P / Q = \sum_{k=0}^{\infty} T(k)\) where+-- \(T(k)\) is defined by /hyp/, using binary splitting and working+-- precision of /prec/ bits. The number of terms is chosen automatically to+-- bound the truncation error by at most \(2^{-\mathrm{tol}}\). The bound+-- for the truncation error is included in the output as part of /P/.+foreign import ccall "hypgeom.h arb_hypgeom_infsum"+ arb_hypgeom_infsum :: Ptr CArb -> Ptr CArb -> Ptr CHypgeom -> CLong -> CLong -> IO ()+
+ src/Data/Number/Flint/MPoly.hs view
@@ -0,0 +1,13 @@+{-|+module : Data.Number.Flint.Fq.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.MPoly (+ module Data.Number.Flint.MPoly.FFI+) where++import Data.Number.Flint.MPoly.FFI+
+ src/Data/Number/Flint/MPoly/FFI.hsc view
@@ -0,0 +1,611 @@+{-|+module : Data.Number.Flint.MPoly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.MPoly.FFI (+ -- * Support functions for multivariate polynomials+ MPolyCtx (..)+ , CMPolyCtx (..)+ , newMPolyCtx+ , withMPolyCtx+ -- * Context+ , mpoly_ctx_init+ , mpoly_ctx_clear+ , mpoly_ordering_randtest+ , mpoly_ctx_init_rand+ , mpoly_ordering_isdeg+ , mpoly_ordering_isrev+ , mpoly_ordering_print+ -- * Orderings+ , COrdering (..)+ , ord_lex+ , ord_deglex+ , ord_degrevlex+ -- * Monomial arithmetic+ , mpoly_monomial_add+ , mpoly_monomial_add_mp+ , mpoly_monomial_sub+ , mpoly_monomial_sub_mp+ , mpoly_monomial_overflows+ , mpoly_monomial_overflows_mp+ , mpoly_monomial_overflows1+ , mpoly_monomial_set+ , mpoly_monomial_swap+ , mpoly_monomial_mul_ui+ -- * Monomial comparison+ , mpoly_monomial_is_zero+ , mpoly_monomial_equal+ , mpoly_get_cmpmask+ , mpoly_monomial_lt+ , mpoly_monomial_gt+ , mpoly_monomial_cmp+ -- * Monomial divisibility+ , mpoly_monomial_divides+ , mpoly_monomial_divides_mp+ , mpoly_monomial_divides1+ , mpoly_monomial_divides_tight+ -- * Basic manipulation+ , mpoly_exp_bits_required_ui+ , mpoly_exp_bits_required_ffmpz+ , mpoly_exp_bits_required_pfmpz+ , mpoly_max_fields_ui_sp+ , mpoly_max_fields_fmpz+ , mpoly_max_degrees_tight+ , mpoly_monomial_exists+ , mpoly_search_monomials+ -- * Setting and getting monomials+ , mpoly_term_exp_fits_ui+ , mpoly_term_exp_fits_si+ , mpoly_get_monomial_ui+ , mpoly_get_monomial_ffmpz+ , mpoly_get_monomial_pfmpz+ , mpoly_set_monomial_ui+ , mpoly_set_monomial_ffmpz+ , mpoly_set_monomial_pfmpz+ -- * Packing and unpacking monomials+ , mpoly_pack_vec_ui+ , mpoly_pack_vec_fmpz+ , mpoly_unpack_vec_ui+ , mpoly_unpack_vec_fmpz+ , mpoly_repack_monomials+ , mpoly_pack_monomials_tight+ , mpoly_unpack_monomials_tight+ -- * Chunking+ , mpoly_main_variable_terms1+ -- * Chained heap functions+ , _mpoly_heap_insert+ , _mpoly_heap_insert1+ , _mpoly_heap_pop+ , _mpoly_heap_pop1+) where ++-- support functions for multivariate polynomials ------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, castPtr)+import Foreign.Storable++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz++#include <flint/flint.h>+#include <flint/mpoly.h>++-- mpoly_ctx_t -----------------------------------------------------------------++data MPolyCtx = MPolyCtx {-# UNPACK #-} !(ForeignPtr CMPolyCtx)+data CMPolyCtx+ +instance Storable CMPolyCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size mpoly_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment mpoly_ctx_t}+ peek = error "CMPolyCtx.peek is not defined."+ poke = error "CMPolyCtx.poke is not defined."++-- | Create a new `MPolyCtx` structure.+newMPolyCtx nvars ord = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ mpoly_ctx_init x (fromIntegral nvars) ord+ addForeignPtrFinalizer p_mpoly_ctx_clear x+ return $ MPolyCtx x++-- | Use a new `MPolyCtx` structure.+withMPolyCtx (MPolyCtx ctx) f = do+ withForeignPtr ctx $ \pctx -> (MPolyCtx ctx,) <$> f pctx+ +-- ordering_t ------------------------------------------------------------------++newtype COrdering = COrdering {_Ordering :: CInt} deriving Eq++instance Storable COrdering where+ {-# INLINE sizeOf #-}+ sizeOf _ = sizeOf (undefined :: CInt)+ {-# INLINE alignment #-}+ alignment _ = alignment (undefined :: CInt)+ peek ptr = do+ v <- peek (castPtr ptr) :: IO CInt+ return $ COrdering v+ poke = undefined++ord_lex = COrdering #const ORD_LEX+ord_deglex = COrdering #const ORD_DEGLEX+ord_degrevlex = COrdering #const ORD_DEGREVLEX++-- mpoly_heap_s ----------------------------------------------------------------++data MPolyHeap = MPolyHeap {-# UNPACK #-} !(ForeignPtr CMPolyHeap)+type CMPolyHeap = Ptr ()++data MPolyHeap1 = MPolyHeap1 {-# UNPACK #-} !(ForeignPtr CMPolyHeap1)+type CMPolyHeap1 = Ptr ()++--------------------------------------------------------------------------------++-- | /mpoly_ctx_init/ /ctx/ /nvars/ /ord/ +-- +-- Initialize a context for specified number of variables and ordering.+foreign import ccall "mpoly.h mpoly_ctx_init"+ mpoly_ctx_init :: Ptr CMPolyCtx -> CLong -> COrdering -> IO ()++-- | /mpoly_ctx_clear/ /mctx/ +-- +-- Clean up any space used by a context object.+foreign import ccall "mpoly.h mpoly_ctx_clear"+ mpoly_ctx_clear :: Ptr CMPolyCtx -> IO ()++foreign import ccall "mpoly.h &mpoly_ctx_clear"+ p_mpoly_ctx_clear :: FunPtr (tr CMPolyCtx -> IO ())++-- | /mpoly_ordering_randtest/ /state/ +-- +-- Return a random ordering. The possibilities are @ORD_LEX@, @ORD_DEGLEX@+-- and @ORD_DEGREVLEX@.+foreign import ccall "mpoly.h mpoly_ordering_randtest"+ mpoly_ordering_randtest :: Ptr CFRandState -> IO (COrdering)++-- | /mpoly_ctx_init_rand/ /mctx/ /state/ /max_nvars/ +-- +-- Initialize a context with a random choice for the ordering.+foreign import ccall "mpoly.h mpoly_ctx_init_rand"+ mpoly_ctx_init_rand :: Ptr CMPolyCtx -> Ptr CFRandState -> CLong -> IO ()++-- | /mpoly_ordering_isdeg/ /ord/ +-- +-- Return 1 if the given ordering is a degree ordering (deglex or+-- degrevlex).+foreign import ccall "mpoly.h mpoly_ordering_isdeg"+ mpoly_ordering_isdeg :: COrdering -> IO CInt++-- | /mpoly_ordering_isrev/ /ord/ +-- +-- Return 1 if the given ordering is a reverse ordering (currently only+-- degrevlex).+foreign import ccall "mpoly.h mpoly_ordering_isrev"+ mpoly_ordering_isrev :: COrdering -> IO CInt++-- | /mpoly_ordering_print/ /ord/ +-- +-- Print a string (either \"lex\", \"deglex\" or \"degrevlex\") to standard+-- output, corresponding to the given ordering.+foreign import ccall "mpoly.h mpoly_ordering_print"+ mpoly_ordering_print :: COrdering -> IO ()++-- Monomial arithmetic ---------------------------------------------------------++-- | /mpoly_monomial_add/ /exp_ptr/ /exp2/ /exp3/ /N/ +-- +-- Set @(exp_ptr, N)@ to the sum of the monomials @(exp2, N)@ and+-- @(exp3, N)@, assuming @bits \<= FLINT_BITS@+foreign import ccall "mpoly.h mpoly_monomial_add"+ mpoly_monomial_add :: Ptr CULong -> Ptr CULong -> Ptr CULong -> CLong -> IO ()++-- | /mpoly_monomial_add_mp/ /exp_ptr/ /exp2/ /exp3/ /N/ +-- +-- Set @(exp_ptr, N)@ to the sum of the monomials @(exp2, N)@ and+-- @(exp3, N)@.+foreign import ccall "mpoly.h mpoly_monomial_add_mp"+ mpoly_monomial_add_mp :: Ptr CULong -> Ptr CULong -> Ptr CULong -> CLong -> IO ()++-- | /mpoly_monomial_sub/ /exp_ptr/ /exp2/ /exp3/ /N/ +-- +-- Set @(exp_ptr, N)@ to the difference of the monomials @(exp2, N)@ and+-- @(exp3, N)@, assuming @bits \<= FLINT_BITS@+foreign import ccall "mpoly.h mpoly_monomial_sub"+ mpoly_monomial_sub :: Ptr CULong -> Ptr CULong -> Ptr CULong -> CLong -> IO ()++-- | /mpoly_monomial_sub_mp/ /exp_ptr/ /exp2/ /exp3/ /N/ +-- +-- Set @(exp_ptr, N)@ to the difference of the monomials @(exp2, N)@ and+-- @(exp3, N)@.+foreign import ccall "mpoly.h mpoly_monomial_sub_mp"+ mpoly_monomial_sub_mp :: Ptr CULong -> Ptr CULong -> Ptr CULong -> CLong -> IO ()++-- | /mpoly_monomial_overflows/ /exp2/ /N/ /mask/ +-- +-- Return true if any of the fields of the given monomial @(exp2, N)@ has+-- overflowed (or is negative). The @mask@ is a word with the high bit of+-- each field set to 1. In other words, the function returns 1 if any word+-- of @exp2@ has any of the nonzero bits in @mask@ set. Assumes that+-- @bits \<= FLINT_BITS@.+foreign import ccall "mpoly.h mpoly_monomial_overflows"+ mpoly_monomial_overflows :: Ptr CULong -> CLong -> CULong -> IO CInt++-- | /mpoly_monomial_overflows_mp/ /exp_ptr/ /N/ /bits/ +-- +-- Return true if any of the fields of the given monomial @(exp_ptr, N)@+-- has overflowed. Assumes that @bits >= FLINT_BITS@.+foreign import ccall "mpoly.h mpoly_monomial_overflows_mp"+ mpoly_monomial_overflows_mp :: Ptr CULong -> CLong -> CFBitCnt -> IO CInt++-- | /mpoly_monomial_overflows1/ /exp/ /mask/ +-- +-- As per @mpoly_monomial_overflows@ with @N = 1@.+foreign import ccall "mpoly.h mpoly_monomial_overflows1"+ mpoly_monomial_overflows1 :: CULong -> CULong -> IO CInt++-- | /mpoly_monomial_set/ /exp2/ /exp3/ /N/ +-- +-- Set the monomial @(exp2, N)@ to @(exp3, N)@.+foreign import ccall "mpoly.h mpoly_monomial_set"+ mpoly_monomial_set :: Ptr CULong -> Ptr CULong -> CLong -> IO ()++-- | /mpoly_monomial_swap/ /exp2/ /exp3/ /N/ +-- +-- Swap the words in @(exp2, N)@ and @(exp3, N)@.+foreign import ccall "mpoly.h mpoly_monomial_swap"+ mpoly_monomial_swap :: Ptr CULong -> Ptr CULong -> CLong -> IO ()++-- | /mpoly_monomial_mul_ui/ /exp2/ /exp3/ /N/ /c/ +-- +-- Set the words of @(exp2, N)@ to the words of @(exp3, N)@ multiplied by+-- @c@.+foreign import ccall "mpoly.h mpoly_monomial_mul_ui"+ mpoly_monomial_mul_ui :: Ptr CULong -> Ptr CULong -> CLong -> CULong -> IO ()++-- Monomial comparison ---------------------------------------------------------++-- | /mpoly_monomial_is_zero/ /exp/ /N/ +-- +-- Return 1 if @(exp, N)@ is zero.+foreign import ccall "mpoly.h mpoly_monomial_is_zero"+ mpoly_monomial_is_zero :: Ptr CULong -> CLong -> IO CInt++-- | /mpoly_monomial_equal/ /exp2/ /exp3/ /N/ +-- +-- Return 1 if the monomials @(exp2, N)@ and @(exp3, N)@ are equal.+foreign import ccall "mpoly.h mpoly_monomial_equal"+ mpoly_monomial_equal :: Ptr CULong -> Ptr CULong -> CLong -> IO CInt++-- | /mpoly_get_cmpmask/ /cmpmask/ /N/ /bits/ /mctx/ +-- +-- Get the mask @(cmpmask, N)@ for comparisons. @bits@ should be set to the+-- number of bits in the exponents to be compared. Any function that+-- compares monomials should use this comparison mask.+foreign import ccall "mpoly.h mpoly_get_cmpmask"+ mpoly_get_cmpmask :: Ptr CULong -> CLong -> CLong -> Ptr CMPolyCtx -> IO ()++-- | /mpoly_monomial_lt/ /exp2/ /exp3/ /N/ /cmpmask/ +-- +-- Return 1 if @(exp2, N)@ is less than @(exp3, N)@.+foreign import ccall "mpoly.h mpoly_monomial_lt"+ mpoly_monomial_lt :: Ptr CULong -> Ptr CULong -> CLong -> Ptr CULong -> IO CInt++-- | /mpoly_monomial_gt/ /exp2/ /exp3/ /N/ /cmpmask/ +-- +-- Return 1 if @(exp2, N)@ is greater than @(exp3, N)@.+foreign import ccall "mpoly.h mpoly_monomial_gt"+ mpoly_monomial_gt :: Ptr CULong -> Ptr CULong -> CLong -> Ptr CULong -> IO CInt++-- | /mpoly_monomial_cmp/ /exp2/ /exp3/ /N/ /cmpmask/ +-- +-- Return \(1\) if @(exp2, N)@ is greater than, \(0\) if it is equal to and+-- \(-1\) if it is less than @(exp3, N)@.+foreign import ccall "mpoly.h mpoly_monomial_cmp"+ mpoly_monomial_cmp :: Ptr CULong -> Ptr CULong -> CLong -> Ptr CULong -> IO CInt++-- Monomial divisibility -------------------------------------------------------++-- | /mpoly_monomial_divides/ /exp_ptr/ /exp2/ /exp3/ /N/ /mask/ +-- +-- Return 1 if the monomial @(exp3, N)@ divides @(exp2, N)@. If so set+-- @(exp_ptr, N)@ to the quotient monomial. The @mask@ is a word with the+-- high bit of each bit field set to 1. Assumes that @bits \<= FLINT_BITS@.+foreign import ccall "mpoly.h mpoly_monomial_divides"+ mpoly_monomial_divides :: Ptr CULong -> Ptr CULong -> Ptr CULong -> CLong -> CULong -> IO CInt++-- | /mpoly_monomial_divides_mp/ /exp_ptr/ /exp2/ /exp3/ /N/ /bits/ +-- +-- Return 1 if the monomial @(exp3, N)@ divides @(exp2, N)@. If so set+-- @(exp_ptr, N)@ to the quotient monomial. Assumes that+-- @bits >= FLINT_BITS@.+foreign import ccall "mpoly.h mpoly_monomial_divides_mp"+ mpoly_monomial_divides_mp :: Ptr CULong -> Ptr CULong -> Ptr CULong -> CLong -> CFBitCnt -> IO CInt++-- | /mpoly_monomial_divides1/ /exp_ptr/ /exp2/ /exp3/ /mask/ +-- +-- As per @mpoly_monomial_divides@ with @N = 1@.+foreign import ccall "mpoly.h mpoly_monomial_divides1"+ mpoly_monomial_divides1 :: Ptr CULong -> CULong -> CULong -> CULong -> IO CInt++-- | /mpoly_monomial_divides_tight/ /e1/ /e2/ /prods/ /num/ +-- +-- Return 1 if the monomial @e2@ divides the monomial @e1@, where the+-- monomials are stored using factorial representation. The array+-- @(prods, num)@ should consist of \(1\), \(b_1, b_1\times b_2, \ldots\),+-- where the \(b_i\) are the bases of the factorial number representation.+foreign import ccall "mpoly.h mpoly_monomial_divides_tight"+ mpoly_monomial_divides_tight :: CLong -> CLong -> Ptr CLong -> CLong -> IO CInt++-- Basic manipulation ----------------------------------------------------------++-- | /mpoly_exp_bits_required_ui/ /user_exp/ /mctx/ +-- +-- Returns the number of bits required to store @user_exp@ in packed+-- format. The returned number of bits includes space for a zeroed signed+-- bit.+foreign import ccall "mpoly.h mpoly_exp_bits_required_ui"+ mpoly_exp_bits_required_ui :: Ptr CULong -> Ptr CMPolyCtx -> IO CFBitCnt++-- | /mpoly_exp_bits_required_ffmpz/ /user_exp/ /mctx/ +-- +-- Returns the number of bits required to store @user_exp@ in packed+-- format. The returned number of bits includes space for a zeroed signed+-- bit.+foreign import ccall "mpoly.h mpoly_exp_bits_required_ffmpz"+ mpoly_exp_bits_required_ffmpz :: Ptr CFmpz -> Ptr CMPolyCtx -> IO CFBitCnt++-- | /mpoly_exp_bits_required_pfmpz/ /user_exp/ /mctx/ +-- +-- Returns the number of bits required to store @user_exp@ in packed+-- format. The returned number of bits includes space for a zeroed signed+-- bit.+foreign import ccall "mpoly.h mpoly_exp_bits_required_pfmpz"+ mpoly_exp_bits_required_pfmpz :: Ptr (Ptr CFmpz) -> Ptr CMPolyCtx -> IO CFBitCnt++-- | /mpoly_max_fields_ui_sp/ /max_fields/ /poly_exps/ /len/ /bits/ /mctx/ +-- +-- Compute the field-wise maximum of packed exponents from @poly_exps@ of+-- length @len@ and unpack the result into @max_fields@. The maximums are+-- assumed to fit a ulong.+foreign import ccall "mpoly.h mpoly_max_fields_ui_sp"+ mpoly_max_fields_ui_sp :: Ptr CULong -> Ptr CULong -> CLong -> CLong -> Ptr CMPolyCtx -> IO ()++-- | /mpoly_max_fields_fmpz/ /max_fields/ /poly_exps/ /len/ /bits/ /mctx/ +-- +-- Compute the field-wise maximum of packed exponents from @poly_exps@ of+-- length @len@ and unpack the result into @max_fields@.+foreign import ccall "mpoly.h mpoly_max_fields_fmpz"+ mpoly_max_fields_fmpz :: Ptr CFmpz -> Ptr CULong -> CLong -> CLong -> Ptr CMPolyCtx -> IO ()++-- | /mpoly_max_degrees_tight/ /max_exp/ /exps/ /len/ /prods/ /num/ +-- +-- Return an array of @num@ integers corresponding to the maximum degrees+-- of the exponents in the array of exponent vectors @(exps, len)@,+-- assuming that the exponent are packed in a factorial representation. The+-- array @(prods, num)@ should consist of \(1\), \(b_1\),+-- \(b_1\times b_2, \ldots\), where the \(b_i\) are the bases of the+-- factorial number representation. The results are stored in the array+-- @max_exp@, with the entry corresponding to the most significant base of+-- the factorial representation first in the array.+foreign import ccall "mpoly.h mpoly_max_degrees_tight"+ mpoly_max_degrees_tight :: Ptr CLong -> Ptr CULong -> CLong -> Ptr CLong -> CLong -> IO ()++-- | /mpoly_monomial_exists/ /index/ /poly_exps/ /exp/ /len/ /N/ /cmpmask/ +-- +-- Returns true if the given exponent vector @exp@ exists in the array of+-- exponent vectors @(poly_exps, len)@, otherwise, returns false. If the+-- exponent vector is found, its index into the array of exponent vectors+-- is returned. Otherwise, @index@ is set to the index where this exponent+-- could be inserted to preserve the ordering. The index can be in the+-- range @[0, len]@.+foreign import ccall "mpoly.h mpoly_monomial_exists"+ mpoly_monomial_exists :: Ptr CLong -> Ptr CULong -> Ptr CULong -> CLong -> CLong -> Ptr CULong -> IO CInt++-- | /mpoly_search_monomials/ /e_ind/ /e/ /e_score/ /t1/ /t2/ /t3/ /lower/ /upper/ /a/ /a_len/ /b/ /b_len/ /N/ /cmpmask/ +-- +-- Given packed exponent vectors @a@ and @b@, compute a packed exponent @e@+-- such that the number of monomials in the cross product @a@ X @b@ that+-- are less than or equal to @e@ is between @lower@ and @upper@. This+-- number is stored in @e_store@. If no such monomial exists, one is chosen+-- so that the number of monomials is as close as possible. This function+-- assumes that @1@ is the smallest monomial and needs three arrays @t1@,+-- @t2@, and @t3@ of the size as @a@ for workspace. The parameter @e_ind@+-- is set to one of @t1@, @t2@, and @t3@ and gives the locations of the+-- monomials in @a@ X @b@.+foreign import ccall "mpoly.h mpoly_search_monomials"+ mpoly_search_monomials :: Ptr (Ptr CLong) -> Ptr CULong -> Ptr CLong -> Ptr CLong -> Ptr CLong -> Ptr CLong -> CLong -> CLong -> Ptr CULong -> CLong -> Ptr CULong -> CLong -> CLong -> Ptr CULong -> IO ()++-- Setting and getting monomials -----------------------------------------------++-- | /mpoly_term_exp_fits_ui/ /exps/ /bits/ /n/ /mctx/ +-- +-- Return whether every entry of the exponent vector of index \(n\) in+-- @exps@ fits into a @ulong@.+foreign import ccall "mpoly.h mpoly_term_exp_fits_ui"+ mpoly_term_exp_fits_ui :: Ptr CULong -> CLong -> CLong -> Ptr CMPolyCtx -> IO CInt++-- | /mpoly_term_exp_fits_si/ /exps/ /bits/ /n/ /mctx/ +-- +-- Return whether every entry of the exponent vector of index \(n\) in+-- @exps@ fits into a @slong@.+foreign import ccall "mpoly.h mpoly_term_exp_fits_si"+ mpoly_term_exp_fits_si :: Ptr CULong -> CLong -> CLong -> Ptr CMPolyCtx -> IO CInt++-- | /mpoly_get_monomial_ui/ /exps/ /poly_exps/ /bits/ /mctx/ +-- +-- Convert the packed exponent @poly_exps@ of bit count @bits@ to a+-- monomial from the user\'s perspective. The exponents are assumed to fit+-- a ulong.+foreign import ccall "mpoly.h mpoly_get_monomial_ui"+ mpoly_get_monomial_ui :: Ptr CULong -> Ptr CULong -> CLong -> Ptr CMPolyCtx -> IO ()++-- | /mpoly_get_monomial_ffmpz/ /exps/ /poly_exps/ /bits/ /mctx/ +-- +-- Convert the packed exponent @poly_exps@ of bit count @bits@ to a+-- monomial from the user\'s perspective.+foreign import ccall "mpoly.h mpoly_get_monomial_ffmpz"+ mpoly_get_monomial_ffmpz :: Ptr CFmpz -> Ptr CULong -> CFBitCnt -> Ptr CMPolyCtx -> IO ()++-- | /mpoly_get_monomial_pfmpz/ /exps/ /poly_exps/ /bits/ /mctx/ +-- +-- Convert the packed exponent @poly_exps@ of bit count @bits@ to a+-- monomial from the user\'s perspective.+foreign import ccall "mpoly.h mpoly_get_monomial_pfmpz"+ mpoly_get_monomial_pfmpz :: Ptr (Ptr CFmpz) -> Ptr CULong -> CFBitCnt -> Ptr CMPolyCtx -> IO ()++-- | /mpoly_set_monomial_ui/ /exp1/ /exp2/ /bits/ /mctx/ +-- +-- Convert the user monomial @exp2@ to packed format using @bits@.+foreign import ccall "mpoly.h mpoly_set_monomial_ui"+ mpoly_set_monomial_ui :: Ptr CULong -> Ptr CULong -> CLong -> Ptr CMPolyCtx -> IO ()++-- | /mpoly_set_monomial_ffmpz/ /exp1/ /exp2/ /bits/ /mctx/ +-- +-- Convert the user monomial @exp2@ to packed format using @bits@.+foreign import ccall "mpoly.h mpoly_set_monomial_ffmpz"+ mpoly_set_monomial_ffmpz :: Ptr CULong -> Ptr CFmpz -> CFBitCnt -> Ptr CMPolyCtx -> IO ()++-- | /mpoly_set_monomial_pfmpz/ /exp1/ /exp2/ /bits/ /mctx/ +-- +-- Convert the user monomial @exp2@ to packed format using @bits@.+foreign import ccall "mpoly.h mpoly_set_monomial_pfmpz"+ mpoly_set_monomial_pfmpz :: Ptr CULong -> Ptr (Ptr CFmpz) -> CFBitCnt -> Ptr CMPolyCtx -> IO ()++-- Packing and unpacking monomials ---------------------------------------------++-- | /mpoly_pack_vec_ui/ /exp1/ /exp2/ /bits/ /nfields/ /len/ +-- +-- Packs a vector @exp2@ into {exp1} using a bit count of @bits@. No+-- checking is done to ensure that the vector actually fits into @bits@+-- bits. The number of fields in each vector is @nfields@ and the total+-- number of vectors to unpack is @len@.+foreign import ccall "mpoly.h mpoly_pack_vec_ui"+ mpoly_pack_vec_ui :: Ptr CULong -> Ptr CULong -> CLong -> CLong -> CLong -> IO ()++-- | /mpoly_pack_vec_fmpz/ /exp1/ /exp2/ /bits/ /nfields/ /len/ +-- +-- Packs a vector @exp2@ into {exp1} using a bit count of @bits@. No+-- checking is done to ensure that the vector actually fits into @bits@+-- bits. The number of fields in each vector is @nfields@ and the total+-- number of vectors to unpack is @len@.+foreign import ccall "mpoly.h mpoly_pack_vec_fmpz"+ mpoly_pack_vec_fmpz :: Ptr CULong -> Ptr CFmpz -> CFBitCnt -> CLong -> CLong -> IO ()++-- | /mpoly_unpack_vec_ui/ /exp1/ /exp2/ /bits/ /nfields/ /len/ +-- +-- Unpacks vector @exp2@ of bit count @bits@ into @exp1@. The number of+-- fields in each vector is @nfields@ and the total number of vectors to+-- unpack is @len@.+foreign import ccall "mpoly.h mpoly_unpack_vec_ui"+ mpoly_unpack_vec_ui :: Ptr CULong -> Ptr CULong -> CLong -> CLong -> CLong -> IO ()++-- | /mpoly_unpack_vec_fmpz/ /exp1/ /exp2/ /bits/ /nfields/ /len/ +-- +-- Unpacks vector @exp2@ of bit count @bits@ into @exp1@. The number of+-- fields in each vector is @nfields@ and the total number of vectors to+-- unpack is @len@.+foreign import ccall "mpoly.h mpoly_unpack_vec_fmpz"+ mpoly_unpack_vec_fmpz :: Ptr CFmpz -> Ptr CULong -> CFBitCnt -> CLong -> CLong -> IO ()++-- | /mpoly_repack_monomials/ /exps1/ /bits1/ /exps2/ /bits2/ /len/ /mctx/ +-- +-- Convert an array of length @len@ of exponents @exps2@ packed using bits+-- @bits2@ into an array @exps1@ using bits @bits1@. No checking is done to+-- ensure that the result fits into bits @bits1@.+foreign import ccall "mpoly.h mpoly_repack_monomials"+ mpoly_repack_monomials :: Ptr CULong -> CLong -> Ptr CULong -> CLong -> CLong -> Ptr CMPolyCtx -> IO ()++-- | /mpoly_pack_monomials_tight/ /exp1/ /exp2/ /len/ /mults/ /num/ /extra/ /bits/ +-- +-- Given an array of possibly packed exponent vectors @exp2@ of length+-- @len@, where each field of each exponent vector is packed into the given+-- number of bits, return the corresponding array of monomial vectors+-- packed using a factorial numbering scheme. The \"bases\" for the+-- factorial numbering scheme are given as an array of integers @mults@,+-- the first entry of which corresponds to the field of least significance+-- in each input exponent vector. Obviously the maximum exponent to be+-- packed must be less than the corresponding base in @mults@.+-- +-- The number of multipliers is given by @num@. The code only considers+-- least significant @num@ fields of each exponent vectors and ignores the+-- rest. The number of ignored fields should be passed in @extras@.+foreign import ccall "mpoly.h mpoly_pack_monomials_tight"+ mpoly_pack_monomials_tight :: Ptr CULong -> Ptr CULong -> CLong -> Ptr CLong -> CLong -> CLong -> CLong -> IO ()++-- | /mpoly_unpack_monomials_tight/ /e1/ /e2/ /len/ /mults/ /num/ /extra/ /bits/ +-- +-- Given an array of exponent vectors @e2@ of length @len@ packed using a+-- factorial numbering scheme, unpack the monomials into an array @e1@ of+-- exponent vectors in standard packed format, where each field has the+-- given number of bits. The \"bases\" for the factorial numbering scheme+-- are given as an array of integers @mults@, the first entry of which+-- corresponds to the field of least significance in each exponent vector.+-- +-- The number of multipliers is given by @num@. The code only considers+-- least significant @num@ fields of each exponent vectors and ignores the+-- rest. The number of ignored fields should be passed in @extras@.+foreign import ccall "mpoly.h mpoly_unpack_monomials_tight"+ mpoly_unpack_monomials_tight :: Ptr CULong -> Ptr CULong -> CLong -> Ptr CLong -> CLong -> CLong -> CLong -> IO ()++-- Chunking --------------------------------------------------------------------++-- | /mpoly_main_variable_terms1/ /i1/ /n1/ /exp1/ /l1/ /len1/ /k/ /num/ /bits/ +-- +-- Given an array of exponent vectors @(exp1, len1)@, each exponent vector+-- taking one word of space, with each exponent being packed into the given+-- number of bits, compute @l1@ starting offsets @i1@ and lengths @n1@+-- (which may be zero) to break the exponents into chunks. Each chunk+-- consists of exponents have the same degree in the main variable. The+-- index of the main variable is given by \(k\). The variables are indexed+-- from the variable of least significance, starting from \(0\). The value+-- @l1@ should be the degree in the main variable, plus one.+foreign import ccall "mpoly.h mpoly_main_variable_terms1"+ mpoly_main_variable_terms1 :: Ptr CLong -> Ptr CLong -> Ptr CULong -> CLong -> CLong -> CLong -> CLong -> CLong -> IO ()++-- Chained heap functions ------------------------------------------------------++-- | /_mpoly_heap_insert/ /heap/ /exp/ /x/ /heap_len/ /N/ /cmpmask/ +-- +-- Given a heap, insert a new node \(x\) corresponding to the given+-- exponent into the heap. Heap elements are ordered by the exponent+-- @(exp, N)@, with the largest element at the head of the heap. A pointer+-- to the current heap length must be passed in via @heap_len@. This will+-- be updated by the function. Note that the index 0 position in the heap+-- is not used, so the length is always one greater than the number of+-- elements.+foreign import ccall "mpoly.h _mpoly_heap_insert"+ _mpoly_heap_insert :: Ptr CMPolyHeap -> Ptr CULong -> Ptr () -> Ptr CLong -> CLong -> Ptr CULong -> IO CInt++-- | /_mpoly_heap_insert1/ /heap/ /exp/ /x/ /heap_len/ /maskhi/ +-- +-- As per @_mpoly_heap_insert@ except that @N = 1@, and+-- @maskhi = cmpmask[0]@.+foreign import ccall "mpoly.h _mpoly_heap_insert1"+ _mpoly_heap_insert1 :: Ptr CMPolyHeap1 -> CULong -> Ptr () -> Ptr CLong -> CULong -> IO ()++-- | /_mpoly_heap_pop/ /heap/ /heap_len/ /N/ /maskhi/ /masklo/ +-- +-- Pop the head of the heap. It is cast to a @void *@. A pointer to the+-- current heap length must be passed in via @heap_len@. This will be+-- updated by the function. Note that the index 0 position in the heap is+-- not used, so the length is always one greater than the number of+-- elements. The @maskhi@ and @masklo@ values are zero except for degrevlex+-- ordering, where they are as per the monomial comparison operations+-- above.+foreign import ccall "mpoly.h _mpoly_heap_pop"+ _mpoly_heap_pop :: Ptr CMPolyHeap -> Ptr CLong -> CLong -> CULong -> CULong -> IO ()++-- | /_mpoly_heap_pop1/ /heap/ /heap_len/ /maskhi/ +-- +-- As per @_mpoly_heap_pop1@ except that @N = 1@, and+-- @maskhi = cmpmask[0]@.+foreign import ccall "mpoly.h _mpoly_heap_pop1"+ _mpoly_heap_pop1 :: Ptr CMPolyHeap1 -> Ptr CLong -> CULong -> IO ()+
+ src/Data/Number/Flint/NF.hs view
@@ -0,0 +1,13 @@+{-|+module : Data.Number.Flint.NF+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.NF (+ module Data.Number.Flint.NF.FFI,+) where++import Data.Number.Flint.NF.FFI+
+ src/Data/Number/Flint/NF/Elem.hs view
@@ -0,0 +1,6 @@+module Data.Number.Flint.NF.Elem (+ module Data.Number.Flint.NF.Elem.FFI,+) where++import Data.Number.Flint.NF.Elem.FFI+
+ src/Data/Number/Flint/NF/Elem/FFI.hsc view
@@ -0,0 +1,616 @@+{-|+module : Data.Number.Flint.NF.Elem.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NF.Elem.FFI (+ -- * __nf_elem.h__ -- number field elements+ NFElem (..)+ , CNFElem (..)+ , newNFElem+ , withNFElem+ , withNewNFElem+ -- * Initialisation+ , nf_elem_init+ , nf_elem_clear+ , nf_elem_randtest+ , nf_elem_canonicalise+ , _nf_elem_reduce+ , nf_elem_reduce+ , _nf_elem_invertible_check+ -- * Conversion+ , nf_elem_set_fmpz_mat_row+ , nf_elem_get_fmpz_mat_row+ , nf_elem_set_fmpq_poly+ , nf_elem_get_fmpq_poly+ , nf_elem_get_nmod_poly_den+ , nf_elem_get_nmod_poly+ , nf_elem_get_fmpz_mod_poly_den+ , nf_elem_get_fmpz_mod_poly+ -- * Basic manipulation+ , nf_elem_set_den+ , nf_elem_get_den+ , _nf_elem_set_coeff_num_fmpz+ -- * Comparison+ , _nf_elem_equal+ , nf_elem_equal+ , nf_elem_is_zero+ , nf_elem_is_one+ -- * I\/O+ , nf_elem_get_str_pretty+ , nf_elem_print_pretty+ -- * Arithmetic+ , nf_elem_zero+ , nf_elem_one+ , nf_elem_set+ , nf_elem_neg+ , nf_elem_swap+ , nf_elem_mul_gen+ , _nf_elem_add+ , nf_elem_add+ , _nf_elem_sub+ , nf_elem_sub+ , _nf_elem_mul+ , _nf_elem_mul_red+ , nf_elem_mul+ , nf_elem_mul_red+ , _nf_elem_inv+ , nf_elem_inv+ , _nf_elem_div+ , nf_elem_div+ , _nf_elem_pow+ , nf_elem_pow+ , _nf_elem_norm+ , nf_elem_norm+ , nf_elem_norm_div+ , _nf_elem_norm_div+ , _nf_elem_trace+ , nf_elem_trace+ -- * Representation matrix+ , nf_elem_rep_mat+ , nf_elem_rep_mat_fmpz_mat_den+ -- * Modular reduction+ , nf_elem_mod_fmpz_den+ , nf_elem_smod_fmpz_den+ , nf_elem_mod_fmpz+ , nf_elem_smod_fmpz+ , nf_elem_coprime_den+ , nf_elem_coprime_den_signed+) where ++-- Number field elements -------------------------------------------------------++import Foreign.C.Types+import Foreign.C.String+import Foreign.ForeignPtr+import Foreign.Ptr+import Foreign.Storable+import Foreign.Marshal.Alloc (free)++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mod.Poly+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fmpq.Poly+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpq.Mat+import Data.Number.Flint.NMod.Types+import Data.Number.Flint.NF++#include <flint/nf_elem.h>++-- nf_elem_t -------------------------------------------------------------------++data NFElem = NFElem !(ForeignPtr CNFElem)+type CNFElem = CFlint NFElem++instance Storable CNFElem where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nf_elem_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nf_elem_t}+ peek = error "CNFElem.peek is not defined."+ poke = error "CNFElem.poke is not defined."++--------------------------------------------------------------------------------++newNFElem nf@(NF pnf) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withNF nf $ \nf -> do+ nf_elem_init x nf+ addForeignPtrFinalizerEnv p_nf_elem_clear x pnf+ return $ NFElem x++-- | Use number-field element.+{-# INLINE withNFElem #-}+withNFElem (NFElem p) f = do+ withForeignPtr p $ \fp -> (NFElem p,) <$> f fp++withNewNFElem nf f = do+ x <- newNFElem nf+ withNFElem x f+ +--------------------------------------------------------------------------------++-- | /nf_elem_init/ /a/ /nf/ +-- +-- Initialise a number field element to belong to the given number field+-- code{nf}. The element is set to zero.+foreign import ccall "nf_elem.h nf_elem_init"+ nf_elem_init :: Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_clear/ /a/ /nf/ +-- +-- Clear resources allocated by the given number field element in the given+-- number field.+foreign import ccall "nf_elem.h nf_elem_clear"+ nf_elem_clear :: Ptr CNFElem -> Ptr CNF -> IO ()++foreign import ccall "nf_elem.h &nf_elem_clear"+ p_nf_elem_clear :: FunPtr (Ptr CNFElem -> Ptr CNF -> IO ())++-- | /nf_elem_randtest/ /a/ /state/ /bits/ /nf/ +-- +-- Generate a random number field element \(a\) in the number field+-- code{nf} whose coefficients have up to the given number of bits.+foreign import ccall "nf_elem.h nf_elem_randtest"+ nf_elem_randtest :: Ptr CNFElem -> Ptr CFRandState -> CMpBitCnt -> Ptr CNF -> IO ()++-- | /nf_elem_canonicalise/ /a/ /nf/ +-- +-- Canonicalise a number field element, i.e. reduce numerator and+-- denominator to lowest terms. If the numerator is \(0\), set the+-- denominator to \(1\).+foreign import ccall "nf_elem.h nf_elem_canonicalise"+ nf_elem_canonicalise :: Ptr CNFElem -> Ptr CNF -> IO ()++-- | /_nf_elem_reduce/ /a/ /nf/ +-- +-- Reduce a number field element modulo the defining polynomial. This is+-- used with functions such as code{nf_elem_mul_red} which allow reduction+-- to be delayed. Does not canonicalise.+foreign import ccall "nf_elem.h _nf_elem_reduce"+ _nf_elem_reduce :: Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_reduce/ /a/ /nf/ +-- +-- Reduce a number field element modulo the defining polynomial. This is+-- used with functions such as code{nf_elem_mul_red} which allow reduction+-- to be delayed.+foreign import ccall "nf_elem.h nf_elem_reduce"+ nf_elem_reduce :: Ptr CNFElem -> Ptr CNF -> IO ()++-- | /_nf_elem_invertible_check/ /a/ /nf/ +-- +-- Whilst the defining polynomial for a number field should by definition+-- be irreducible, it is not enforced. Thus in test code, it is convenient+-- to be able to check that a given number field element is invertible+-- modulo the defining polynomial of the number field. This function does+-- precisely this.+-- +-- If \(a\) is invertible modulo the defining polynomial of code{nf} the+-- value \(1\) is returned, otherwise \(0\) is returned.+-- +-- The function is only intended to be used in test code.+foreign import ccall "nf_elem.h _nf_elem_invertible_check"+ _nf_elem_invertible_check :: Ptr CNFElem -> Ptr CNF -> IO CInt++-- Conversion ------------------------------------------------------------------++-- | /nf_elem_set_fmpz_mat_row/ /b/ /M/ /i/ /den/ /nf/ +-- +-- Set \(b\) to the element specified by row \(i\) of the matrix \(M\) and+-- with the given denominator \(d\). Column \(0\) of the matrix corresponds+-- to the constant coefficient of the number field element.+foreign import ccall "nf_elem.h nf_elem_set_fmpz_mat_row"+ nf_elem_set_fmpz_mat_row :: Ptr CNFElem -> Ptr CFmpzMat -> CInt -> Ptr CFmpz -> Ptr CNF -> IO ()++-- | /nf_elem_get_fmpz_mat_row/ /M/ /i/ /den/ /b/ /nf/ +-- +-- Set the row \(i\) of the matrix \(M\) to the coefficients of the+-- numerator of the element \(b\) and \(d\) to the denominator of \(b\).+-- Column \(0\) of the matrix corresponds to the constant coefficient of+-- the number field element.+foreign import ccall "nf_elem.h nf_elem_get_fmpz_mat_row"+ nf_elem_get_fmpz_mat_row :: Ptr CFmpzMat -> CInt -> Ptr CFmpz -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_set_fmpq_poly/ /a/ /pol/ /nf/ +-- +-- Set \(a\) to the element corresponding to the polynomial code{pol}.+foreign import ccall "nf_elem.h nf_elem_set_fmpq_poly"+ nf_elem_set_fmpq_poly :: Ptr CNFElem -> Ptr CFmpqPoly -> Ptr CNF -> IO ()++-- | /nf_elem_get_fmpq_poly/ /pol/ /a/ /nf/ +-- +-- Set code{pol} to a polynomial corresponding to \(a\), reduced modulo the+-- defining polynomial of code{nf}.+foreign import ccall "nf_elem.h nf_elem_get_fmpq_poly"+ nf_elem_get_fmpq_poly :: Ptr CFmpqPoly -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_get_nmod_poly_den/ /pol/ /a/ /nf/ /den/ +-- +-- Set code{pol} to the reduction of the polynomial corresponding to the+-- numerator of \(a\). If code{den == 1}, the result is multiplied by the+-- inverse of the denominator of \(a\). In this case it is assumed that the+-- reduction of the denominator of \(a\) is invertible.+foreign import ccall "nf_elem.h nf_elem_get_nmod_poly_den"+ nf_elem_get_nmod_poly_den :: Ptr CNModPoly -> Ptr CNFElem -> Ptr CNF -> CInt -> IO ()++-- | /nf_elem_get_nmod_poly/ /pol/ /a/ /nf/ +-- +-- Set code{pol} to the reduction of the polynomial corresponding to the+-- numerator of \(a\). The result is multiplied by the inverse of the+-- denominator of \(a\). It is assumed that the reduction of the+-- denominator of \(a\) is invertible.+foreign import ccall "nf_elem.h nf_elem_get_nmod_poly"+ nf_elem_get_nmod_poly :: Ptr CNModPoly -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_get_fmpz_mod_poly_den/ /pol/ /a/ /nf/ /den/ +-- +-- Set code{pol} to the reduction of the polynomial corresponding to the+-- numerator of \(a\). If code{den == 1}, the result is multiplied by the+-- inverse of the denominator of \(a\). In this case it is assumed that the+-- reduction of the denominator of \(a\) is invertible.+foreign import ccall "nf_elem.h nf_elem_get_fmpz_mod_poly_den"+ nf_elem_get_fmpz_mod_poly_den :: Ptr CFmpzModPoly -> Ptr CNFElem -> Ptr CNF -> CInt -> IO ()++-- | /nf_elem_get_fmpz_mod_poly/ /pol/ /a/ /nf/ +-- +-- Set code{pol} to the reduction of the polynomial corresponding to the+-- numerator of \(a\). The result is multiplied by the inverse of the+-- denominator of \(a\). It is assumed that the reduction of the+-- denominator of \(a\) is invertible.+foreign import ccall "nf_elem.h nf_elem_get_fmpz_mod_poly"+ nf_elem_get_fmpz_mod_poly :: Ptr CFmpzModPoly -> Ptr CNFElem -> Ptr CNF -> IO ()++-- Basic manipulation ----------------------------------------------------------++-- | /nf_elem_set_den/ /b/ /d/ /nf/ +-- +-- Set the denominator of the code{nf_elem_t b} to the given integer \(d\).+-- Assumes \(d > 0\).+foreign import ccall "nf_elem.h nf_elem_set_den"+ nf_elem_set_den :: Ptr CNFElem -> Ptr CFmpz -> Ptr CNF -> IO ()++-- | /nf_elem_get_den/ /d/ /b/ /nf/ +-- +-- Set \(d\) to the denominator of the code{nf_elem_t b}.+foreign import ccall "nf_elem.h nf_elem_get_den"+ nf_elem_get_den :: Ptr CFmpz -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /_nf_elem_set_coeff_num_fmpz/ /a/ /i/ /d/ /nf/ +-- +-- Set the \(i`th coefficient of the denominator of :math:`a\) to the given+-- integer \(d\).+foreign import ccall "nf_elem.h _nf_elem_set_coeff_num_fmpz"+ _nf_elem_set_coeff_num_fmpz :: Ptr CNFElem -> CLong -> Ptr CFmpz -> Ptr CNF -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /_nf_elem_equal/ /a/ /b/ /nf/ +-- +-- Return \(1\) if the given number field elements are equal in the given+-- number field code{nf}. This function does emph{not} assume \(a\) and+-- \(b\) are canonicalised.+foreign import ccall "nf_elem.h _nf_elem_equal"+ _nf_elem_equal :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO CInt++-- | /nf_elem_equal/ /a/ /b/ /nf/ +-- +-- Return \(1\) if the given number field elements are equal in the given+-- number field code{nf}. This function assumes \(a\) and \(b\) emph{are}+-- canonicalised.+foreign import ccall "nf_elem.h nf_elem_equal"+ nf_elem_equal :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO CInt++-- | /nf_elem_is_zero/ /a/ /nf/ +-- +-- Return \(1\) if the given number field element is equal to zero,+-- otherwise return \(0\).+foreign import ccall "nf_elem.h nf_elem_is_zero"+ nf_elem_is_zero :: Ptr CNFElem -> Ptr CNF -> IO CInt++-- | /nf_elem_is_one/ /a/ /nf/ +-- +-- Return \(1\) if the given number field element is equal to one,+-- otherwise return \(0\).+foreign import ccall "nf_elem.h nf_elem_is_one"+ nf_elem_is_one :: Ptr CNFElem -> Ptr CNF -> IO CInt++-- I\/O ------------------------------------------------------------------------++foreign import ccall "nf_elem.h nf_elem_get_str_pretty"+ nf_elem_get_str_pretty :: Ptr CNFElem -> CString -> Ptr CNF -> IO CString++-- | /nf_elem_print_pretty/ /a/ /nf/ /var/ +-- +-- Print the given number field element to code{stdout} using the+-- null-terminated string code{var} not equal to code{\"0\"} as the name of+-- the primitive element.+-- foreign import ccall "nf_elem.h nf_elem_print_pretty"+nf_elem_print_pretty :: Ptr CNFElem -> Ptr CNF -> CString -> IO ()+nf_elem_print_pretty x nf var = do+ cs <- nf_elem_get_str_pretty x var nf+ s <- peekCString cs+ free cs+ putStr s+ +-- Arithmetic ------------------------------------------------------------------++-- | /nf_elem_zero/ /a/ /nf/ +-- +-- Set the given number field element to zero.+foreign import ccall "nf_elem.h nf_elem_zero"+ nf_elem_zero :: Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_one/ /a/ /nf/ +-- +-- Set the given number field element to one.+foreign import ccall "nf_elem.h nf_elem_one"+ nf_elem_one :: Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_set/ /a/ /b/ /nf/ +-- +-- Set the number field element \(a\) to equal the number field element+-- \(b\), i.e. set \(a = b\).+foreign import ccall "nf_elem.h nf_elem_set"+ nf_elem_set :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_neg/ /a/ /b/ /nf/ +-- +-- Set the number field element \(a\) to minus the number field element+-- \(b\), i.e. set \(a = -b\).+foreign import ccall "nf_elem.h nf_elem_neg"+ nf_elem_neg :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_swap/ /a/ /b/ /nf/ +-- +-- Efficiently swap the two number field elements \(a\) and \(b\).+foreign import ccall "nf_elem.h nf_elem_swap"+ nf_elem_swap :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_mul_gen/ /a/ /b/ /nf/ +-- +-- Multiply the element \(b\) with the generator of the number field.+foreign import ccall "nf_elem.h nf_elem_mul_gen"+ nf_elem_mul_gen :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /_nf_elem_add/ /r/ /a/ /b/ /nf/ +-- +-- Add two elements of a number field code{nf}, i.e. set \(r = a + b\).+-- Canonicalisation is not performed.+foreign import ccall "nf_elem.h _nf_elem_add"+ _nf_elem_add :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_add/ /r/ /a/ /b/ /nf/ +-- +-- Add two elements of a number field code{nf}, i.e. set \(r = a + b\).+foreign import ccall "nf_elem.h nf_elem_add"+ nf_elem_add :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /_nf_elem_sub/ /r/ /a/ /b/ /nf/ +-- +-- Subtract two elements of a number field code{nf}, i.e. set+-- \(r = a - b\). Canonicalisation is not performed.+foreign import ccall "nf_elem.h _nf_elem_sub"+ _nf_elem_sub :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_sub/ /r/ /a/ /b/ /nf/ +-- +-- Subtract two elements of a number field code{nf}, i.e. set+-- \(r = a - b\).+foreign import ccall "nf_elem.h nf_elem_sub"+ nf_elem_sub :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /_nf_elem_mul/ /a/ /b/ /c/ /nf/ +-- +-- Multiply two elements of a number field code{nf}, i.e. set+-- \(r = a * b\). Does not canonicalise. Aliasing of inputs with output is+-- not supported.+foreign import ccall "nf_elem.h _nf_elem_mul"+ _nf_elem_mul :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /_nf_elem_mul_red/ /a/ /b/ /c/ /nf/ /red/ +-- +-- As per code{_nf_elem_mul}, but reduction modulo the defining polynomial+-- of the number field is only carried out if code{red == 1}. Assumes both+-- inputs are reduced.+foreign import ccall "nf_elem.h _nf_elem_mul_red"+ _nf_elem_mul_red :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> CInt -> IO ()++-- | /nf_elem_mul/ /a/ /b/ /c/ /nf/ +-- +-- Multiply two elements of a number field code{nf}, i.e. set+-- \(r = a * b\).+foreign import ccall "nf_elem.h nf_elem_mul"+ nf_elem_mul :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_mul_red/ /a/ /b/ /c/ /nf/ /red/ +-- +-- As per code{nf_elem_mul}, but reduction modulo the defining polynomial+-- of the number field is only carried out if code{red == 1}. Assumes both+-- inputs are reduced.+foreign import ccall "nf_elem.h nf_elem_mul_red"+ nf_elem_mul_red :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> CInt -> IO ()++-- | /_nf_elem_inv/ /r/ /a/ /nf/ +-- +-- Invert an element of a number field code{nf}, i.e. set \(r = a^{-1}\).+-- Aliasing of the input with the output is not supported.+foreign import ccall "nf_elem.h _nf_elem_inv"+ _nf_elem_inv :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_inv/ /r/ /a/ /nf/ +-- +-- Invert an element of a number field code{nf}, i.e. set \(r = a^{-1}\).+foreign import ccall "nf_elem.h nf_elem_inv"+ nf_elem_inv :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /_nf_elem_div/ /a/ /b/ /c/ /nf/ +-- +-- Set \(a\) to \(b/c\) in the given number field. Aliasing of \(a\) and+-- \(b\) is not permitted.+foreign import ccall "nf_elem.h _nf_elem_div"+ _nf_elem_div :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_div/ /a/ /b/ /c/ /nf/ +-- +-- Set \(a\) to \(b/c\) in the given number field.+foreign import ccall "nf_elem.h nf_elem_div"+ nf_elem_div :: Ptr CNFElem -> Ptr CNFElem -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /_nf_elem_pow/ /res/ /a/ /e/ /nf/ +-- +-- Set code{res} to \(a^e\) using left-to-right binary exponentiation as+-- described in~citep[p.~461]{Knu1997}.+-- +-- Assumes that \(a \neq 0\) and \(e > 1\). Does not support aliasing.+foreign import ccall "nf_elem.h _nf_elem_pow"+ _nf_elem_pow :: Ptr CNFElem -> Ptr CNFElem -> CULong -> Ptr CNF -> IO ()++-- | /nf_elem_pow/ /res/ /a/ /e/ /nf/ +-- +-- Set code{res} = code{a^e} using the binary exponentiation algorithm. If+-- \(e\) is zero, returns one, so that in particular code{0^0 = 1}.+foreign import ccall "nf_elem.h nf_elem_pow"+ nf_elem_pow :: Ptr CNFElem -> Ptr CNFElem -> CULong -> Ptr CNF -> IO ()++-- | /_nf_elem_norm/ /rnum/ /rden/ /a/ /nf/ +-- +-- Set code{{rnum, rden}} to the absolute norm of the given number field+-- element \(a\).+foreign import ccall "nf_elem.h _nf_elem_norm"+ _nf_elem_norm :: Ptr CFmpz -> Ptr CFmpz -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_norm/ /res/ /a/ /nf/ +-- +-- Set code{res} to the absolute norm of the given number field element+-- \(a\).+foreign import ccall "nf_elem.h nf_elem_norm"+ nf_elem_norm :: Ptr CFmpq -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_norm_div/ /res/ /a/ /nf/ /div/ /nbits/ +-- +-- Set code{res} to the absolute norm of the given number field element+-- \(a\), divided by code{div} . Assumes the result to be an integer and+-- having at most code{nbits} bits.+foreign import ccall "nf_elem.h nf_elem_norm_div"+ nf_elem_norm_div :: Ptr CFmpq -> Ptr CNFElem -> Ptr CNF -> Ptr CFmpz -> CLong -> IO ()++-- | /_nf_elem_norm_div/ /rnum/ /rden/ /a/ /nf/ /divisor/ /nbits/ +-- +-- Set code{{rnum, rden}} to the absolute norm of the given number field+-- element \(a\), divided by code{div} . Assumes the result to be an+-- integer and having at most code{nbits} bits.+foreign import ccall "nf_elem.h _nf_elem_norm_div"+ _nf_elem_norm_div :: Ptr CFmpz -> Ptr CFmpz -> Ptr CNFElem -> Ptr CNF -> Ptr CFmpz -> CLong -> IO ()++-- | /_nf_elem_trace/ /rnum/ /rden/ /a/ /nf/ +-- +-- Set code{{rnum, rden}} to the absolute trace of the given number field+-- element \(a\).+foreign import ccall "nf_elem.h _nf_elem_trace"+ _nf_elem_trace :: Ptr CFmpz -> Ptr CFmpz -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_trace/ /res/ /a/ /nf/ +-- +-- Set code{res} to the absolute trace of the given number field element+-- \(a\).+foreign import ccall "nf_elem.h nf_elem_trace"+ nf_elem_trace :: Ptr CFmpq -> Ptr CNFElem -> Ptr CNF -> IO ()++-- Representation matrix -------------------------------------------------------++-- | /nf_elem_rep_mat/ /res/ /a/ /nf/ +-- +-- Set code{res} to the matrix representing the multiplication with \(a\)+-- with respect to the basis \(1, a, \dotsc, a^{d - 1}\), where \(a\) is+-- the generator of the number field of \(d\) is its degree.+foreign import ccall "nf_elem.h nf_elem_rep_mat"+ nf_elem_rep_mat :: Ptr CFmpqMat -> Ptr CNFElem -> Ptr CNF -> IO ()++-- | /nf_elem_rep_mat_fmpz_mat_den/ /res/ /den/ /a/ /nf/ +-- +-- Return a tuple \(M, d\) such that \(M/d\) is the matrix representing the+-- multiplication with \(a\) with respect to the basis+-- \(1, a, \dotsc, a^{d - 1}\), where \(a\) is the generator of the number+-- field of \(d\) is its degree. The integral matrix \(M\) is primitive.+foreign import ccall "nf_elem.h nf_elem_rep_mat_fmpz_mat_den"+ nf_elem_rep_mat_fmpz_mat_den :: Ptr CFmpzMat -> Ptr CFmpz -> Ptr CNFElem -> Ptr CNF -> IO ()++-- Modular reduction -----------------------------------------------------------++-- | /nf_elem_mod_fmpz_den/ /z/ /a/ /mod/ /nf/ +-- +-- If code{den == 0}, return an element \(z\) with denominator \(1\), such+-- that the coefficients of \(z - da\) are divisble by code{mod}, where+-- \(d\) is the denominator of \(a\). The coefficients of \(z\) are reduced+-- modulo code{mod}.+-- +-- If code{den == 1}, return an element \(z\), such that \(z - a\) has+-- denominator \(1\) and the coefficients of \(z - a\) are divisble by+-- code{mod}. The coefficients of \(z\) are reduced modulo code{mod * d},+-- where \(d\) is the denominator of \(a\).+-- +-- Reduction takes place with respect to the positive residue system.+foreign import ccall "nf_elem.h nf_elem_mod_fmpz_den"+ nf_elem_mod_fmpz_den :: Ptr CNFElem -> Ptr CNFElem -> Ptr CFmpz -> Ptr CNF -> IO ()++-- | /nf_elem_smod_fmpz_den/ /z/ /a/ /mod/ /nf/ +-- +-- If code{den == 0}, return an element \(z\) with denominator \(1\), such+-- that the coefficients of \(z - da\) are divisble by code{mod}, where+-- \(d\) is the denominator of \(a\). The coefficients of \(z\) are reduced+-- modulo code{mod}.+-- +-- If code{den == 1}, return an element \(z\), such that \(z - a\) has+-- denominator \(1\) and the coefficients of \(z - a\) are divisble by+-- code{mod}. The coefficients of \(z\) are reduced modulo code{mod * d},+-- where \(d\) is the denominator of \(a\).+-- +-- Reduction takes place with respect to the symmetric residue system.+foreign import ccall "nf_elem.h nf_elem_smod_fmpz_den"+ nf_elem_smod_fmpz_den :: Ptr CNFElem -> Ptr CNFElem -> Ptr CFmpz -> Ptr CNF -> IO ()++-- | /nf_elem_mod_fmpz/ /res/ /a/ /mod/ /nf/ +-- +-- Return an element \(z\) such that \(z - a\) has denominator \(1\) and+-- the coefficients of \(z - a\) are divisible by code{mod}. The+-- coefficients of \(z\) are reduced modulo code{mod * d}, where \(d\) is+-- the denominator of \(b\).+-- +-- Reduction takes place with respect to the positive residue system.+foreign import ccall "nf_elem.h nf_elem_mod_fmpz"+ nf_elem_mod_fmpz :: Ptr CNFElem -> Ptr CNFElem -> Ptr CFmpz -> Ptr CNF -> IO ()++-- | /nf_elem_smod_fmpz/ /res/ /a/ /mod/ /nf/ +-- +-- Return an element \(z\) such that \(z - a\) has denominator \(1\) and+-- the coefficients of \(z - a\) are divisible by code{mod}. The+-- coefficients of \(z\) are reduced modulo code{mod * d}, where \(d\) is+-- the denominator of \(b\).+-- +-- Reduction takes place with respect to the symmetric residue system.+foreign import ccall "nf_elem.h nf_elem_smod_fmpz"+ nf_elem_smod_fmpz :: Ptr CNFElem -> Ptr CNFElem -> Ptr CFmpz -> Ptr CNF -> IO ()++-- | /nf_elem_coprime_den/ /res/ /a/ /mod/ /nf/ +-- +-- Return an element \(z\) such that the denominator of \(z - a\) is+-- coprime to code{mod}.+-- +-- Reduction takes place with respect to the positive residue system.+foreign import ccall "nf_elem.h nf_elem_coprime_den"+ nf_elem_coprime_den :: Ptr CNFElem -> Ptr CNFElem -> Ptr CFmpz -> Ptr CNF -> IO ()++-- | /nf_elem_coprime_den_signed/ /res/ /a/ /mod/ /nf/ +-- +-- Return an element \(z\) such that the denominator of \(z - a\) is+-- coprime to code{mod}.+-- +-- Reduction takes place with respect to the symmetric residue system.+foreign import ccall "nf_elem.h nf_elem_coprime_den_signed"+ nf_elem_coprime_den_signed :: Ptr CNFElem -> Ptr CNFElem -> Ptr CFmpz -> Ptr CNF -> IO ()+
+ src/Data/Number/Flint/NF/FFI.hsc view
@@ -0,0 +1,72 @@+{-|+module : Data.Number.Flint.NF.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NF.FFI (+ -- Number fields+ NF (..)+ , CNF (..)+ , newNF+ , withNF+ , nf_init+ , nf_clear+) where++-- Number fields ---------------------------------------------------------------++import Foreign.ForeignPtr+import Foreign.Ptr+import Foreign.Storable++import Data.Number.Flint.Fmpq.Poly++#include <flint/nf.h>++-- nf_t ------------------------------------------------------------------------++data NF = NF {-# UNPACK #-} !(ForeignPtr CNF)+data CNF = CNF++instance Storable CNF where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nf_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nf_t}+ peek = error "CNF.peek is not defined."+ poke = error "CNF.poke is not defined."++--------------------------------------------------------------------------------++-- | Create a new number field+newNF poly = do+ nf <- mallocForeignPtr+ withForeignPtr nf $ \nf ->+ withFmpqPoly poly $ \poly ->+ nf_init nf poly+ addForeignPtrFinalizer p_nf_clear nf + return $ NF nf++-- | Use number field+withNF (NF nf) f = do+ withForeignPtr nf $ \fp -> (NF nf,) <$> f fp++--------------------------------------------------------------------------------++-- | /nf_init/ /nf/ /pol/ +-- +-- Perform basic initialisation of a number field (for element arithmetic)+-- given a defining polynomial over \(\mathbb{Q}\).+foreign import ccall "nf.h nf_init"+ nf_init :: Ptr CNF -> Ptr CFmpqPoly -> IO ()++-- | /nf_clear/ /nf/ +-- +-- Release resources used by a number field object. The object will need+-- initialisation again before it can be used.+foreign import ccall "nf.h nf_clear"+ nf_clear :: Ptr CNF -> IO ()++foreign import ccall "nf.h &nf_clear"+ p_nf_clear :: FunPtr (Ptr CNF -> IO ())
+ src/Data/Number/Flint/NF/Fmpzi.hs view
@@ -0,0 +1,10 @@+{-+This module allows working with elements of the ring \(\mathbb{Z}[i]\).+At present, only a minimal interface is provided.+-}+module Data.Number.Flint.NF.Fmpzi (+ module Data.Number.Flint.NF.Fmpzi.FFI,+) where++import Data.Number.Flint.NF.Fmpzi.FFI+
+ src/Data/Number/Flint/NF/Fmpzi/FFI.hsc view
@@ -0,0 +1,273 @@+{-|+module : Data.Number.Flint.NF.Fmpzi.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NF.Fmpzi.FFI (+ -- * Gaussian integers+ Fmpzi (..)+ , CFmpzi (..)+ , newFmpzi+ , newFmpzi_+ , withFmpzi+ , withNewFmpzi+ , withFmpziReal+ , withFmpziImag+ -- * Types+ -- * Basic manipulation+ , fmpzi_init+ , fmpzi_clear+ , fmpzi_swap+ , fmpzi_zero+ , fmpzi_one+ , fmpzi_set+ , fmpzi_set_si_si+ -- * Input and output+ , fmpzi_get_str+ , fmpzi_fprint+ , fmpzi_print+ -- * Random number generation+ , fmpzi_randtest+ -- * Properties+ , fmpzi_equal+ , fmpzi_is_zero+ , fmpzi_is_one+ -- * Units+ , fmpzi_is_unit+ , fmpzi_canonical_unit_i_pow+ , fmpzi_canonicalise_unit+ -- * Norms+ , fmpzi_bits+ , fmpzi_norm+ -- * Arithmetic+ , fmpzi_conj+ , fmpzi_neg+ , fmpzi_add+ , fmpzi_sub+ , fmpzi_sqr+ , fmpzi_mul+ , fmpzi_pow_ui+ -- * Division+ , fmpzi_divexact+ , fmpzi_divrem+ , fmpzi_divrem_approx+ , fmpzi_remove_one_plus_i+ -- * GCD+ , fmpzi_gcd_euclidean+) where ++-- Gaussian integers -----------------------------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import qualified Foreign.Concurrent+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++#include <flint/fmpzi.h>++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz++-- Types -----------------------------------------------------------------------++data Fmpzi = Fmpzi {-# UNPACK #-} !(ForeignPtr CFmpzi)+data CFmpzi = CFmpzi CFmpz CFmpz++instance Storable CFmpzi where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fmpzi_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fmpzi_t}+ peek = undefined+ poke = undefined++-- | Create `Fmpzi`.+newFmpzi = do+ x <- mallocForeignPtr+ withForeignPtr x fmpzi_init+ addForeignPtrFinalizer p_fmpzi_clear x+ return $ Fmpzi x++-- | Create `Fmpzi`.+newFmpzi_ a b = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ fmpzi_init x+ fmpzi_set_si_si x a b+ addForeignPtrFinalizer p_fmpzi_clear x+ return $ Fmpzi x++-- | Use `Fmpzi`+{-# INLINE withFmpzi #-}+withFmpzi (Fmpzi x) f = do+ withForeignPtr x $ \p -> f p >>= return . (Fmpzi x,)++-- | Use real part of `Fmpzi`+{-# INLINE withFmpziReal #-}+withFmpziReal (Fmpzi x) f = do+ withForeignPtr x $ \p -> (Fmpzi x,) <$> f (castPtr p)++-- | Use imaginary part of `Fmpzi`+{-# INLINE withFmpziImag #-}+withFmpziImag (Fmpzi x) f = do+ withForeignPtr x $ \p -> (Fmpzi x,) <$> f (castPtr p `advancePtr` 1)++-- | Use new `Fmpzi`+{-# INLINE withNewFmpzi #-}+withNewFmpzi f = do+ x <- newFmpzi+ withFmpzi x f ++-- Memory management -----------------------------------------------------------++foreign import ccall "fmpzi.h fmpzi_init"+ fmpzi_init :: Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h fmpzi_clear"+ fmpzi_clear :: Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h &fmpzi_clear"+ p_fmpzi_clear :: FunPtr (Ptr CFmpzi -> IO ())++-- Basic manipulation ----------------------------------------------------------++foreign import ccall "fmpzi.h fmpzi_swap"+ fmpzi_swap :: Ptr CFmpzi -> Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h fmpzi_zero"+ fmpzi_zero :: Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h fmpzi_one"+ fmpzi_one :: Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h fmpzi_set"+ fmpzi_set :: Ptr CFmpzi -> Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h fmpzi_set_si_si"+ fmpzi_set_si_si :: Ptr CFmpzi -> CLong -> CLong -> IO ()++-- Input and output ------------------------------------------------------------++foreign import ccall "fmpzi.h fmpzi_get_str"+ fmpzi_get_str :: Ptr CFmpzi -> IO CString++foreign import ccall "fmpzi.h fmpzi_fprint"+ fmpzi_fprint :: Ptr CFile -> Ptr CFmpzi -> IO ()+ +fmpzi_print :: Ptr CFmpzi -> IO ()+fmpzi_print z = do+ printCStr fmpzi_get_str z+ return ()++-- Random number generation ----------------------------------------------------++foreign import ccall "fmpzi.h fmpzi_randtest"+ fmpzi_randtest :: Ptr CFmpzi -> Ptr CFRandState -> CMpBitCnt -> IO ()++-- Properties ------------------------------------------------------------------++foreign import ccall "fmpzi.h fmpzi_equal"+ fmpzi_equal :: Ptr CFmpzi -> Ptr CFmpzi -> IO CInt++foreign import ccall "fmpzi.h fmpzi_is_zero"+ fmpzi_is_zero :: Ptr CFmpzi -> IO CInt++foreign import ccall "fmpzi.h fmpzi_is_one"+ fmpzi_is_one :: Ptr CFmpzi -> IO CInt++-- Units -----------------------------------------------------------------------++foreign import ccall "fmpzi.h fmpzi_is_unit"+ fmpzi_is_unit :: Ptr CFmpzi -> IO CInt++foreign import ccall "fmpzi.h fmpzi_canonical_unit_i_pow"+ fmpzi_canonical_unit_i_pow :: Ptr CFmpzi -> IO CLong++foreign import ccall "fmpzi.h fmpzi_canonicalise_unit"+ fmpzi_canonicalise_unit :: Ptr CFmpzi -> Ptr CFmpzi -> IO ()++-- Norms -----------------------------------------------------------------------++foreign import ccall "fmpzi.h fmpzi_bits"+ fmpzi_bits :: Ptr CFmpzi -> IO CLong++foreign import ccall "fmpzi.h fmpzi_norm"+ fmpzi_norm :: Ptr CFmpz -> Ptr CFmpzi -> IO ()++-- Arithmetic ------------------------------------------------------------------++foreign import ccall "fmpzi.h fmpzi_conj"+ fmpzi_conj :: Ptr CFmpzi -> Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h fmpzi_neg"+ fmpzi_neg :: Ptr CFmpzi -> Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h fmpzi_add"+ fmpzi_add :: Ptr CFmpzi -> Ptr CFmpzi -> Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h fmpzi_sub"+ fmpzi_sub :: Ptr CFmpzi -> Ptr CFmpzi -> Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h fmpzi_sqr"+ fmpzi_sqr :: Ptr CFmpzi -> Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h fmpzi_mul"+ fmpzi_mul :: Ptr CFmpzi -> Ptr CFmpzi -> Ptr CFmpzi -> IO ()++foreign import ccall "fmpzi.h fmpzi_pow_ui"+ fmpzi_pow_ui :: Ptr CFmpzi -> Ptr CFmpzi -> CULong -> IO ()++-- Division --------------------------------------------------------------------++-- | /fmpzi_divexact/ /q/ /x/ /y/ +-- +-- Sets /q/ to the quotient of /x/ and /y/, assuming that the division is+-- exact.+foreign import ccall "fmpzi.h fmpzi_divexact"+ fmpzi_divexact :: Ptr CFmpzi -> Ptr CFmpzi -> Ptr CFmpzi -> IO ()++-- | /fmpzi_divrem/ /q/ /r/ /x/ /y/ +-- +-- Computes a quotient and remainder satisfying \(x = q y + r\) with+-- \(N(r) \le N(y)/2\), with a canonical choice of remainder when breaking+-- ties.+foreign import ccall "fmpzi.h fmpzi_divrem"+ fmpzi_divrem :: Ptr CFmpzi -> Ptr CFmpzi -> Ptr CFmpzi -> Ptr CFmpzi -> IO ()++-- | /fmpzi_divrem_approx/ /q/ /r/ /x/ /y/ +-- +-- Computes a quotient and remainder satisfying \(x = q y + r\) with+-- \(N(r) < N(y)\), with an implementation-defined, non-canonical choice of+-- remainder.+foreign import ccall "fmpzi.h fmpzi_divrem_approx"+ fmpzi_divrem_approx :: Ptr CFmpzi -> Ptr CFmpzi -> Ptr CFmpzi -> Ptr CFmpzi -> IO ()++-- | /fmpzi_remove_one_plus_i/ /res/ /x/ +-- +-- Divide /x/ exactly by the largest possible power \((1+i)^k\) and return+-- the exponent /k/.+foreign import ccall "fmpzi.h fmpzi_remove_one_plus_i"+ fmpzi_remove_one_plus_i :: Ptr CFmpzi -> Ptr CFmpzi -> IO CLong++-- GCD -------------------------------------------------------------------------++-- | /fmpzi_gcd_euclidean/ /res/ /x/ /y/ +-- +-- Computes the GCD of /x/ and /y/. The result is in canonical unit form.+-- +-- The /euclidean/ version is a straightforward implementation of Euclid\'s+-- algorithm. The /euclidean_improved/ version is optimized by performing+-- approximate divisions. The /binary/ version uses a (1+i)-ary analog of+-- the binary GCD algorithm for integers < [Wei2000]>. The /shortest/+-- version finds the GCD as the shortest vector in a lattice. The default+-- version chooses an algorithm automatically.+foreign import ccall "fmpzi.h fmpzi_gcd_euclidean"+ fmpzi_gcd_euclidean :: Ptr CFmpzi -> Ptr CFmpzi -> Ptr CFmpzi -> IO ()+
+ src/Data/Number/Flint/NF/Fmpzi/Instances.hs view
@@ -0,0 +1,50 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.NF.Fmpzi.Instances where++import System.IO.Unsafe+import Foreign.C.String+import Foreign.Marshal.Alloc ( free )++import Data.Number.Flint.NF.Fmpzi++instance Show Fmpzi where+ show x = unsafePerformIO $ do+ (_, cs) <- withFmpzi x fmpzi_get_str+ s <- peekCString cs+ free cs+ return s++instance Eq Fmpzi where+ (==) x y = snd $ snd $ unsafePerformIO $ + withFmpzi x $ \x ->+ withFmpzi y $ \y -> do+ result <- fmpzi_equal x y+ return $ result == 1++instance Num Fmpzi where+ {-# INLINE (+) #-}+ (+) = lift2 fmpzi_add+ {-# INLINE (-) #-}+ (-) = lift2 fmpzi_sub+ {-# INLINE (*) #-}+ (*) = lift2 fmpzi_mul+ negate = lift1 fmpzi_neg+ abs = undefined+ fromInteger x = unsafePerformIO $ do+ result <- newFmpzi+ withFmpzi result $ \result -> do+ fmpzi_set_si_si result (fromInteger x) 1+ return result+ signum = undefined++lift1 f x = fst $ unsafePerformIO $ + withNewFmpzi $ \result -> + withFmpzi x $ \x ->+ f result x+ +lift2 f x y = fst $ unsafePerformIO $ + withNewFmpzi $ \result ->+ withFmpzi x $ \x ->+ withFmpzi y $ \y ->+ f result x y+
+ src/Data/Number/Flint/NF/QQbar.hs view
@@ -0,0 +1,31 @@+{-|+module : Data.Number.Flint.NF.QQbar+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++= Algebraic numbers++A @QQbar@ represents a real or complex algebraic number +(an element of \(\overline{\mathbb{Q}}\)) by its unique reduced +minimal polynomial in \(\mathbb{Z}[x]\) and an isolating complex interval. +The precision of isolating intervals is maintained automatically to ensure +that all operations on @QQbar@ instances are exact.++This representation is useful for working with individual algebraic+numbers of moderate degree (up to 100, say). Arithmetic in this+representation is expensive: an arithmetic operation on numbers of+degrees /m/ and /n/ involves computing and then factoring an+annihilating polynomial of degree /mn/ and potentially also performing+numerical root-finding. For doing repeated arithmetic, it is generally+more efficient to work with the @CA@ type in a fixed number field. The+@QQbar@ type is used internally by the @CA@ type to represent the+embedding of number fields in \(\mathbb{R}\) or \(\mathbb{C}\) and to decide+predicates for algebraic numbers.+-}+module Data.Number.Flint.NF.QQbar (+ module Data.Number.Flint.NF.QQbar.FFI,+) where++import Data.Number.Flint.NF.QQbar.FFI+
+ src/Data/Number/Flint/NF/QQbar/FFI.hsc view
@@ -0,0 +1,1511 @@+{-|+module : Data.Number.Flint.NF.QQbar.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NF.QQbar.FFI (+ -- * Algebraic numbers represented by minimal polynomials+ -- * Types+ QQbar (..)+ , CQQbar (..)+ , newQQbar+ , newQQbarFromFmpz+ , newQQbarFromFmpq+ , newQQbarFromDouble+ , withQQbar+ , withNewQQbar+ -- * Assignment+ , qqbar_swap+ , qqbar_set+ , qqbar_set_si+ , qqbar_set_ui+ , qqbar_set_fmpz+ , qqbar_set_fmpq+ , qqbar_set_re_im+ , qqbar_set_d+ , qqbar_set_re_im_d+ -- * Properties+ , qqbar_degree+ , qqbar_is_rational+ , qqbar_is_integer+ , qqbar_is_algebraic_integer+ , qqbar_is_zero+ , qqbar_is_one+ , qqbar_is_neg_one+ , qqbar_is_i+ , qqbar_is_neg_i+ , qqbar_is_real+ , qqbar_height+ , qqbar_height_bits+ , qqbar_within_limits+ , qqbar_binop_within_limits+ -- * Conversions+ , _qqbar_get_fmpq+ , qqbar_get_fmpq+ , qqbar_get_fmpz+ -- * Special values+ , qqbar_zero+ , qqbar_one+ , qqbar_i+ , qqbar_phi+ -- * Input and output+ , qqbar_get_str+ , qqbar_get_strn+ , qqbar_get_strnd+ , qqbar_print+ , qqbar_printn+ , qqbar_printnd+ -- * Random generation+ , qqbar_randtest+ , qqbar_randtest_real+ , qqbar_randtest_nonreal+ -- * Comparisons+ , qqbar_equal+ , qqbar_equal_fmpq_poly_val+ , qqbar_cmp_re+ , qqbar_cmp_im+ , qqbar_cmpabs_re+ , qqbar_cmpabs_im+ , qqbar_cmpabs+ , qqbar_cmp_root_order+ , qqbar_hash+ -- * Complex parts+ , qqbar_conj+ , qqbar_re+ , qqbar_im+ , qqbar_re_im+ , qqbar_abs+ , qqbar_abs2+ , qqbar_sgn+ , qqbar_sgn_re+ , qqbar_sgn_im+ , qqbar_csgn+ -- * Integer parts+ , qqbar_floor+ , qqbar_ceil+ -- * Arithmetic+ , qqbar_neg+ , qqbar_add+ , qqbar_add_fmpq+ , qqbar_add_fmpz+ , qqbar_add_ui+ , qqbar_add_si+ , qqbar_sub+ , qqbar_sub_fmpq+ , qqbar_sub_fmpz+ , qqbar_sub_ui+ , qqbar_sub_si+ , qqbar_fmpq_sub+ , qqbar_fmpz_sub+ , qqbar_ui_sub+ , qqbar_si_sub+ , qqbar_mul+ , qqbar_mul_fmpq+ , qqbar_mul_fmpz+ , qqbar_mul_ui+ , qqbar_mul_si+ , qqbar_mul_2exp_si+ , qqbar_sqr+ , qqbar_inv+ , qqbar_div+ , qqbar_div_fmpq+ , qqbar_div_fmpz+ , qqbar_div_ui+ , qqbar_div_si+ , qqbar_fmpq_div+ , qqbar_fmpz_div+ , qqbar_ui_div+ , qqbar_si_div+ , qqbar_scalar_op+ -- * Powers and roots+ , qqbar_sqrt+ , qqbar_sqrt_ui+ , qqbar_rsqrt+ , qqbar_pow_ui+ , qqbar_pow_si+ , qqbar_pow_fmpz+ , qqbar_pow_fmpq+ , qqbar_root_ui+ , qqbar_fmpq_root_ui+ , qqbar_fmpq_pow_si_ui+ , qqbar_pow+ -- * Numerical enclosures+ , qqbar_get_acb+ , qqbar_get_arb+ , qqbar_get_arb_re+ , qqbar_get_arb_im+ , qqbar_cache_enclosure+ -- * Numerator and denominator+ , qqbar_denominator+ , qqbar_numerator+ -- * Conjugates+ , qqbar_conjugates+ -- * Polynomial evaluation+ , _qqbar_evaluate_fmpq_poly+ , qqbar_evaluate_fmpq_poly+ , _qqbar_evaluate_fmpz_poly+ , qqbar_evaluate_fmpz_poly+ , qqbar_evaluate_fmpz_mpoly_iter+ , qqbar_evaluate_fmpz_mpoly_horner+ , qqbar_evaluate_fmpz_mpoly+ -- * Polynomial roots+ , qqbar_roots_fmpz_poly+ , qqbar_roots_fmpq_poly+ , qqbar_eigenvalues_fmpz_mat+ , qqbar_eigenvalues_fmpq_mat+ -- * Roots of unity and trigonometric functions+ , qqbar_root_of_unity+ , qqbar_is_root_of_unity+ , qqbar_exp_pi_i+ , qqbar_cos_pi+ , qqbar_sin_pi+ , qqbar_tan_pi+ , qqbar_cot_pi+ , qqbar_sec_pi+ , qqbar_csc_pi+ , qqbar_log_pi_i+ , qqbar_atan_pi+ , qqbar_asin_pi+ , qqbar_acos_pi+ , qqbar_acot_pi+ , qqbar_asec_pi+ , qqbar_acsc_pi+ -- * Guessing and simplification+ , qqbar_guess+ , qqbar_express_in_field+ -- * Symbolic expressions and conversion to radicals+ , qqbar_get_quadratic+ , qqbar_set_fexpr+ , qqbar_get_fexpr_repr+ , qqbar_get_fexpr_root_nearest+ , qqbar_get_fexpr_root_indexed+ , qqbar_get_fexpr_formula+ -- * Internal functions+ , qqbar_fmpz_poly_composed_op+ , qqbar_binary_op+ , _qqbar_validate_uniqueness+ , _qqbar_validate_existence_uniqueness+ , _qqbar_enclosure_raw+ , qqbar_enclosure_raw+ , _qqbar_acb_lindep+) where++-- Algebraic numbers represented by minimal polynomials ------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable+import Foreign.C.Types+import Foreign.C.String+import Foreign.Marshal.Alloc++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpz.MPoly++import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fmpq.Poly++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb.Types++#include <flint/qqbar.h>++-- qq_bar_t --------------------------------------------------------------------++data QQbar = QQbar {-# UNPACK #-} !(ForeignPtr CQQbar) +type CQQbar = CFlint QQbar++instance Storable CQQbar where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size qqbar_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment qqbar_t}+ peek = undefined+ poke = undefined+ +-- | Create a QQbar.+newQQbar = do+ p <- mallocForeignPtr+ withForeignPtr p qqbar_init+ addForeignPtrFinalizer p_qqbar_clear p+ return $ QQbar p++-- | Create a QQbar from Fmpz.+newQQbarFromFmpz x = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p -> do+ qqbar_init p+ withFmpz x $ \x -> qqbar_set_fmpz p x+ addForeignPtrFinalizer p_qqbar_clear p+ return $ QQbar p++-- | Create a QQbar from Fmpq.+newQQbarFromFmpq x = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p -> do+ qqbar_init p+ withFmpq x $ \x -> qqbar_set_fmpq p x+ addForeignPtrFinalizer p_qqbar_clear p+ return $ QQbar p++-- | Create a QQbar from Double.+newQQbarFromDouble x = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p -> do+ qqbar_init p+ qqbar_set_d p (realToFrac x)+ addForeignPtrFinalizer p_qqbar_clear p+ return $ QQbar p++-- | Use QQbar in `f`.+{-# INLINE withQQbar #-}+withQQbar (QQbar p) f = do+ withForeignPtr p $ \fp -> (QQbar p,) <$> f fp++-- | Apply `f` to new QQbar.+{-# INLINE withNewQQbar #-}+withNewQQbar f = do+ x <- newQQbar+ withQQbar x f++-- Memory management -----------------------------------------------------------++-- | /qqbar_init/ /res/ +-- +-- Initializes the variable /res/ for use, and sets its value to zero.+foreign import ccall "qqbar.h qqbar_init"+ qqbar_init :: Ptr CQQbar -> IO ()++-- | /qqbar_clear/ /res/ +-- +-- Clears the variable /res/, freeing or recycling its allocated memory.+foreign import ccall "qqbar.h qqbar_clear"+ qqbar_clear :: Ptr CQQbar -> IO ()++foreign import ccall "qqbar.h &qqbar_clear"+ p_qqbar_clear :: FunPtr (Ptr CQQbar -> IO ())++-- | /_qqbar_vec_init/ /len/ +-- +-- Returns a pointer to an array of /len/ initialized /qqbar_struct/:s.+foreign import ccall "qqbar.h _qqbar_vec_init"+ _qqbar_vec_init :: CLong -> IO (Ptr CQQbar)++-- | /_qqbar_vec_clear/ /vec/ /len/ +-- +-- Clears all /len/ entries in the vector /vec/ and frees the vector+-- itself.+foreign import ccall "qqbar.h _qqbar_vec_clear"+ _qqbar_vec_clear :: Ptr CQQbar -> CLong -> IO ()++-- Assignment ------------------------------------------------------------------++-- | /qqbar_swap/ /x/ /y/ +--+-- Swaps the values of /x/ and /y/ efficiently.+foreign import ccall "qqbar.h qqbar_swap"+ qqbar_swap :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_set/ /res/ /x/ +foreign import ccall "qqbar.h qqbar_set"+ qqbar_set :: Ptr CQQbar -> Ptr CQQbar -> IO ()+-- | /qqbar_set_si/ /res/ /x/ +foreign import ccall "qqbar.h qqbar_set_si"+ qqbar_set_si :: Ptr CQQbar -> CLong -> IO ()+-- | /qqbar_set_ui/ /res/ /x/ +foreign import ccall "qqbar.h qqbar_set_ui"+ qqbar_set_ui :: Ptr CQQbar -> CULong -> IO ()+-- | /qqbar_set_fmpz/ /res/ /x/ +foreign import ccall "qqbar.h qqbar_set_fmpz"+ qqbar_set_fmpz :: Ptr CQQbar -> Ptr CFmpz -> IO ()+-- | /qqbar_set_fmpq/ /res/ /x/ +--+-- Sets /res/ to the value /x/.+foreign import ccall "qqbar.h qqbar_set_fmpq"+ qqbar_set_fmpq :: Ptr CQQbar -> Ptr CFmpq -> IO ()++-- | /qqbar_set_re_im/ /res/ /x/ /y/ +--+-- Sets /res/ to the value \(x + yi\).+foreign import ccall "qqbar.h qqbar_set_re_im"+ qqbar_set_re_im :: Ptr CQQbar -> Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_set_d/ /res/ /x/ +foreign import ccall "qqbar.h qqbar_set_d"+ qqbar_set_d :: Ptr CQQbar -> CDouble -> IO CInt+-- | /qqbar_set_re_im_d/ /res/ /x/ /y/ +--+-- Sets /res/ to the value /x/ or \(x + yi\) respectively. These functions+-- performs error handling: if /x/ and /y/ are finite, the conversion+-- succeeds and the return flag is 1. If /x/ or /y/ is non-finite (infinity+-- or NaN), the conversion fails and the return flag is 0.+foreign import ccall "qqbar.h qqbar_set_re_im_d"+ qqbar_set_re_im_d :: Ptr CQQbar -> CDouble -> CDouble -> IO CInt++-- Properties ------------------------------------------------------------------++-- | /qqbar_degree/ /x/ +--+-- Returns the degree of /x/, i.e. the degree of the minimal polynomial.+foreign import ccall "qqbar.h qqbar_degree"+ qqbar_degree :: Ptr CQQbar -> IO CLong++-- | /qqbar_is_rational/ /x/ +--+-- Returns whether /x/ is a rational number.+foreign import ccall "qqbar.h qqbar_is_rational"+ qqbar_is_rational :: Ptr CQQbar -> IO CInt++-- | /qqbar_is_integer/ /x/ +--+-- Returns whether /x/ is an integer (an element of \(\mathbb{Z}\)).+foreign import ccall "qqbar.h qqbar_is_integer"+ qqbar_is_integer :: Ptr CQQbar -> IO CInt++-- | /qqbar_is_algebraic_integer/ /x/ +--+-- Returns whether /x/ is an algebraic integer, i.e. whether its minimal+-- polynomial has leading coefficient 1.+foreign import ccall "qqbar.h qqbar_is_algebraic_integer"+ qqbar_is_algebraic_integer :: Ptr CQQbar -> IO CInt++-- | /qqbar_is_zero/ /x/ +foreign import ccall "qqbar.h qqbar_is_zero"+ qqbar_is_zero :: Ptr CQQbar -> IO CInt+-- | /qqbar_is_one/ /x/ +foreign import ccall "qqbar.h qqbar_is_one"+ qqbar_is_one :: Ptr CQQbar -> IO CInt+-- | /qqbar_is_neg_one/ /x/ +--+-- Returns whether /x/ is the number \(0\), \(1\), \(-1\).+foreign import ccall "qqbar.h qqbar_is_neg_one"+ qqbar_is_neg_one :: Ptr CQQbar -> IO CInt++-- | /qqbar_is_i/ /x/ +foreign import ccall "qqbar.h qqbar_is_i"+ qqbar_is_i :: Ptr CQQbar -> IO CInt+-- | /qqbar_is_neg_i/ /x/ +--+-- Returns whether /x/ is the imaginary unit \(i\) (respectively \(-i\)).+foreign import ccall "qqbar.h qqbar_is_neg_i"+ qqbar_is_neg_i :: Ptr CQQbar -> IO CInt++-- | /qqbar_is_real/ /x/ +--+-- Returns whether /x/ is a real number.+foreign import ccall "qqbar.h qqbar_is_real"+ qqbar_is_real :: Ptr CQQbar -> IO CInt++-- | /qqbar_height/ /res/ /x/ +--+-- Sets /res/ to the height of /x/ (the largest absolute value of the+-- coefficients of the minimal polynomial of /x/).+foreign import ccall "qqbar.h qqbar_height"+ qqbar_height :: Ptr CFmpz -> Ptr CQQbar -> IO ()++-- | /qqbar_height_bits/ /x/ +--+-- Returns the height of /x/ (the largest absolute value of the+-- coefficients of the minimal polynomial of /x/) measured in bits.+foreign import ccall "qqbar.h qqbar_height_bits"+ qqbar_height_bits :: Ptr CQQbar -> IO CLong++-- | /qqbar_within_limits/ /x/ /deg_limit/ /bits_limit/ +--+-- Checks if /x/ has degree bounded by /deg_limit/ and height bounded by+-- /bits_limit/ bits, returning 0 (false) or 1 (true). If /deg_limit/ is+-- set to 0, the degree check is skipped, and similarly for /bits_limit/.+foreign import ccall "qqbar.h qqbar_within_limits"+ qqbar_within_limits :: Ptr CQQbar -> CLong -> CLong -> IO CInt++-- | /qqbar_binop_within_limits/ /x/ /y/ /deg_limit/ /bits_limit/ +--+-- Checks if \(x + y\), \(x - y\), \(x \cdot y\) and \(x / y\) certainly+-- have degree bounded by /deg_limit/ (by multiplying the degrees for /x/+-- and /y/ to obtain a trivial bound). For /bits_limits/, the sum of the+-- bit heights of /x/ and /y/ is checked against the bound (this is only a+-- heuristic). If /deg_limit/ is set to 0, the degree check is skipped, and+-- similarly for /bits_limit/.+foreign import ccall "qqbar.h qqbar_binop_within_limits"+ qqbar_binop_within_limits :: Ptr CQQbar -> Ptr CQQbar -> CLong -> CLong -> IO CInt++-- Conversions -----------------------------------------------------------------++-- | /_qqbar_get_fmpq/ /num/ /den/ /x/ +--+-- Sets /num/ and /den/ to the numerator and denominator of /x/. Aborts if+-- /x/ is not a rational number.+foreign import ccall "qqbar.h _qqbar_get_fmpq"+ _qqbar_get_fmpq :: Ptr CFmpz -> Ptr CFmpz -> Ptr CQQbar -> IO ()++-- | /qqbar_get_fmpq/ /res/ /x/ +--+-- Sets /res/ to /x/. Aborts if /x/ is not a rational number.+foreign import ccall "qqbar.h qqbar_get_fmpq"+ qqbar_get_fmpq :: Ptr CFmpq -> Ptr CQQbar -> IO ()++-- | /qqbar_get_fmpz/ /res/ /x/ +--+-- Sets /res/ to /x/. Aborts if /x/ is not an integer.+foreign import ccall "qqbar.h qqbar_get_fmpz"+ qqbar_get_fmpz :: Ptr CFmpz -> Ptr CQQbar -> IO ()++-- Special values --------------------------------------------------------------++-- | /qqbar_zero/ /res/ +--+-- Sets /res/ to the number 0.+foreign import ccall "qqbar.h qqbar_zero"+ qqbar_zero :: Ptr CQQbar -> IO ()++-- | /qqbar_one/ /res/ +--+-- Sets /res/ to the number 1.+foreign import ccall "qqbar.h qqbar_one"+ qqbar_one :: Ptr CQQbar -> IO ()++-- | /qqbar_i/ /res/ +--+-- Sets /res/ to the imaginary unit \(i\).+foreign import ccall "qqbar.h qqbar_i"+ qqbar_i :: Ptr CQQbar -> IO ()++-- | /qqbar_phi/ /res/ +--+-- Sets /res/ to the golden ratio \(\varphi = \tfrac{1}{2}(\sqrt{5} + 1)\).+foreign import ccall "qqbar.h qqbar_phi"+ qqbar_phi :: Ptr CQQbar -> IO ()++-- Input and output ------------------------------------------------------------++foreign import ccall "qqbar.h qqbar_get_str"+ qqbar_get_str :: Ptr CQQbar -> IO CString++foreign import ccall "qqbar.h qqbar_get_strn"+ qqbar_get_strn :: Ptr CQQbar -> CLong -> IO CString++foreign import ccall "qqbar.h qqbar_get_strnd"+ qqbar_get_strnd :: Ptr CQQbar -> CLong -> IO CString+ +-- | /qqbar_print/ /x/ +-- +-- Prints /res/ to standard output. The output shows the degree and the+-- list of coefficients of the minimal polynomial followed by a decimal+-- representation of the enclosing interval. This function is mainly+-- intended for debugging.+qqbar_print :: Ptr CQQbar -> IO ()+qqbar_print x = do+ printCStr qqbar_get_str x+ return ()+ +-- | /qqbar_printn/ /x/ /n/ +-- +-- Prints /res/ to standard output. The output shows a decimal+-- approximation to /n/ digits.+qqbar_printn :: Ptr CQQbar -> CLong -> IO ()+qqbar_printn x digits = do+ printCStr (\x -> qqbar_get_strn x digits) x+ return ()+ +-- | /qqbar_printnd/ /x/ /n/ +-- +-- Prints /res/ to standard output. The output shows a decimal+-- approximation to /n/ digits, followed by the degree of the number.+qqbar_printnd :: Ptr CQQbar -> CLong -> IO ()+qqbar_printnd x digits = do+ printCStr (\x -> qqbar_get_strnd x digits) x+ return ()++-- For example, /print/, /printn/ and /printnd/ with \(n = 6\) give the+-- following output for the numbers 0, 1, \(i\), \(\varphi\),+-- \(\sqrt{2}-\sqrt{3} i\):++-- Random generation -----------------------------------------------------------++-- | /qqbar_randtest/ /res/ /state/ /deg/ /bits/ +--+-- Sets /res/ to a random algebraic number with degree up to /deg/ and with+-- height (measured in bits) up to /bits/.+foreign import ccall "qqbar.h qqbar_randtest"+ qqbar_randtest :: Ptr CQQbar -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /qqbar_randtest_real/ /res/ /state/ /deg/ /bits/ +--+-- Sets /res/ to a random real algebraic number with degree up to /deg/ and+-- with height (measured in bits) up to /bits/.+foreign import ccall "qqbar.h qqbar_randtest_real"+ qqbar_randtest_real :: Ptr CQQbar -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- | /qqbar_randtest_nonreal/ /res/ /state/ /deg/ /bits/ +--+-- Sets /res/ to a random nonreal algebraic number with degree up to /deg/+-- and with height (measured in bits) up to /bits/. Since all algebraic+-- numbers of degree 1 are real, /deg/ must be at least 2.+foreign import ccall "qqbar.h qqbar_randtest_nonreal"+ qqbar_randtest_nonreal :: Ptr CQQbar -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- Comparisons -----------------------------------------------------------------++-- | /qqbar_equal/ /x/ /y/ +--+-- Returns whether /x/ and /y/ are equal.+foreign import ccall "qqbar.h qqbar_equal"+ qqbar_equal :: Ptr CQQbar -> Ptr CQQbar -> IO CInt++-- | /qqbar_equal_fmpq_poly_val/ /x/ /f/ /y/ +--+-- Returns whether /x/ is equal to \(f(y)\). This function is more+-- efficient than evaluating \(f(y)\) and comparing the results.+foreign import ccall "qqbar.h qqbar_equal_fmpq_poly_val"+ qqbar_equal_fmpq_poly_val :: Ptr CQQbar -> Ptr CFmpqPoly -> Ptr CQQbar -> IO CInt++-- | /qqbar_cmp_re/ /x/ /y/ +--+-- Compares the real parts of /x/ and /y/, returning -1, 0 or +1.+foreign import ccall "qqbar.h qqbar_cmp_re"+ qqbar_cmp_re :: Ptr CQQbar -> Ptr CQQbar -> IO CInt++-- | /qqbar_cmp_im/ /x/ /y/ +--+-- Compares the imaginary parts of /x/ and /y/, returning -1, 0 or +1.+foreign import ccall "qqbar.h qqbar_cmp_im"+ qqbar_cmp_im :: Ptr CQQbar -> Ptr CQQbar -> IO CInt++-- | /qqbar_cmpabs_re/ /x/ /y/ +--+-- Compares the absolute values of the real parts of /x/ and /y/, returning+-- -1, 0 or +1.+foreign import ccall "qqbar.h qqbar_cmpabs_re"+ qqbar_cmpabs_re :: Ptr CQQbar -> Ptr CQQbar -> IO CInt++-- | /qqbar_cmpabs_im/ /x/ /y/ +--+-- Compares the absolute values of the imaginary parts of /x/ and /y/,+-- returning -1, 0 or +1.+foreign import ccall "qqbar.h qqbar_cmpabs_im"+ qqbar_cmpabs_im :: Ptr CQQbar -> Ptr CQQbar -> IO CInt++-- | /qqbar_cmpabs/ /x/ /y/ +--+-- Compares the absolute values of /x/ and /y/, returning -1, 0 or +1.+foreign import ccall "qqbar.h qqbar_cmpabs"+ qqbar_cmpabs :: Ptr CQQbar -> Ptr CQQbar -> IO CInt++-- | /qqbar_cmp_root_order/ /x/ /y/ +--+-- Compares /x/ and /y/ using an arbitrary but convenient ordering defined+-- on the complex numbers. This is useful for sorting the roots of a+-- polynomial in a canonical order.+-- +-- We define the root order as follows: real roots come first, in+-- descending order. Nonreal roots are subsequently ordered first by real+-- part in descending order, then in ascending order by the absolute value+-- of the imaginary part, and then in descending order of the sign. This+-- implies that complex conjugate roots are adjacent, with the root in the+-- upper half plane first.+foreign import ccall "qqbar.h qqbar_cmp_root_order"+ qqbar_cmp_root_order :: Ptr CQQbar -> Ptr CQQbar -> IO CInt++-- | /qqbar_hash/ /x/ +--+-- Returns a hash of /x/. As currently implemented, this function only+-- hashes the minimal polynomial of /x/. The user should mix in some bits+-- based on the numerical value if it is critical to distinguish between+-- conjugates of the same minimal polynomial. This function is also likely+-- to produce serial runs of values for lexicographically close minimal+-- polynomials. This is not necessarily a problem for use in hash tables,+-- but if it is important that all bits in the output are random, the user+-- should apply an integer hash function to the output.+foreign import ccall "qqbar.h qqbar_hash"+ qqbar_hash :: Ptr CQQbar -> IO CULong++-- Complex parts ---------------------------------------------------------------++-- | /qqbar_conj/ /res/ /x/ +--+-- Sets /res/ to the complex conjugate of /x/.+foreign import ccall "qqbar.h qqbar_conj"+ qqbar_conj :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_re/ /res/ /x/ +--+-- Sets /res/ to the real part of /x/.+foreign import ccall "qqbar.h qqbar_re"+ qqbar_re :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_im/ /res/ /x/ +--+-- Sets /res/ to the imaginary part of /x/.+foreign import ccall "qqbar.h qqbar_im"+ qqbar_im :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_re_im/ /res1/ /res2/ /x/ +--+-- Sets /res1/ to the real part of /x/ and /res2/ to the imaginary part of+-- /x/.+foreign import ccall "qqbar.h qqbar_re_im"+ qqbar_re_im :: Ptr CQQbar -> Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_abs/ /res/ /x/ +--+-- Sets /res/ to the absolute value of /x/:+foreign import ccall "qqbar.h qqbar_abs"+ qqbar_abs :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_abs2/ /res/ /x/ +--+-- Sets /res/ to the square of the absolute value of /x/.+foreign import ccall "qqbar.h qqbar_abs2"+ qqbar_abs2 :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_sgn/ /res/ /x/ +--+-- Sets /res/ to the complex sign of /x/, defined as 0 if /x/ is zero and+-- as \(x / |x|\) otherwise.+foreign import ccall "qqbar.h qqbar_sgn"+ qqbar_sgn :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_sgn_re/ /x/ +--+-- Returns the sign of the real part of /x/ (-1, 0 or +1).+foreign import ccall "qqbar.h qqbar_sgn_re"+ qqbar_sgn_re :: Ptr CQQbar -> IO CInt++-- | /qqbar_sgn_im/ /x/ +--+-- Returns the sign of the imaginary part of /x/ (-1, 0 or +1).+foreign import ccall "qqbar.h qqbar_sgn_im"+ qqbar_sgn_im :: Ptr CQQbar -> IO CInt++-- | /qqbar_csgn/ /x/ +--+-- Returns the extension of the real sign function taking the value 1 for+-- /x/ strictly in the right half plane, -1 for /x/ strictly in the left+-- half plane, and the sign of the imaginary part when /x/ is on the+-- imaginary axis. Equivalently,+-- \(\operatorname{csgn}(x) = x / \sqrt{x^2}\) except that the value is 0+-- when /x/ is zero.+foreign import ccall "qqbar.h qqbar_csgn"+ qqbar_csgn :: Ptr CQQbar -> IO CInt++-- Integer parts ---------------------------------------------------------------++-- | /qqbar_floor/ /res/ /x/ +--+-- Sets /res/ to the floor function of /x/. If /x/ is not real, the value+-- is defined as the floor function of the real part of /x/.+foreign import ccall "qqbar.h qqbar_floor"+ qqbar_floor :: Ptr CFmpz -> Ptr CQQbar -> IO ()++-- | /qqbar_ceil/ /res/ /x/ +--+-- Sets /res/ to the ceiling function of /x/. If /x/ is not real, the value+-- is defined as the ceiling function of the real part of /x/.+foreign import ccall "qqbar.h qqbar_ceil"+ qqbar_ceil :: Ptr CFmpz -> Ptr CQQbar -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- | /qqbar_neg/ /res/ /x/ +--+-- Sets /res/ to the negation of /x/.+foreign import ccall "qqbar.h qqbar_neg"+ qqbar_neg :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_add/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_add"+ qqbar_add :: Ptr CQQbar -> Ptr CQQbar -> Ptr CQQbar -> IO ()+-- | /qqbar_add_fmpq/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_add_fmpq"+ qqbar_add_fmpq :: Ptr CQQbar -> Ptr CQQbar -> Ptr CFmpq -> IO ()+-- | /qqbar_add_fmpz/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_add_fmpz"+ qqbar_add_fmpz :: Ptr CQQbar -> Ptr CQQbar -> Ptr CFmpz -> IO ()+-- | /qqbar_add_ui/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_add_ui"+ qqbar_add_ui :: Ptr CQQbar -> Ptr CQQbar -> CULong -> IO ()+-- | /qqbar_add_si/ /res/ /x/ /y/ +--+-- Sets /res/ to the sum of /x/ and /y/.+foreign import ccall "qqbar.h qqbar_add_si"+ qqbar_add_si :: Ptr CQQbar -> Ptr CQQbar -> CLong -> IO ()++-- | /qqbar_sub/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_sub"+ qqbar_sub :: Ptr CQQbar -> Ptr CQQbar -> Ptr CQQbar -> IO ()+-- | /qqbar_sub_fmpq/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_sub_fmpq"+ qqbar_sub_fmpq :: Ptr CQQbar -> Ptr CQQbar -> Ptr CFmpq -> IO ()+-- | /qqbar_sub_fmpz/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_sub_fmpz"+ qqbar_sub_fmpz :: Ptr CQQbar -> Ptr CQQbar -> Ptr CFmpz -> IO ()+-- | /qqbar_sub_ui/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_sub_ui"+ qqbar_sub_ui :: Ptr CQQbar -> Ptr CQQbar -> CULong -> IO ()+-- | /qqbar_sub_si/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_sub_si"+ qqbar_sub_si :: Ptr CQQbar -> Ptr CQQbar -> CLong -> IO ()+-- | /qqbar_fmpq_sub/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_fmpq_sub"+ qqbar_fmpq_sub :: Ptr CQQbar -> Ptr CFmpq -> Ptr CQQbar -> IO ()+-- | /qqbar_fmpz_sub/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_fmpz_sub"+ qqbar_fmpz_sub :: Ptr CQQbar -> Ptr CFmpz -> Ptr CQQbar -> IO ()+-- | /qqbar_ui_sub/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_ui_sub"+ qqbar_ui_sub :: Ptr CQQbar -> CULong -> Ptr CQQbar -> IO ()+-- | /qqbar_si_sub/ /res/ /x/ /y/ +--+-- Sets /res/ to the difference of /x/ and /y/.+foreign import ccall "qqbar.h qqbar_si_sub"+ qqbar_si_sub :: Ptr CQQbar -> CLong -> Ptr CQQbar -> IO ()++-- | /qqbar_mul/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_mul"+ qqbar_mul :: Ptr CQQbar -> Ptr CQQbar -> Ptr CQQbar -> IO ()+-- | /qqbar_mul_fmpq/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_mul_fmpq"+ qqbar_mul_fmpq :: Ptr CQQbar -> Ptr CQQbar -> Ptr CFmpq -> IO ()+-- | /qqbar_mul_fmpz/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_mul_fmpz"+ qqbar_mul_fmpz :: Ptr CQQbar -> Ptr CQQbar -> Ptr CFmpz -> IO ()+-- | /qqbar_mul_ui/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_mul_ui"+ qqbar_mul_ui :: Ptr CQQbar -> Ptr CQQbar -> CULong -> IO ()+-- | /qqbar_mul_si/ /res/ /x/ /y/ +--+-- Sets /res/ to the product of /x/ and /y/.+foreign import ccall "qqbar.h qqbar_mul_si"+ qqbar_mul_si :: Ptr CQQbar -> Ptr CQQbar -> CLong -> IO ()++-- | /qqbar_mul_2exp_si/ /res/ /x/ /e/ +--+-- Sets /res/ to /x/ multiplied by \(2^e\).+foreign import ccall "qqbar.h qqbar_mul_2exp_si"+ qqbar_mul_2exp_si :: Ptr CQQbar -> Ptr CQQbar -> CLong -> IO ()++-- | /qqbar_sqr/ /res/ /x/ +--+-- Sets /res/ to the square of /x/.+foreign import ccall "qqbar.h qqbar_sqr"+ qqbar_sqr :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_inv/ /res/ /x/ /y/ +--+-- Sets /res/ to the multiplicative inverse of /y/. Division by zero calls+-- /flint_abort/.+foreign import ccall "qqbar.h qqbar_inv"+ qqbar_inv :: Ptr CQQbar -> Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_div/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_div"+ qqbar_div :: Ptr CQQbar -> Ptr CQQbar -> Ptr CQQbar -> IO ()+-- | /qqbar_div_fmpq/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_div_fmpq"+ qqbar_div_fmpq :: Ptr CQQbar -> Ptr CQQbar -> Ptr CFmpq -> IO ()+-- | /qqbar_div_fmpz/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_div_fmpz"+ qqbar_div_fmpz :: Ptr CQQbar -> Ptr CQQbar -> Ptr CFmpz -> IO ()+-- | /qqbar_div_ui/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_div_ui"+ qqbar_div_ui :: Ptr CQQbar -> Ptr CQQbar -> CULong -> IO ()+-- | /qqbar_div_si/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_div_si"+ qqbar_div_si :: Ptr CQQbar -> Ptr CQQbar -> CLong -> IO ()+-- | /qqbar_fmpq_div/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_fmpq_div"+ qqbar_fmpq_div :: Ptr CQQbar -> Ptr CFmpq -> Ptr CQQbar -> IO ()+-- | /qqbar_fmpz_div/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_fmpz_div"+ qqbar_fmpz_div :: Ptr CQQbar -> Ptr CFmpz -> Ptr CQQbar -> IO ()+-- | /qqbar_ui_div/ /res/ /x/ /y/ +foreign import ccall "qqbar.h qqbar_ui_div"+ qqbar_ui_div :: Ptr CQQbar -> CULong -> Ptr CQQbar -> IO ()+-- | /qqbar_si_div/ /res/ /x/ /y/ +--+-- Sets /res/ to the quotient of /x/ and /y/. Division by zero calls+-- /flint_abort/.+foreign import ccall "qqbar.h qqbar_si_div"+ qqbar_si_div :: Ptr CQQbar -> CLong -> Ptr CQQbar -> IO ()++-- | /qqbar_scalar_op/ /res/ /x/ /a/ /b/ /c/ +--+-- Sets /res/ to the rational affine transformation \((ax+b)/c\), performed+-- as a single operation. There are no restrictions on /a/, /b/ and /c/+-- except that /c/ must be nonzero. Division by zero calls /flint_abort/.+foreign import ccall "qqbar.h qqbar_scalar_op"+ qqbar_scalar_op :: Ptr CQQbar -> Ptr CQQbar -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- Powers and roots ------------------------------------------------------------++-- | /qqbar_sqrt/ /res/ /x/ +foreign import ccall "qqbar.h qqbar_sqrt"+ qqbar_sqrt :: Ptr CQQbar -> Ptr CQQbar -> IO ()+-- | /qqbar_sqrt_ui/ /res/ /x/ +--+-- Sets /res/ to the principal square root of /x/.+foreign import ccall "qqbar.h qqbar_sqrt_ui"+ qqbar_sqrt_ui :: Ptr CQQbar -> CULong -> IO ()++-- | /qqbar_rsqrt/ /res/ /x/ +--+-- Sets /res/ to the reciprocal of the principal square root of /x/.+-- Division by zero calls /flint_abort/.+foreign import ccall "qqbar.h qqbar_rsqrt"+ qqbar_rsqrt :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- | /qqbar_pow_ui/ /res/ /x/ /n/ +foreign import ccall "qqbar.h qqbar_pow_ui"+ qqbar_pow_ui :: Ptr CQQbar -> Ptr CQQbar -> CULong -> IO ()+-- | /qqbar_pow_si/ /res/ /x/ /n/ +foreign import ccall "qqbar.h qqbar_pow_si"+ qqbar_pow_si :: Ptr CQQbar -> Ptr CQQbar -> CULong -> IO ()+-- | /qqbar_pow_fmpz/ /res/ /x/ /n/ +foreign import ccall "qqbar.h qqbar_pow_fmpz"+ qqbar_pow_fmpz :: Ptr CQQbar -> Ptr CQQbar -> Ptr CFmpz -> IO ()+-- | /qqbar_pow_fmpq/ /res/ /x/ /n/ +--+-- Sets /res/ to /x/ raised to the /n/-th power. Raising zero to a negative+-- power aborts.+foreign import ccall "qqbar.h qqbar_pow_fmpq"+ qqbar_pow_fmpq :: Ptr CQQbar -> Ptr CQQbar -> Ptr CFmpq -> IO ()++-- | /qqbar_root_ui/ /res/ /x/ /n/ +foreign import ccall "qqbar.h qqbar_root_ui"+ qqbar_root_ui :: Ptr CQQbar -> Ptr CQQbar -> CULong -> IO ()+-- | /qqbar_fmpq_root_ui/ /res/ /x/ /n/ +--+-- Sets /res/ to the principal /n/-th root of /x/. The order /n/ must be+-- positive.+foreign import ccall "qqbar.h qqbar_fmpq_root_ui"+ qqbar_fmpq_root_ui :: Ptr CQQbar -> Ptr CFmpq -> CULong -> IO ()++-- | /qqbar_fmpq_pow_si_ui/ /res/ /x/ /m/ /n/ +--+-- Sets /res/ to the principal branch of \(x^{m/n}\). The order /n/ must be+-- positive. Division by zero calls /flint_abort/.+foreign import ccall "qqbar.h qqbar_fmpq_pow_si_ui"+ qqbar_fmpq_pow_si_ui :: Ptr CQQbar -> Ptr CFmpq -> CLong -> CULong -> IO ()++-- | /qqbar_pow/ /res/ /x/ /y/ +--+-- General exponentiation: if \(x^y\) is an algebraic number, sets /res/ to+-- this value and returns 1. If \(x^y\) is transcendental or undefined,+-- returns 0. Note that this function returns 0 instead of aborting on+-- division zero.+foreign import ccall "qqbar.h qqbar_pow"+ qqbar_pow :: Ptr CQQbar -> Ptr CQQbar -> Ptr CQQbar -> IO CInt++-- Numerical enclosures --------------------------------------------------------++-- The following functions guarantee a polished output in which both the+-- real and imaginary parts are accurate to /prec/ bits and exact when+-- exactly representable (that is, when a real or imaginary part is a+-- sufficiently small dyadic number). In some cases, the computations+-- needed to polish the output may be expensive. When polish is+-- unnecessary, @qqbar_enclosure_raw@ may be used instead. Alternatively,+-- @qqbar_cache_enclosure@ can be used to avoid recomputations.+--+-- | /qqbar_get_acb/ /res/ /x/ /prec/ +--+-- Sets /res/ to an enclosure of /x/ rounded to /prec/ bits.+foreign import ccall "qqbar.h qqbar_get_acb"+ qqbar_get_acb :: Ptr CAcb -> Ptr CQQbar -> CLong -> IO ()++-- | /qqbar_get_arb/ /res/ /x/ /prec/ +--+-- Sets /res/ to an enclosure of /x/ rounded to /prec/ bits, assuming that+-- /x/ is a real number. If /x/ is not real, /res/ is set to+-- \([\operatorname{NaN} \pm \infty]\).+foreign import ccall "qqbar.h qqbar_get_arb"+ qqbar_get_arb :: Ptr CArb -> Ptr CQQbar -> CLong -> IO ()++-- | /qqbar_get_arb_re/ /res/ /x/ /prec/ +--+-- Sets /res/ to an enclosure of the real part of /x/ rounded to /prec/+-- bits.+foreign import ccall "qqbar.h qqbar_get_arb_re"+ qqbar_get_arb_re :: Ptr CArb -> Ptr CQQbar -> CLong -> IO ()++-- | /qqbar_get_arb_im/ /res/ /x/ /prec/ +--+-- Sets /res/ to an enclosure of the imaginary part of /x/ rounded to+-- /prec/ bits.+foreign import ccall "qqbar.h qqbar_get_arb_im"+ qqbar_get_arb_im :: Ptr CArb -> Ptr CQQbar -> CLong -> IO ()++-- | /qqbar_cache_enclosure/ /res/ /prec/ +--+-- Polishes the internal enclosure of /res/ to at least /prec/ bits of+-- precision in-place. Normally, /qqbar/ operations that need+-- high-precision enclosures compute them on the fly without caching the+-- results; if /res/ will be used as an invariant operand for many+-- operations, calling this function as a precomputation step can improve+-- performance.+foreign import ccall "qqbar.h qqbar_cache_enclosure"+ qqbar_cache_enclosure :: Ptr CQQbar -> CLong -> IO ()++-- Numerator and denominator ---------------------------------------------------++-- | /qqbar_denominator/ /res/ /y/ +--+-- Sets /res/ to the denominator of /y/, i.e. the leading coefficient of+-- the minimal polynomial of /y/.+foreign import ccall "qqbar.h qqbar_denominator"+ qqbar_denominator :: Ptr CFmpz -> Ptr CQQbar -> IO ()++-- | /qqbar_numerator/ /res/ /y/ +--+-- Sets /res/ to the numerator of /y/, i.e. /y/ multiplied by its+-- denominator.+foreign import ccall "qqbar.h qqbar_numerator"+ qqbar_numerator :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- Conjugates ------------------------------------------------------------------++-- | /qqbar_conjugates/ /res/ /x/ +--+-- Sets the entries of the vector /res/ to the /d/ algebraic conjugates of+-- /x/, including /x/ itself, where /d/ is the degree of /x/. The output is+-- sorted in a canonical order (as defined by @qqbar_cmp_root_order@).+foreign import ccall "qqbar.h qqbar_conjugates"+ qqbar_conjugates :: Ptr CQQbar -> Ptr CQQbar -> IO ()++-- Polynomial evaluation -------------------------------------------------------++-- | /_qqbar_evaluate_fmpq_poly/ /res/ /poly/ /den/ /len/ /x/ +foreign import ccall "qqbar.h _qqbar_evaluate_fmpq_poly"+ _qqbar_evaluate_fmpq_poly :: Ptr CQQbar -> Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CQQbar -> IO ()+-- | /qqbar_evaluate_fmpq_poly/ /res/ /poly/ /x/ +foreign import ccall "qqbar.h qqbar_evaluate_fmpq_poly"+ qqbar_evaluate_fmpq_poly :: Ptr CQQbar -> Ptr CFmpqPoly -> Ptr CQQbar -> IO ()+-- | /_qqbar_evaluate_fmpz_poly/ /res/ /poly/ /len/ /x/ +foreign import ccall "qqbar.h _qqbar_evaluate_fmpz_poly"+ _qqbar_evaluate_fmpz_poly :: Ptr CQQbar -> Ptr CFmpz -> CLong -> Ptr CQQbar -> IO ()+-- | /qqbar_evaluate_fmpz_poly/ /res/ /poly/ /x/ +--+-- Sets /res/ to the value of the given polynomial /poly/ evaluated at the+-- algebraic number /x/. These methods detect simple special cases and+-- automatically reduce /poly/ if its degree is greater or equal to that of+-- the minimal polynomial of /x/. In the generic case, evaluation is done+-- by computing minimal polynomials of representation matrices.+foreign import ccall "qqbar.h qqbar_evaluate_fmpz_poly"+ qqbar_evaluate_fmpz_poly :: Ptr CQQbar -> Ptr CFmpzPoly -> Ptr CQQbar -> IO ()++-- | /qqbar_evaluate_fmpz_mpoly_iter/ /res/ /poly/ /x/ /deg_limit/ /bits_limit/ /ctx/ +foreign import ccall "qqbar.h qqbar_evaluate_fmpz_mpoly_iter"+ qqbar_evaluate_fmpz_mpoly_iter :: Ptr CQQbar -> Ptr CFmpzMPoly ->Ptr CQQbar -> CLong -> CLong -> Ptr CFmpzMPolyCtx -> IO CInt+-- | /qqbar_evaluate_fmpz_mpoly_horner/ /res/ /poly/ /x/ /deg_limit/ /bits_limit/ /ctx/ +foreign import ccall "qqbar.h qqbar_evaluate_fmpz_mpoly_horner"+ qqbar_evaluate_fmpz_mpoly_horner :: Ptr CQQbar -> Ptr CFmpzMPoly ->Ptr CQQbar -> CLong -> CLong -> Ptr CFmpzMPolyCtx -> IO CInt+-- | /qqbar_evaluate_fmpz_mpoly/ /res/ /poly/ /x/ /deg_limit/ /bits_limit/ /ctx/ +--+-- Sets /res/ to the value of /poly/ evaluated at the algebraic numbers+-- given in the vector /x/. The number of variables is defined by the+-- context object /ctx/.+-- +-- The parameters /deg_limit/ and /bits_limit/ define evaluation limits: if+-- any temporary result exceeds these limits (not necessarily the final+-- value, in case of cancellation), the evaluation is aborted and 0+-- (failure) is returned. If evaluation succeeds, 1 is returned.+-- +-- The /iter/ version iterates over all terms in succession and computes+-- the powers that appear. The /horner/ version uses a multivariate+-- implementation of the Horner scheme. The default algorithm currently+-- uses the Horner scheme.+foreign import ccall "qqbar.h qqbar_evaluate_fmpz_mpoly"+ qqbar_evaluate_fmpz_mpoly :: Ptr CQQbar -> Ptr CFmpzMPoly ->Ptr CQQbar -> CLong -> CLong -> Ptr CFmpzMPolyCtx -> IO CInt++-- Polynomial roots ------------------------------------------------------------++-- | /qqbar_roots_fmpz_poly/ /res/ /poly/ /flags/ +foreign import ccall "qqbar.h qqbar_roots_fmpz_poly"+ qqbar_roots_fmpz_poly :: Ptr CQQbar -> Ptr CFmpzPoly -> CInt -> IO ()+-- | /qqbar_roots_fmpq_poly/ /res/ /poly/ /flags/ +--+-- Sets the entries of the vector /res/ to the /d/ roots of the polynomial+-- /poly/. Roots with multiplicity appear with repetition in the output+-- array. By default, the roots will be sorted in a convenient canonical+-- order (as defined by @qqbar_cmp_root_order@). Instances of a repeated+-- root always appear consecutively.+-- +-- The following /flags/ are supported:+-- +-- - QQBAR_ROOTS_IRREDUCIBLE - if set, /poly/ is assumed to be+-- irreducible (it may still have constant content), and no polynomial+-- factorization is performed internally.+-- - QQBAR_ROOTS_UNSORTED - if set, the roots will not be guaranteed to+-- be sorted (except for repeated roots being listed consecutively).+foreign import ccall "qqbar.h qqbar_roots_fmpq_poly"+ qqbar_roots_fmpq_poly :: Ptr CQQbar -> Ptr CFmpqPoly -> CInt -> IO ()++-- | /qqbar_eigenvalues_fmpz_mat/ /res/ /mat/ /flags/ +foreign import ccall "qqbar.h qqbar_eigenvalues_fmpz_mat"+ qqbar_eigenvalues_fmpz_mat :: Ptr CQQbar -> Ptr CFmpzMat -> CInt -> IO ()+-- | /qqbar_eigenvalues_fmpq_mat/ /res/ /mat/ /flags/ +--+-- Sets the entries of the vector /res/ to the eigenvalues of the square+-- matrix /mat/. These functions compute the characteristic polynomial of+-- /mat/ and then call @qqbar_roots_fmpz_poly@ with the same flags.+foreign import ccall "qqbar.h qqbar_eigenvalues_fmpq_mat"+ qqbar_eigenvalues_fmpq_mat :: Ptr CQQbar -> Ptr CFmpzMat -> CInt -> IO ()++-- Roots of unity and trigonometric functions ----------------------------------++-- The following functions use word-size integers /p/ and /q/ instead of+-- /fmpq_t/ instances to express rational numbers. This is to emphasize+-- that the computations are feasible only with small /q/ in this+-- representation of algebraic numbers since the associated minimal+-- polynomials have degree \(O(q)\). The input /p/ and /q/ do not need to+-- be reduced /a priori/, but should not be close to the word boundaries+-- (they may be added and subtracted internally).+--+-- | /qqbar_root_of_unity/ /res/ /p/ /q/ +--+-- Sets /res/ to the root of unity \(e^{2 \pi i p / q}\).+foreign import ccall "qqbar.h qqbar_root_of_unity"+ qqbar_root_of_unity :: Ptr CQQbar -> CLong -> CULong -> IO ()++-- | /qqbar_is_root_of_unity/ /p/ /q/ /x/ +--+-- If /x/ is not a root of unity, returns 0. If /x/ is a root of unity,+-- returns 1. If /p/ and /q/ are not /NULL/ and /x/ is a root of unity,+-- this also sets /p/ and /q/ to the minimal integers with \(0 \le p < q\)+-- such that \(x = e^{2 \pi i p / q}\).+foreign import ccall "qqbar.h qqbar_is_root_of_unity"+ qqbar_is_root_of_unity :: Ptr CLong -> Ptr CULong -> Ptr CQQbar -> IO CInt++-- | /qqbar_exp_pi_i/ /res/ /p/ /q/ +--+-- Sets /res/ to the root of unity \(e^{\pi i p / q}\).+foreign import ccall "qqbar.h qqbar_exp_pi_i"+ qqbar_exp_pi_i :: Ptr CQQbar -> CLong -> CULong -> IO ()++-- | /qqbar_cos_pi/ /res/ /p/ /q/ +foreign import ccall "qqbar.h qqbar_cos_pi"+ qqbar_cos_pi :: Ptr CQQbar -> CLong -> CULong -> IO ()+-- | /qqbar_sin_pi/ /res/ /p/ /q/ +foreign import ccall "qqbar.h qqbar_sin_pi"+ qqbar_sin_pi :: Ptr CQQbar -> CLong -> CULong -> IO ()+-- | /qqbar_tan_pi/ /res/ /p/ /q/ +foreign import ccall "qqbar.h qqbar_tan_pi"+ qqbar_tan_pi :: Ptr CQQbar -> CLong -> CULong -> IO CInt+-- | /qqbar_cot_pi/ /res/ /p/ /q/ +foreign import ccall "qqbar.h qqbar_cot_pi"+ qqbar_cot_pi :: Ptr CQQbar -> CLong -> CULong -> IO CInt+-- | /qqbar_sec_pi/ /res/ /p/ /q/ +foreign import ccall "qqbar.h qqbar_sec_pi"+ qqbar_sec_pi :: Ptr CQQbar -> CLong -> CULong -> IO CInt+-- | /qqbar_csc_pi/ /res/ /p/ /q/ +--+-- Sets /res/ to the trigonometric function \(\cos(\pi x)\),+-- \(\sin(\pi x)\), etc., with \(x = \tfrac{p}{q}\). The functions tan,+-- cot, sec and csc return the flag 1 if the value exists, and return 0 if+-- the evaluation point is a pole of the function.+foreign import ccall "qqbar.h qqbar_csc_pi"+ qqbar_csc_pi :: Ptr CQQbar -> CLong -> CULong -> IO CInt++-- | /qqbar_log_pi_i/ /p/ /q/ /x/ +--+-- If \(y = \operatorname{log}(x) / (\pi i)\) is algebraic, and hence+-- necessarily rational, sets \(y = p / q\) to the reduced such fraction+-- with \(-1 < y \le 1\) and returns 1. If /y/ is not algebraic, returns 0.+foreign import ccall "qqbar.h qqbar_log_pi_i"+ qqbar_log_pi_i :: Ptr CLong -> Ptr CULong -> Ptr CQQbar -> IO CInt++-- | /qqbar_atan_pi/ /p/ /q/ /x/ +--+-- If \(y = \operatorname{atan}(x) / \pi\) is algebraic, and hence+-- necessarily rational, sets \(y = p / q\) to the reduced such fraction+-- with \(|y| < \tfrac{1}{2}\) and returns 1. If /y/ is not algebraic,+-- returns 0.+foreign import ccall "qqbar.h qqbar_atan_pi"+ qqbar_atan_pi :: Ptr CLong -> Ptr CULong -> Ptr CQQbar -> IO CInt++-- | /qqbar_asin_pi/ /p/ /q/ /x/ +--+-- If \(y = \operatorname{asin}(x) / \pi\) is algebraic, and hence+-- necessarily rational, sets \(y = p / q\) to the reduced such fraction+-- with \(|y| \le \tfrac{1}{2}\) and returns 1. If /y/ is not algebraic,+-- returns 0.+foreign import ccall "qqbar.h qqbar_asin_pi"+ qqbar_asin_pi :: Ptr CLong -> Ptr CULong -> Ptr CQQbar -> IO CInt++-- | /qqbar_acos_pi/ /p/ /q/ /x/ +--+-- If \(y = \operatorname{acos}(x) / \pi\) is algebraic, and hence+-- necessarily rational, sets \(y = p / q\) to the reduced such fraction+-- with \(0 \le y \le 1\) and returns 1. If /y/ is not algebraic, returns+-- 0.+foreign import ccall "qqbar.h qqbar_acos_pi"+ qqbar_acos_pi :: Ptr CLong -> Ptr CULong -> Ptr CQQbar -> IO CInt++-- | /qqbar_acot_pi/ /p/ /q/ /x/ +--+-- If \(y = \operatorname{acot}(x) / \pi\) is algebraic, and hence+-- necessarily rational, sets \(y = p / q\) to the reduced such fraction+-- with \(-\tfrac{1}{2} < y \le \tfrac{1}{2}\) and returns 1. If /y/ is not+-- algebraic, returns 0.+foreign import ccall "qqbar.h qqbar_acot_pi"+ qqbar_acot_pi :: Ptr CLong -> Ptr CULong -> Ptr CQQbar -> IO CInt++-- | /qqbar_asec_pi/ /p/ /q/ /x/ +--+-- If \(y = \operatorname{asec}(x) / \pi\) is algebraic, and hence+-- necessarily rational, sets \(y = p / q\) to the reduced such fraction+-- with \(0 \le y \le 1\) and returns 1. If /y/ is not algebraic, returns+-- 0.+foreign import ccall "qqbar.h qqbar_asec_pi"+ qqbar_asec_pi :: Ptr CLong -> Ptr CULong -> Ptr CQQbar -> IO CInt++-- | /qqbar_acsc_pi/ /p/ /q/ /x/ +--+-- If \(y = \operatorname{acsc}(x) / \pi\) is algebraic, and hence+-- necessarily rational, sets \(y = p / q\) to the reduced such fraction+-- with \(-\tfrac{1}{2} \le y \le \tfrac{1}{2}\) and returns 1. If /y/ is+-- not algebraic, returns 0.+foreign import ccall "qqbar.h qqbar_acsc_pi"+ qqbar_acsc_pi :: Ptr CLong -> Ptr CULong -> Ptr CQQbar -> IO CInt++-- Guessing and simplification -------------------------------------------------++-- | /qqbar_guess/ /res/ /z/ /max_deg/ /max_bits/ /flags/ /prec/ +--+-- Attempts to find an algebraic number /res/ of degree at most /max_deg/+-- and height at most /max_bits/ bits matching the numerical enclosure /z/.+-- The return flag indicates success. This is only a heuristic method, and+-- the return flag neither implies a rigorous proof that /res/ is the+-- correct result, nor a rigorous proof that no suitable algebraic number+-- with the given /max_deg/ and /max_bits/ exists. (Proof of nonexistence+-- could in principle be computed, but this is not yet implemented.)+-- +-- The working precision /prec/ should normally be the same as the+-- precision used to compute /z/. It does not make much sense to run this+-- algorithm with precision smaller than O(/max_deg/ · /max_bits/).+-- +-- This function does a single iteration at the target /max_deg/,+-- /max_bits/, and /prec/. For best performance, one should invoke this+-- function repeatedly with successively larger parameters when the size of+-- the intended solution is unknown or may be much smaller than a+-- worst-case bound.+foreign import ccall "qqbar.h qqbar_guess"+ qqbar_guess :: Ptr CQQbar -> Ptr CAcb -> CLong -> CLong -> CInt -> CLong -> IO CInt++-- | /qqbar_express_in_field/ /res/ /alpha/ /x/ /max_bits/ /flags/ /prec/ +--+-- Attempts to express /x/ in the number field generated by /alpha/,+-- returning success (0 or 1). On success, /res/ is set to a polynomial /f/+-- of degree less than the degree of /alpha/ and with height (counting both+-- the numerator and the denominator, when the coefficients of /g/ are put+-- on a common denominator) bounded by /max_bits/ bits, such that+-- \(f(\alpha) = x\).+-- +-- (Exception: the /max_bits/ parameter is currently ignored if /x/ is+-- rational, in which case /res/ is just set to the value of /x/.)+-- +-- This function looks for a linear relation heuristically using a working+-- precision of /prec/ bits. If /x/ is expressible in terms of /alpha/,+-- then this function is guaranteed to succeed when /prec/ is taken large+-- enough. The identity \(f(\alpha) = x\) is checked rigorously, i.e. a+-- return value of 1 implies a proof of correctness. In principle, choosing+-- a sufficiently large /prec/ can be used to prove that /x/ does not lie+-- in the field generated by /alpha/, but the present implementation does+-- not support doing so automatically.+-- +-- This function does a single iteration at the target /max_bits/ and and+-- /prec/. For best performance, one should invoke this function repeatedly+-- with successively larger parameters when the size of the intended+-- solution is unknown or may be much smaller than a worst-case bound.+foreign import ccall "qqbar.h qqbar_express_in_field"+ qqbar_express_in_field :: Ptr CFmpqPoly -> Ptr CQQbar -> Ptr CQQbar -> CLong -> CInt -> CLong -> IO CInt++-- Symbolic expressions and conversion to radicals -----------------------------++-- fexptr_t --------------------------------------------------------------------++data FExpr = FExpr {-# UNPACK #-} !(ForeignPtr CFExpr)+type CFExpr = CFlint FExpr++--------------------------------------------------------------------------------++-- | /qqbar_get_quadratic/ /a/ /b/ /c/ /q/ /x/ /factoring/ +--+-- Assuming that /x/ has degree 1 or 2, computes integers /a/, /b/, /c/ and+-- /q/ such that+-- +-- \[`\]+-- \[x = \frac{a + b \sqrt{c}}{q}\]+-- +-- and such that /c/ is not a perfect square, /q/ is positive, and /q/ has+-- no content in common with both /a/ and /b/. In other words, this+-- determines a quadratic field \(\mathbb{Q}(\sqrt{c})\) containing /x/,+-- and then finds the canonical reduced coefficients /a/, /b/ and /q/+-- expressing /x/ in this field. For convenience, this function supports+-- rational /x/, for which /b/ and /c/ will both be set to zero. The+-- following remarks apply to irrationals.+-- +-- The radicand /c/ will not be a perfect square, but will not+-- automatically be squarefree since this would require factoring the+-- discriminant. As a special case, /c/ will be set to \(-1\) if /x/ is a+-- Gaussian rational number. Otherwise, behavior is controlled by the+-- /factoring/ parameter.+-- +-- - If /factoring/ is 0, no factorization is performed apart from+-- removing powers of two.+-- - If /factoring/ is 1, a complete factorization is performed (/c/ will+-- be minimal). This can be very expensive if the discriminant is+-- large.+-- - If /factoring/ is 2, a smooth factorization is performed to remove+-- small factors from /c/. This is a tradeoff that provides pretty+-- output in most cases while avoiding extreme worst-case slowdown. The+-- smooth factorization guarantees finding all small factors (up to+-- some trial division limit determined internally by Flint), but large+-- factors are only found heuristically.+foreign import ccall "qqbar.h qqbar_get_quadratic"+ qqbar_get_quadratic :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CQQbar -> CInt -> IO ()++-- | /qqbar_set_fexpr/ /res/ /expr/ +--+-- Sets /res/ to the algebraic number represented by the symbolic+-- expression /expr/, returning 1 on success and 0 on failure.+-- +-- This function performs a \"static\" evaluation using /qqbar/ arithmetic,+-- supporting only closed-form expressions with explicitly algebraic+-- subexpressions. It can be used to recover values generated by+-- @qqbar_get_expr_formula@ and variants. For evaluating more complex+-- expressions involving other types of values or requiring symbolic+-- simplifications, the user should preprocess /expr/ so that it is in a+-- form which can be parsed by @qqbar_set_fexpr@.+-- +-- The following expressions are supported:+-- +-- - Integer constants+-- - Arithmetic operations with algebraic operands+-- - Square roots of algebraic numbers+-- - Powers with algebraic base and exponent an explicit rational number+-- - NumberI, GoldenRatio, RootOfUnity+-- - Floor, Ceil, Abs, Sign, Csgn, Conjugate, Re, Im, Max, Min+-- - Trigonometric functions with argument an explicit rational number+-- times Pi+-- - Exponentials with argument an explicit rational number times Pi *+-- NumberI+-- - The Decimal() constructor+-- - AlgebraicNumberSerialized() (assuming valid data, which is not+-- checked)+-- - PolynomialRootIndexed()+-- - PolynomialRootNearest()+-- +-- Examples of formulas that are not supported, despite the value being an+-- algebraic number:+-- +-- - @Pi - Pi@ (general transcendental simplifications are not performed)+-- - @1 \/ Infinity@ (only numbers are handled)+-- - @Sum(n, For(n, 1, 10))@ (only static evaluation is performed)+foreign import ccall "qqbar.h qqbar_set_fexpr"+ qqbar_set_fexpr :: Ptr CQQbar -> Ptr CFExpr -> IO CInt++-- | /qqbar_get_fexpr_repr/ /res/ /x/ +--+-- Sets /res/ to a symbolic expression reflecting the exact internal+-- representation of /x/. The output will have the form+-- @AlgebraicNumberSerialized(List(coeffs), enclosure)@. The output can be+-- converted back to a @qqbar_t@ value using @qqbar_set_fexpr@. This is the+-- recommended format for serializing algebraic numbers as it requires+-- minimal computation, but it has the disadvantage of not being+-- human-readable.+foreign import ccall "qqbar.h qqbar_get_fexpr_repr"+ qqbar_get_fexpr_repr :: Ptr CFExpr -> Ptr CQQbar -> IO ()++-- | /qqbar_get_fexpr_root_nearest/ /res/ /x/ +--+-- Sets /res/ to a symbolic expression unambiguously describing /x/ in the+-- form @PolynomialRootNearest(List(coeffs), point)@ where /point/ is an+-- approximation of /x/ guaranteed to be closer to /x/ than any conjugate+-- root. The output can be converted back to a @qqbar_t@ value using+-- @qqbar_set_fexpr@. This is a useful format for human-readable+-- presentation, but serialization and deserialization can be expensive.+foreign import ccall "qqbar.h qqbar_get_fexpr_root_nearest"+ qqbar_get_fexpr_root_nearest :: Ptr CFExpr -> Ptr CQQbar -> IO ()++-- | /qqbar_get_fexpr_root_indexed/ /res/ /x/ +--+-- Sets /res/ to a symbolic expression unambiguously describing /x/ in the+-- form @PolynomialRootIndexed(List(coeffs), index)@ where /index/ is the+-- index of /x/ among its conjugate roots in the builtin root sort order.+-- The output can be converted back to a @qqbar_t@ value using+-- @qqbar_set_fexpr@. This is a useful format for human-readable+-- presentation when the numerical value is important, but serialization+-- and deserialization can be expensive.+foreign import ccall "qqbar.h qqbar_get_fexpr_root_indexed"+ qqbar_get_fexpr_root_indexed :: Ptr CFExpr -> Ptr CQQbar -> IO ()++-- | /qqbar_get_fexpr_formula/ /res/ /x/ /flags/ +--+-- Attempts to express the algebraic number /x/ as a closed-form expression+-- using arithmetic operations, radicals, and possibly exponentials or+-- trigonometric functions, but without using @PolynomialRootNearest@ or+-- @PolynomialRootIndexed@. Returns 0 on failure and 1 on success.+-- +-- The /flags/ parameter toggles different methods for generating formulas.+-- It can be set to any combination of the following. If /flags/ is 0, only+-- rational numbers will be handled.+-- +-- QQBAR_FORMULA_ALL+-- +-- Toggles all methods (potentially expensive).+-- +-- QQBAR_FORMULA_GAUSSIANS+-- +-- Detect Gaussian rational numbers \(a + bi\).+-- +-- QQBAR_FORMULA_QUADRATICS+-- +-- Solve quadratics in the form \(a + b \sqrt{d}\).+-- +-- QQBAR_FORMULA_CYCLOTOMICS+-- +-- Detect elements of cyclotomic fields. This works by trying plausible+-- cyclotomic fields (based on the degree of the input), using LLL to find+-- candidate number field elements, and certifying candidates through an+-- exact computation. Detection is heuristic and is not guaranteed to find+-- all cyclotomic numbers.+-- +-- QQBAR_FORMULA_CUBICS QQBAR_FORMULA_QUARTICS QQBAR_FORMULA_QUINTICS+-- +-- Solve polynomials of degree 3, 4 and (where applicable) 5 using cubic,+-- quartic and quintic formulas (not yet implemented).+-- +-- QQBAR_FORMULA_DEPRESSION+-- +-- Use depression to try to generate simpler numbers.+-- +-- QQBAR_FORMULA_DEFLATION+-- +-- Use deflation to try to generate simpler numbers. This allows handling+-- number of the form \(a^{1/n}\) where /a/ can be represented in closed+-- form.+-- +-- QQBAR_FORMULA_SEPARATION+-- +-- Try separating real and imaginary parts or sign and magnitude of complex+-- numbers. This allows handling numbers of the form \(a + bi\) or+-- \(m \cdot s\) (with \(m > 0, |s| = 1\)) where /a/ and /b/ or /m/ and /s/+-- can be represented in closed form. This is only attempted as a fallback+-- after other methods fail: if an explicit Cartesian or magnitude-sign+-- represented is desired, the user should manually separate the number+-- into complex parts before calling @qqbar_get_fexpr_formula@.+-- +-- QQBAR_FORMULA_EXP_FORM QQBAR_FORMULA_TRIG_FORM+-- QQBAR_FORMULA_RADICAL_FORM QQBAR_FORMULA_AUTO_FORM+-- +-- Select output form for cyclotomic numbers. The /auto/ form (equivalent+-- to no flags being set) results in radicals for numbers of low degree,+-- trigonometric functions for real numbers, and complex exponentials for+-- nonreal numbers. The other flags (not fully implemented) can be used to+-- force exponential form, trigonometric form, or radical form.+foreign import ccall "qqbar.h qqbar_get_fexpr_formula"+ qqbar_get_fexpr_formula :: Ptr CFExpr -> Ptr CQQbar -> CULong -> IO CInt++-- Internal functions ----------------------------------------------------------++-- | /qqbar_fmpz_poly_composed_op/ /res/ /A/ /B/ /op/ +--+-- Given nonconstant polynomials /A/ and /B/, sets /res/ to a polynomial+-- whose roots are \(a+b\), \(a-b\), \(ab\) or \(a/b\) for all roots /a/ of+-- /A/ and all roots /b/ of /B/. The parameter /op/ selects the arithmetic+-- operation: 0 for addition, 1 for subtraction, 2 for multiplication and 3+-- for division. If /op/ is 3, /B/ must not have zero as a root.+foreign import ccall "qqbar.h qqbar_fmpz_poly_composed_op"+ qqbar_fmpz_poly_composed_op :: Ptr CFmpzPoly -> Ptr CFmpzPoly -> Ptr CFmpzPoly -> CInt -> IO ()++-- | /qqbar_binary_op/ /res/ /x/ /y/ /op/ +--+-- Performs a binary operation using a generic algorithm. This does not+-- check for special cases.+foreign import ccall "qqbar.h qqbar_binary_op"+ qqbar_binary_op :: Ptr CQQbar -> Ptr CQQbar -> Ptr CQQbar -> CInt -> IO ()++-- | /_qqbar_validate_uniqueness/ /res/ /poly/ /z/ /max_prec/ +--+-- Given /z/ known to be an enclosure of at least one root of /poly/,+-- certifies that the enclosure contains a unique root, and in that case+-- sets /res/ to a new (possibly improved) enclosure for the same root,+-- returning 1. Returns 0 if uniqueness cannot be certified.+-- +-- The enclosure is validated by performing a single step with the interval+-- Newton method. The working precision is determined from the accuracy of+-- /z/, but limited by /max_prec/ bits.+-- +-- This method slightly inflates the enclosure /z/ to improve the chances+-- that the interval Newton step will succeed. Uniqueness on this larger+-- interval implies uniqueness of the original interval, but not existence;+-- when existence has not been ensured a priori,+-- @_qqbar_validate_existence_uniqueness@ should be used instead.+foreign import ccall "qqbar.h _qqbar_validate_uniqueness"+ _qqbar_validate_uniqueness :: Ptr CAcb -> Ptr CFmpzPoly -> Ptr CAcb -> CLong -> IO CInt++-- | /_qqbar_validate_existence_uniqueness/ /res/ /poly/ /z/ /max_prec/ +--+-- Given any complex interval /z/, certifies that the enclosure contains a+-- unique root of /poly/, and in that case sets /res/ to a new (possibly+-- improved) enclosure for the same root, returning 1. Returns 0 if+-- existence and uniqueness cannot be certified.+-- +-- The enclosure is validated by performing a single step with the interval+-- Newton method. The working precision is determined from the accuracy of+-- /z/, but limited by /max_prec/ bits.+foreign import ccall "qqbar.h _qqbar_validate_existence_uniqueness"+ _qqbar_validate_existence_uniqueness :: Ptr CAcb -> Ptr CFmpzPoly -> Ptr CAcb -> CLong -> IO CInt++-- | /_qqbar_enclosure_raw/ /res/ /poly/ /z/ /prec/ +foreign import ccall "qqbar.h _qqbar_enclosure_raw"+ _qqbar_enclosure_raw :: Ptr CAcb -> Ptr CFmpzPoly -> Ptr CAcb -> CLong -> IO ()+-- | /qqbar_enclosure_raw/ /res/ /x/ /prec/ +--+-- Sets /res/ to an enclosure of /x/ accurate to about /prec/ bits (the+-- actual accuracy can be slightly lower, or higher).+-- +-- This function uses repeated interval Newton steps to polish the initial+-- enclosure /z/, doubling the working precision each time. If any step+-- fails to improve the accuracy significantly, the root is recomputed from+-- scratch to higher precision.+-- +-- If the initial enclosure is accurate enough, /res/ is set to this value+-- without rounding and without further computation.+foreign import ccall "qqbar.h qqbar_enclosure_raw"+ qqbar_enclosure_raw :: Ptr CAcb -> Ptr CQQbar -> CLong -> IO ()++-- | /_qqbar_acb_lindep/ /rel/ /vec/ /len/ /check/ /prec/ +--+-- Attempts to find an integer vector /rel/ giving a linear relation+-- between the elements of the real or complex vector /vec/, using the LLL+-- algorithm.+-- +-- The working precision is set to the minimum of /prec/ and the relative+-- accuracy of /vec/ (that is, the difference between the largest magnitude+-- and the largest error magnitude within /vec/). 95% of the bits within+-- the working precision are used for the LLL matrix, and the remaining 5%+-- bits are used to validate the linear relation by evaluating the linear+-- combination and checking that the resulting interval contains zero. This+-- validation does not prove the existence or nonexistence of a linear+-- relation, but it provides a quick heuristic way to eliminate spurious+-- relations.+-- +-- If /check/ is set, the return value indicates whether the validation was+-- successful; otherwise, the return value simply indicates whether the+-- algorithm was executed normally (failure may occur, for example, if the+-- input vector is non-finite).+-- +-- In principle, this method can be used to produce a proof that no linear+-- relation exists with coefficients up to a specified bit size, but this+-- has not yet been implemented.+foreign import ccall "qqbar.h _qqbar_acb_lindep"+ _qqbar_acb_lindep :: Ptr CFmpz -> Ptr CAcb -> CLong -> CInt -> CLong -> IO CInt++++
+ src/Data/Number/Flint/NF/QQbar/Instances.hs view
@@ -0,0 +1,50 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.NF.QQbar.Instances where++import System.IO.Unsafe+import Foreign.C.String+import Foreign.Marshal.Alloc ( free )++import Data.Number.Flint.NF.QQbar++instance Show QQbar where+ show x = unsafePerformIO $ do+ (_, cs) <- withQQbar x qqbar_get_str+ s <- peekCString cs+ free cs+ return s++instance Eq QQbar where+ (==) x y = snd $ snd $ unsafePerformIO $ + withQQbar x $ \x ->+ withQQbar y $ \y -> do+ result <- qqbar_equal x y+ return $ result == 1++instance Num QQbar where+ {-# INLINE (+) #-}+ (+) = lift2 qqbar_add+ {-# INLINE (-) #-}+ (-) = lift2 qqbar_sub+ {-# INLINE (*) #-}+ (*) = lift2 qqbar_mul+ negate = lift1 qqbar_neg+ abs = undefined+ fromInteger x = unsafePerformIO $ do+ result <- newQQbar+ withQQbar result $ \result -> do+ qqbar_set_si result (fromInteger x)+ return result+ signum = undefined++lift1 f x = fst $ unsafePerformIO $ + withNewQQbar $ \result -> + withQQbar x $ \x ->+ f result x+ +lift2 f x y = fst $ unsafePerformIO $ + withNewQQbar $ \result ->+ withQQbar x $ \x ->+ withQQbar y $ \y ->+ f result x y+
+ src/Data/Number/Flint/NMod.hs view
@@ -0,0 +1,12 @@+{-|+module : Data.Number.Flint.NMod+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.NMod (+ module Data.Number.Flint.NMod.FFI+) where++import Data.Number.Flint.NMod.FFI
+ src/Data/Number/Flint/NMod/FFI.hsc view
@@ -0,0 +1,214 @@+{-|+module : Data.Number.Flint.NMod.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NMod.FFI (+ -- * Integers mod n (word-size n)+ NMod (..)+ , CNMod (..)+ -- * Memory management+ , newNMod+ , withNMod+ , withNewNMod+ , nmod_init+ -- * Modular reduction and arithmetic+ , _nmod_add+ , nmod_add+ , _nmod_sub+ , nmod_sub+ , nmod_neg+ , nmod_mul+ , _nmod_mul_fullword+ , nmod_inv+ , nmod_div+ , nmod_pow_ui+ -- * Discrete Logarithms via Pohlig-Hellman+ , NModDiscreteLogPohligHellman (..)+ , CNModDiscreteLogPohligHellman (..)+ , nmod_discrete_log_pohlig_hellman_init+ , nmod_discrete_log_pohlig_hellman_clear+ , nmod_discrete_log_pohlig_hellman_precompute_prime+ , nmod_discrete_log_pohlig_hellman_primitive_root+ , nmod_discrete_log_pohlig_hellman_run+) where ++-- integers mod n (word-size n) ------------------------------------------------++import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, nullPtr )+import Foreign.Storable++import Data.Number.Flint.Flint++#include <flint/nmod.h>++-- NMod ------------------------------------------------------------------------++data NMod = NMod {-# UNPACK #-} !(ForeignPtr CNMod)+data CNMod = CNMod CMpLimb CMpLimb CFBitCnt++instance Storable CNMod where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_t}+ peek ptr = return CNMod + <*> #{peek nmod_t, n } ptr+ <*> #{peek nmod_t, ninv} ptr+ <*> #{peek nmod_t, norm} ptr+ poke = error "CNMod.poke: Not defined"++instance Show CNMod where+ show (CNMod n ninv norm) = show n++-- NModDiscreteLogPohligHellman ------------------------------------------------++data NModDiscreteLogPohligHellman =+ NModDiscreteLogPohligHellman !(ForeignPtr CNModDiscreteLogPohligHellman)+type CNModDiscreteLogPohligHellman = CFlint NModDiscreteLogPohligHellman++instance Storable CNModDiscreteLogPohligHellman where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_discrete_log_pohlig_hellman_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_discrete_log_pohlig_hellman_t}+ peek ptr = error "CNModDiscreteLogPohligHellman poke: Not defined"+ poke = error "CNMod.poke: Not defined"++-- Modular reduction and arithmetic --------------------------------------------++-- | Create a new `NMod` structure+newNMod n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> nmod_init x n+ return $ NMod x++-- | Use `NMod` structure+{-# INLINE withNMod #-}+withNMod (NMod x) f = do+ withForeignPtr x $ \xp -> f xp >>= return . (NMod x,)++withNewNMod n f = do+ x <- newNMod n+ withNMod x $ \x -> f x++--------------------------------------------------------------------------------++-- | /nmod_init/ /mod/ /n/ +-- +-- Initialises the given @nmod_t@ structure for reduction modulo \(n\) with+-- a precomputed inverse.+foreign import ccall "nmod.h nmod_init"+ nmod_init :: Ptr CNMod -> CMpLimb -> IO ()++-- | /_nmod_add/ /a/ /b/ /mod/ +-- +-- Returns \(a + b\) modulo @mod.n@. It is assumed that @mod@ is no more+-- than @FLINT_BITS - 1@ bits. It is assumed that \(a\) and \(b\) are+-- already reduced modulo @mod.n@.+foreign import ccall "nmod.h _nmod_add"+ _nmod_add :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb++-- | /nmod_add/ /a/ /b/ /mod/ +-- +-- Returns \(a + b\) modulo @mod.n@. No assumptions are made about @mod.n@.+-- It is assumed that \(a\) and \(b\) are already reduced modulo @mod.n@.+foreign import ccall "nmod.h nmod_add"+ nmod_add :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb++-- | /_nmod_sub/ /a/ /b/ /mod/ +-- +-- Returns \(a - b\) modulo @mod.n@. It is assumed that @mod@ is no more+-- than @FLINT_BITS - 1@ bits. It is assumed that \(a\) and \(b\) are+-- already reduced modulo @mod.n@.+foreign import ccall "nmod.h _nmod_sub"+ _nmod_sub :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb++-- | /nmod_sub/ /a/ /b/ /mod/ +-- +-- Returns \(a - b\) modulo @mod.n@. No assumptions are made about @mod.n@.+-- It is assumed that \(a\) and \(b\) are already reduced modulo @mod.n@.+foreign import ccall "nmod.h nmod_sub"+ nmod_sub :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb++-- | /nmod_neg/ /a/ /mod/ +-- +-- Returns \(-a\) modulo @mod.n@. It is assumed that \(a\) is already+-- reduced modulo @mod.n@, but no assumptions are made about the latter.+foreign import ccall "nmod.h nmod_neg"+ nmod_neg :: CMpLimb -> Ptr CNMod -> IO CMpLimb++-- | /nmod_mul/ /a/ /b/ /mod/ +-- +-- Returns \(ab\) modulo @mod.n@. No assumptions are made about @mod.n@. It+-- is assumed that \(a\) and \(b\) are already reduced modulo @mod.n@.+foreign import ccall "nmod.h nmod_mul"+ nmod_mul :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb++-- | /_nmod_mul_fullword/ /a/ /b/ /mod/ +-- +-- Returns \(ab\) modulo @mod.n@. Requires that @mod.n@ is exactly+-- @FLINT_BITS@ large. It is assumed that \(a\) and \(b\) are already+-- reduced modulo @mod.n@.+foreign import ccall "nmod.h _nmod_mul_fullword"+ _nmod_mul_fullword :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb++-- | /nmod_inv/ /a/ /mod/ +-- +-- Returns \(a^{-1}\) modulo @mod.n@. The inverse is assumed to exist.+foreign import ccall "nmod.h nmod_inv"+ nmod_inv :: CMpLimb -> Ptr CNMod -> IO CMpLimb++-- | /nmod_div/ /a/ /b/ /mod/ +-- +-- Returns \(ab^{-1}\) modulo @mod.n@. The inverse of \(b\) is assumed to+-- exist. It is assumed that \(a\) is already reduced modulo @mod.n@.+foreign import ccall "nmod.h nmod_div"+ nmod_div :: CMpLimb -> CMpLimb -> Ptr CNMod -> IO CMpLimb++-- | /nmod_pow_ui/ /a/ /e/ /mod/ +-- +-- Returns \(a^e\) modulo @mod.n@. No assumptions are made about @mod.n@.+-- It is assumed that \(a\) is already reduced modulo @mod.n@.+foreign import ccall "nmod.h nmod_pow_ui"+ nmod_pow_ui :: CMpLimb -> CULong -> Ptr CNMod -> IO CMpLimb++-- Discrete Logarithms via Pohlig-Hellman --------------------------------------++-- | /nmod_discrete_log_pohlig_hellman_init/ /L/ +-- +-- Initialize @L@. Upon initialization @L@ is not ready for computation.+foreign import ccall "nmod.h nmod_discrete_log_pohlig_hellman_init"+ nmod_discrete_log_pohlig_hellman_init :: Ptr CNModDiscreteLogPohligHellman -> IO ()++-- | /nmod_discrete_log_pohlig_hellman_clear/ /L/ +-- +-- Free any space used by @L@.+foreign import ccall "nmod.h nmod_discrete_log_pohlig_hellman_clear"+ nmod_discrete_log_pohlig_hellman_clear :: Ptr CNModDiscreteLogPohligHellman -> IO ()++-- | /nmod_discrete_log_pohlig_hellman_precompute_prime/ /L/ /p/ +-- +-- Configure @L@ for discrete logarithms modulo @p@ to an internally chosen+-- base. It is assumed that @p@ is prime. The return is an estimate on the+-- number of multiplications needed for one run.+foreign import ccall "nmod.h nmod_discrete_log_pohlig_hellman_precompute_prime"+ nmod_discrete_log_pohlig_hellman_precompute_prime :: Ptr CNModDiscreteLogPohligHellman -> CMpLimb -> IO CDouble++-- | /nmod_discrete_log_pohlig_hellman_primitive_root/ /L/ +-- +-- Return the internally stored base.+foreign import ccall "nmod.h nmod_discrete_log_pohlig_hellman_primitive_root"+ nmod_discrete_log_pohlig_hellman_primitive_root :: Ptr CNModDiscreteLogPohligHellman -> IO CMpLimb++-- | /nmod_discrete_log_pohlig_hellman_run/ /L/ /y/ +-- +-- Return the logarithm of @y@ with respect to the internally stored base.+-- @y@ is expected to be reduced modulo the @p@. The function is undefined+-- if the logarithm does not exist.+foreign import ccall "nmod.h nmod_discrete_log_pohlig_hellman_run"+ nmod_discrete_log_pohlig_hellman_run :: Ptr CNModDiscreteLogPohligHellman -> CMpLimb -> IO CULong+
+ src/Data/Number/Flint/NMod/MPoly.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.NMod.MPoly (+ module Data.Number.Flint.NMod.MPoly.FFI+ ) where++import Data.Number.Flint.NMod.MPoly.FFI
+ src/Data/Number/Flint/NMod/MPoly/FFI.hsc view
@@ -0,0 +1,1161 @@+{-|+module : Data.Number.Flint.NMod.MPoly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NMod.MPoly.FFI (+ -- * Multivariate polynomials over integers mod n (word-size n)+ NModMPoly (..)+ , CNModMPoly (..)+ , newNModMPoly+ , withNModMPoly+ -- * Context object+ , NModMPolyCtx (..)+ , CNModMPolyCtx (..)+ , newNModMPolyCtx+ , withNModMPolyCtx+ , nmod_mpoly_ctx_init+ , nmod_mpoly_ctx_nvars+ , nmod_mpoly_ctx_ord+ , nmod_mpoly_ctx_modulus+ , nmod_mpoly_ctx_clear+ -- * Memory management+ , nmod_mpoly_init+ , nmod_mpoly_init2+ , nmod_mpoly_init3+ , nmod_mpoly_fit_length+ , nmod_mpoly_realloc+ , nmod_mpoly_clear+ -- * Input\/Output+ , nmod_mpoly_get_str_pretty+ , nmod_mpoly_fprint_pretty+ , nmod_mpoly_print_pretty+ , nmod_mpoly_set_str_pretty+ -- * Basic manipulation+ , nmod_mpoly_gen+ , nmod_mpoly_is_gen+ , nmod_mpoly_set+ , nmod_mpoly_equal+ , nmod_mpoly_swap+ -- * Constants+ , nmod_mpoly_is_ui+ , nmod_mpoly_get_ui+ , nmod_mpoly_set_ui+ , nmod_mpoly_zero+ , nmod_mpoly_one+ , nmod_mpoly_equal_ui+ , nmod_mpoly_is_zero+ , nmod_mpoly_is_one+ -- * Degrees+ , nmod_mpoly_degrees_fit_si+ , nmod_mpoly_degrees_fmpz+ , nmod_mpoly_degrees_si+ , nmod_mpoly_degree_fmpz+ , nmod_mpoly_degree_si+ , nmod_mpoly_total_degree_fits_si+ , nmod_mpoly_total_degree_fmpz+ , nmod_mpoly_total_degree_si+ , nmod_mpoly_used_vars+ -- * Coefficients+ , nmod_mpoly_get_coeff_ui_monomial+ , nmod_mpoly_set_coeff_ui_monomial+ , nmod_mpoly_get_coeff_ui_fmpz+ , nmod_mpoly_get_coeff_ui_ui+ , nmod_mpoly_set_coeff_ui_fmpz+ , nmod_mpoly_set_coeff_ui_ui+ , nmod_mpoly_get_coeff_vars_ui+ -- * Comparison+ , nmod_mpoly_cmp+ -- * Container operations+ , nmod_mpoly_term_coeff_ref+ , nmod_mpoly_is_canonical+ , nmod_mpoly_length+ , nmod_mpoly_resize+ , nmod_mpoly_get_term_coeff_ui+ , nmod_mpoly_set_term_coeff_ui+ , nmod_mpoly_term_exp_fits_si+ , nmod_mpoly_term_exp_fits_ui+ , nmod_mpoly_get_term_exp_fmpz+ , nmod_mpoly_get_term_exp_ui+ , nmod_mpoly_get_term_exp_si+ , nmod_mpoly_get_term_var_exp_ui+ , nmod_mpoly_get_term_var_exp_si+ , nmod_mpoly_set_term_exp_fmpz+ , nmod_mpoly_set_term_exp_ui+ , nmod_mpoly_get_term+ , nmod_mpoly_get_term_monomial+ , nmod_mpoly_push_term_ui_fmpz+ , nmod_mpoly_push_term_ui_ui+ , nmod_mpoly_sort_terms+ , nmod_mpoly_combine_like_terms+ , nmod_mpoly_reverse+ -- * Random generation+ , nmod_mpoly_randtest_bound+ , nmod_mpoly_randtest_bounds+ , nmod_mpoly_randtest_bits+ -- * Addition\/Subtraction+ , nmod_mpoly_add_ui+ , nmod_mpoly_sub_ui+ , nmod_mpoly_add+ , nmod_mpoly_sub+ -- * Scalar operations+ , nmod_mpoly_neg+ , nmod_mpoly_scalar_mul_ui+ , nmod_mpoly_make_monic+ -- * Differentiation+ , nmod_mpoly_derivative+ -- * Evaluation+ , nmod_mpoly_evaluate_all_ui+ , nmod_mpoly_evaluate_one_ui+ , nmod_mpoly_compose_nmod_poly+ , nmod_mpoly_compose_nmod_mpoly_geobucket+ , nmod_mpoly_compose_nmod_mpoly_horner+ , nmod_mpoly_compose_nmod_mpoly+ , nmod_mpoly_compose_nmod_mpoly_gen+ -- * Multiplication+ , nmod_mpoly_mul+ , nmod_mpoly_mul_johnson+ , nmod_mpoly_mul_heap_threaded+ , nmod_mpoly_mul_array+ , nmod_mpoly_mul_array_threaded+ , nmod_mpoly_mul_dense+ -- * Powering+ , nmod_mpoly_pow_fmpz+ , nmod_mpoly_pow_ui+ -- * Division+ , nmod_mpoly_divides+ , nmod_mpoly_div+ , nmod_mpoly_divrem+ , nmod_mpoly_divrem_ideal+ , nmod_mpoly_divides_dense+ , nmod_mpoly_divides_monagan_pearce+ , nmod_mpoly_divides_heap_threaded+ -- * Greatest Common Divisor+ , nmod_mpoly_term_content+ , nmod_mpoly_content_vars+ , nmod_mpoly_gcd+ , nmod_mpoly_gcd_cofactors+ , nmod_mpoly_gcd_brown+ , nmod_mpoly_gcd_hensel+ , nmod_mpoly_gcd_zippel+ , nmod_mpoly_resultant+ , nmod_mpoly_discriminant+ -- * Square Root+ , nmod_mpoly_sqrt+ , nmod_mpoly_is_square+ , nmod_mpoly_quadratic_root+ -- * Univariate Functions+ , nmod_mpoly_univar_init+ , nmod_mpoly_univar_clear+ , nmod_mpoly_univar_swap+ , nmod_mpoly_to_univar+ , nmod_mpoly_from_univar+ , nmod_mpoly_univar_degree_fits_si+ , nmod_mpoly_univar_length+ , nmod_mpoly_univar_get_term_exp_si+ , nmod_mpoly_univar_get_term_coeff+ , nmod_mpoly_univar_swap_term_coeff+ -- * Internal Functions+ , nmod_mpoly_pow_rmul+ , nmod_mpoly_div_monagan_pearce+ , nmod_mpoly_divrem_monagan_pearce+ , nmod_mpoly_divrem_ideal_monagan_pearce+) where++-- Multivariate polynomials over integers mod n (word-size n) ------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.MPoly+import Data.Number.Flint.NMod+import Data.Number.Flint.NMod.Types++#include <flint/flint.h>+#include <flint/nmod.h>+#include <flint/nmod_poly.h>+#include <flint/nmod_mpoly.h>++-- nmod_mpoly_t ----------------------------------------------------------------++data NModMPoly = NModMPoly {-# UNPACK #-} !(ForeignPtr CNModMPoly)+data CNModMPoly = CNModMPoly ++instance Storable CNModMPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_mpoly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_mpoly_t}+ peek = error "CNModMPoly.peek: Not defined"+ poke = error "CNModMPoly.poke: Not defined"++-- | Create a new `NModMPoly`+newNModMPoly ctx@(NModMPolyCtx pctx) = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withNModMPolyCtx ctx $ \ctx -> do + nmod_mpoly_init p ctx+ addForeignPtrFinalizerEnv p_nmod_mpoly_clear p pctx + return $ NModMPoly p++{-# INLINE withNModMPoly #-}+withNModMPoly (NModMPoly p) f = do+ withForeignPtr p $ \fp -> (NModMPoly p,) <$> f fp++-- nmod_mpoly_univar_t ---------------------------------------------------------++data NModMPolyUnivar = NModMPolyUnivar {-# UNPACK #-} !(ForeignPtr CNModMPolyUnivar)+data CNModMPolyUnivar = CNModMPolyUnivar ++instance Storable CNModMPolyUnivar where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_mpoly_univar_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_mpoly_univar_t}+ peek = error "CNModMPolyUnivar.peek: Not defined"+ poke = error "CNModMPolyUnivar.poke: Not defined"++-- | Create a new `NModMPolyUnivar`+newNModMPolyUnivar ctx@(NModMPolyCtx pctx) = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withNModMPolyCtx ctx $ \ctx -> do + nmod_mpoly_univar_init p ctx+ addForeignPtrFinalizerEnv p_nmod_mpoly_univar_clear p pctx+ return $ NModMPolyUnivar p++{-# INLINE withNModMPolyUnivar #-}+withNModMPolyUnivar (NModMPolyUnivar p) f = do+ withForeignPtr p $ \fp -> (NModMPolyUnivar p,) <$> f fp++-- nmod_mpoly_ctx_t ------------------------------------------------------------++data NModMPolyCtx = NModMPolyCtx {-# UNPACK #-} !(ForeignPtr CNModMPolyCtx)+data CNModMPolyCtx++instance Storable CNModMPolyCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_mpoly_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_mpoly_ctx_t}+ peek = error "CNModMPolyCtx.peek: Not defined"+ poke = error "CNModMPolyCtx.poke: Not defined"++-- | Create a new `NModMPolyCtx`+newNModMPolyCtx nvars ord n = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ nmod_mpoly_ctx_init p nvars ord n+ addForeignPtrFinalizer p_nmod_mpoly_ctx_clear p+ return $ NModMPolyCtx p++-- | Use a `NModMPolyCtx`+{-# INLINE withNModMPolyCtx #-}+withNModMPolyCtx (NModMPolyCtx p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (NModMPolyCtx p,)++-- Context object --------------------------------------------------------------++-- | /nmod_mpoly_ctx_init/ /ctx/ /nvars/ /ord/ /n/ +--+-- Initialise a context object for a polynomial ring with the given number+-- of variables and the given ordering. It will have coefficients modulo+-- /n/. Setting \(n = 0\) will give undefined behavior. The possibilities+-- for the ordering are @ORD_LEX@, @ORD_DEGLEX@ and @ORD_DEGREVLEX@.+foreign import ccall "nmod_mpoly.h nmod_mpoly_ctx_init"+ nmod_mpoly_ctx_init :: Ptr CNModMPolyCtx -> CLong -> Ptr COrdering -> CMpLimb -> IO ()++-- | /nmod_mpoly_ctx_nvars/ /ctx/ +--+-- Return the number of variables used to initialize the context.+foreign import ccall "nmod_mpoly.h nmod_mpoly_ctx_nvars"+ nmod_mpoly_ctx_nvars :: Ptr CNModMPolyCtx -> IO CLong++-- | /nmod_mpoly_ctx_ord/ /ctx/ +--+-- Return the ordering used to initialize the context.+foreign import ccall "nmod_mpoly.h nmod_mpoly_ctx_ord"+ nmod_mpoly_ctx_ord :: Ptr CNModMPolyCtx -> IO (Ptr COrdering)++-- | /nmod_mpoly_ctx_modulus/ /ctx/ +--+-- Return the modulus used to initialize the context.+foreign import ccall "nmod_mpoly.h nmod_mpoly_ctx_modulus"+ nmod_mpoly_ctx_modulus :: Ptr CNModMPolyCtx -> IO CMpLimb++-- | /nmod_mpoly_ctx_clear/ /ctx/ +--+-- Release any space allocated by /ctx/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_ctx_clear"+ nmod_mpoly_ctx_clear :: Ptr CNModMPolyCtx -> IO ()++foreign import ccall "nmod_mpoly.h &nmod_mpoly_ctx_clear"+ p_nmod_mpoly_ctx_clear :: FunPtr (Ptr CNModMPolyCtx -> IO ())++-- Memory management -----------------------------------------------------------++-- | /nmod_mpoly_init/ /A/ /ctx/ +--+-- Initialise /A/ for use with the given an initialised context object. Its+-- value is set to zero.+foreign import ccall "nmod_mpoly.h nmod_mpoly_init"+ nmod_mpoly_init :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_init2/ /A/ /alloc/ /ctx/ +--+-- Initialise /A/ for use with the given an initialised context object. Its+-- value is set to zero. It is allocated with space for /alloc/ terms and+-- at least @MPOLY_MIN_BITS@ bits for the exponent widths.+foreign import ccall "nmod_mpoly.h nmod_mpoly_init2"+ nmod_mpoly_init2 :: Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_init3/ /A/ /alloc/ /bits/ /ctx/ +--+-- Initialise /A/ for use with the given an initialised context object. Its+-- value is set to zero. It is allocated with space for /alloc/ terms and+-- /bits/ bits for the exponents.+foreign import ccall "nmod_mpoly.h nmod_mpoly_init3"+ nmod_mpoly_init3 :: Ptr CNModMPoly -> CLong -> CFBitCnt -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_fit_length/ /A/ /len/ /ctx/ +--+-- Ensure that /A/ has space for at least /len/ terms.+foreign import ccall "nmod_mpoly.h nmod_mpoly_fit_length"+ nmod_mpoly_fit_length :: Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_realloc/ /A/ /alloc/ /ctx/ +--+-- Reallocate /A/ to have space for /alloc/ terms. Assumes the current+-- length of the polynomial is not greater than /alloc/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_realloc"+ nmod_mpoly_realloc :: Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_clear/ /A/ /ctx/ +--+-- Release any space allocated for /A/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_clear"+ nmod_mpoly_clear :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++foreign import ccall "nmod_mpoly.h &nmod_mpoly_clear"+ p_nmod_mpoly_clear :: FunPtr (Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ())++-- Input\/Output ---------------------------------------------------------------++-- | /nmod_mpoly_get_str_pretty/ /A/ /x/ /ctx/ +--+-- Return a string, which the user is responsible for cleaning up,+-- representing /A/, given an array of variable strings /x/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_get_str_pretty"+ nmod_mpoly_get_str_pretty :: Ptr CNModMPoly -> Ptr (Ptr CChar) -> Ptr CNModMPolyCtx -> IO CString++-- | /nmod_mpoly_fprint_pretty/ /file/ /A/ /x/ /ctx/ +--+-- Print a string representing /A/ to /file/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_fprint_pretty"+ nmod_mpoly_fprint_pretty :: Ptr CFile -> Ptr CNModMPoly -> Ptr (Ptr CChar) -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_print_pretty/ /A/ /x/ /ctx/ +--+-- Print a string representing /A/ to @stdout@.+nmod_mpoly_print_pretty :: Ptr CNModMPoly+ -> Ptr (Ptr CChar)+ -> Ptr CNModMPolyCtx+ -> IO CInt+nmod_mpoly_print_pretty a x ctx =+ printCStr (\a -> nmod_mpoly_get_str_pretty a x ctx) a++-- | /nmod_mpoly_set_str_pretty/ /A/ /str/ /x/ /ctx/ +--+-- Set /A/ to the polynomial in the null-terminates string /str/ given an+-- array /x/ of variable strings. If parsing /str/ fails, /A/ is set to+-- zero, and \(-1\) is returned. Otherwise, \(0\) is returned. The+-- operations @+@, @-@, @*@, and @\/@ are permitted along with integers and+-- the variables in /x/. The character @^@ must be immediately followed by+-- the (integer) exponent. If any division is not exact, parsing fails.+foreign import ccall "nmod_mpoly.h nmod_mpoly_set_str_pretty"+ nmod_mpoly_set_str_pretty :: Ptr CNModMPoly -> CString -> Ptr (Ptr CChar) -> Ptr CNModMPolyCtx -> IO CInt++-- Basic manipulation ----------------------------------------------------------++-- | /nmod_mpoly_gen/ /A/ /var/ /ctx/ +--+-- Set /A/ to the variable of index /var/, where \(var = 0\) corresponds to+-- the variable with the most significance with respect to the ordering.+foreign import ccall "nmod_mpoly.h nmod_mpoly_gen"+ nmod_mpoly_gen :: Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_is_gen/ /A/ /var/ /ctx/ +--+-- If \(var \ge 0\), return \(1\) if /A/ is equal to the \(var\)-th+-- generator, otherwise return \(0\). If \(var < 0\), return \(1\) if the+-- polynomial is equal to any generator, otherwise return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_is_gen"+ nmod_mpoly_is_gen :: Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_set/ /A/ /B/ /ctx/ +--+-- Set /A/ to /B/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_set"+ nmod_mpoly_set :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_equal/ /A/ /B/ /ctx/ +--+-- Return \(1\) if /A/ is equal to /B/, else return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_equal"+ nmod_mpoly_equal :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_swap/ /A/ /B/ /ctx/ +--+-- Efficiently swap /A/ and /B/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_swap"+ nmod_mpoly_swap :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- Constants -------------------------------------------------------------------++-- | /nmod_mpoly_is_ui/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is a constant, else return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_is_ui"+ nmod_mpoly_is_ui :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_get_ui/ /A/ /ctx/ +--+-- Assuming that /A/ is a constant, return this constant. This function+-- throws if /A/ is not a constant.+foreign import ccall "nmod_mpoly.h nmod_mpoly_get_ui"+ nmod_mpoly_get_ui :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CULong++-- | /nmod_mpoly_set_ui/ /A/ /c/ /ctx/ +--+-- Set /A/ to the constant /c/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_set_ui"+ nmod_mpoly_set_ui :: Ptr CNModMPoly -> CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_zero/ /A/ /ctx/ +--+-- Set /A/ to the constant \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_zero"+ nmod_mpoly_zero :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_one/ /A/ /ctx/ +--+-- Set /A/ to the constant \(1\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_one"+ nmod_mpoly_one :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_equal_ui/ /A/ /c/ /ctx/ +--+-- Return \(1\) if /A/ is equal to the constant /c/, else return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_equal_ui"+ nmod_mpoly_equal_ui :: Ptr CNModMPoly -> CULong -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_is_zero/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is the constant \(0\), else return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_is_zero"+ nmod_mpoly_is_zero :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_is_one/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is the constant \(1\), else return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_is_one"+ nmod_mpoly_is_one :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- Degrees ---------------------------------------------------------------------++-- | /nmod_mpoly_degrees_fit_si/ /A/ /ctx/ +--+-- Return \(1\) if the degrees of /A/ with respect to each variable fit+-- into an @slong@, otherwise return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_degrees_fit_si"+ nmod_mpoly_degrees_fit_si :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_degrees_fmpz/ /degs/ /A/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_degrees_fmpz"+ nmod_mpoly_degrees_fmpz :: Ptr (Ptr CFmpz) -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()+-- | /nmod_mpoly_degrees_si/ /degs/ /A/ /ctx/ +--+-- Set /degs/ to the degrees of /A/ with respect to each variable. If /A/+-- is zero, all degrees are set to \(-1\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_degrees_si"+ nmod_mpoly_degrees_si :: Ptr CLong -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_degree_fmpz/ /deg/ /A/ /var/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_degree_fmpz"+ nmod_mpoly_degree_fmpz :: Ptr CFmpz -> Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()+-- | /nmod_mpoly_degree_si/ /A/ /var/ /ctx/ +--+-- Either return or set /deg/ to the degree of /A/ with respect to the+-- variable of index /var/. If /A/ is zero, the degree is defined to be+-- \(-1\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_degree_si"+ nmod_mpoly_degree_si :: Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO CLong++-- | /nmod_mpoly_total_degree_fits_si/ /A/ /ctx/ +--+-- Return \(1\) if the total degree of /A/ fits into an @slong@, otherwise+-- return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_total_degree_fits_si"+ nmod_mpoly_total_degree_fits_si :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_total_degree_fmpz/ /tdeg/ /A/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_total_degree_fmpz"+ nmod_mpoly_total_degree_fmpz :: Ptr CFmpz -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()+-- | /nmod_mpoly_total_degree_si/ /A/ /ctx/ +--+-- Either return or set /tdeg/ to the total degree of /A/. If /A/ is zero,+-- the total degree is defined to be \(-1\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_total_degree_si"+ nmod_mpoly_total_degree_si :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CLong++-- | /nmod_mpoly_used_vars/ /used/ /A/ /ctx/ +--+-- For each variable index /i/, set @used[i]@ to nonzero if the variable of+-- index /i/ appears in /A/ and to zero otherwise.+foreign import ccall "nmod_mpoly.h nmod_mpoly_used_vars"+ nmod_mpoly_used_vars :: Ptr CInt -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- Coefficients ----------------------------------------------------------------++-- | /nmod_mpoly_get_coeff_ui_monomial/ /A/ /M/ /ctx/ +--+-- Assuming that /M/ is a monomial, return the coefficient of the+-- corresponding monomial in /A/. This function throws if /M/ is not a+-- monomial.+foreign import ccall "nmod_mpoly.h nmod_mpoly_get_coeff_ui_monomial"+ nmod_mpoly_get_coeff_ui_monomial :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CULong++-- | /nmod_mpoly_set_coeff_ui_monomial/ /A/ /c/ /M/ /ctx/ +--+-- Assuming that /M/ is a monomial, set the coefficient of the+-- corresponding monomial in /A/ to /c/. This function throws if /M/ is not+-- a monomial.+foreign import ccall "nmod_mpoly.h nmod_mpoly_set_coeff_ui_monomial"+ nmod_mpoly_set_coeff_ui_monomial :: Ptr CNModMPoly -> CULong -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_get_coeff_ui_fmpz/ /A/ /exp/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_get_coeff_ui_fmpz"+ nmod_mpoly_get_coeff_ui_fmpz :: Ptr CNModMPoly -> Ptr (Ptr CFmpz) -> Ptr CNModMPolyCtx -> IO CULong+-- | /nmod_mpoly_get_coeff_ui_ui/ /A/ /exp/ /ctx/ +--+-- Return the coefficient of the monomial with exponent /exp/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_get_coeff_ui_ui"+ nmod_mpoly_get_coeff_ui_ui :: Ptr CNModMPoly -> Ptr CULong -> Ptr CNModMPolyCtx -> IO CULong++-- | /nmod_mpoly_set_coeff_ui_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_set_coeff_ui_fmpz"+ nmod_mpoly_set_coeff_ui_fmpz :: Ptr CNModMPoly -> CULong -> Ptr (Ptr CFmpz) -> Ptr CNModMPolyCtx -> IO ()+-- | /nmod_mpoly_set_coeff_ui_ui/ /A/ /c/ /exp/ /ctx/ +--+-- Set the coefficient of the monomial with exponent /exp/ to \(c\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_set_coeff_ui_ui"+ nmod_mpoly_set_coeff_ui_ui :: Ptr CNModMPoly -> CULong -> Ptr CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_get_coeff_vars_ui/ /C/ /A/ /vars/ /exps/ /length/ /ctx/ +--+-- Set /C/ to the coefficient of /A/ with respect to the variables in+-- /vars/ with powers in the corresponding array /exps/. Both /vars/ and+-- /exps/ point to array of length /length/. It is assumed that+-- @0 \< length \\le nvars(A)@ and that the variables in /vars/ are+-- distinct.+foreign import ccall "nmod_mpoly.h nmod_mpoly_get_coeff_vars_ui"+ nmod_mpoly_get_coeff_vars_ui :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CLong -> Ptr CULong -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /nmod_mpoly_cmp/ /A/ /B/ /ctx/ +--+-- Return \(1\) (resp. \(-1\), or \(0\)) if /A/ is after (resp. before,+-- same as) /B/ in some arbitrary but fixed total ordering of the+-- polynomials. This ordering agrees with the usual ordering of monomials+-- when /A/ and /B/ are both monomials.+foreign import ccall "nmod_mpoly.h nmod_mpoly_cmp"+ nmod_mpoly_cmp :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- Container operations --------------------------------------------------------++-- | /nmod_mpoly_term_coeff_ref/ /A/ /i/ /ctx/ +--+-- Return a reference to the coefficient of index /i/ of /A/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_term_coeff_ref"+ nmod_mpoly_term_coeff_ref :: Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO (Ptr CMpLimb)++-- | /nmod_mpoly_is_canonical/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is in canonical form. Otherwise, return \(0\). To be+-- in canonical form, all of the terms must have nonzero coefficients, and+-- the terms must be sorted from greatest to least.+foreign import ccall "nmod_mpoly.h nmod_mpoly_is_canonical"+ nmod_mpoly_is_canonical :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_length/ /A/ /ctx/ +--+-- Return the number of terms in /A/. If the polynomial is in canonical+-- form, this will be the number of nonzero coefficients.+foreign import ccall "nmod_mpoly.h nmod_mpoly_length"+ nmod_mpoly_length :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CLong++-- | /nmod_mpoly_resize/ /A/ /new_length/ /ctx/ +--+-- Set the length of /A/ to @new_length@. Terms are either deleted from the+-- end, or new zero terms are appended.+foreign import ccall "nmod_mpoly.h nmod_mpoly_resize"+ nmod_mpoly_resize :: Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_get_term_coeff_ui/ /A/ /i/ /ctx/ +--+-- Return the coefficient of the term of index /i/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_get_term_coeff_ui"+ nmod_mpoly_get_term_coeff_ui :: Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO CULong++-- | /nmod_mpoly_set_term_coeff_ui/ /A/ /i/ /c/ /ctx/ +--+-- Set the coefficient of the term of index /i/ to /c/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_set_term_coeff_ui"+ nmod_mpoly_set_term_coeff_ui :: Ptr CNModMPoly -> CLong -> CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_term_exp_fits_si/ /A/ /i/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_term_exp_fits_si"+ nmod_mpoly_term_exp_fits_si :: Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO CInt+-- | /nmod_mpoly_term_exp_fits_ui/ /A/ /i/ /ctx/ +--+-- Return \(1\) if all entries of the exponent vector of the term of index+-- /i/ fit into an @slong@ (resp. a @ulong@). Otherwise, return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_term_exp_fits_ui"+ nmod_mpoly_term_exp_fits_ui :: Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_get_term_exp_fmpz/ /exp/ /A/ /i/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_get_term_exp_fmpz"+ nmod_mpoly_get_term_exp_fmpz :: Ptr (Ptr CFmpz) -> Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()+-- | /nmod_mpoly_get_term_exp_ui/ /exp/ /A/ /i/ /ctx/ +--+foreign import ccall "nmod_mpoly.h nmod_mpoly_get_term_exp_ui"+ nmod_mpoly_get_term_exp_ui :: Ptr CULong -> Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_get_term_exp_si/ /exp/ /A/ /i/ /ctx/ +--+-- Set /exp/ to the exponent vector of the term of index /i/. The @_ui@+-- (resp. @_si@) version throws if any entry does not fit into a @ulong@+-- (resp. @slong@).+foreign import ccall "nmod_mpoly.h nmod_mpoly_get_term_exp_si"+ nmod_mpoly_get_term_exp_si :: Ptr CLong -> Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_get_term_var_exp_ui/ /A/ /i/ /var/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_get_term_var_exp_ui"+ nmod_mpoly_get_term_var_exp_ui :: Ptr CNModMPoly -> CLong -> CLong -> Ptr CNModMPolyCtx -> IO CULong+-- | /nmod_mpoly_get_term_var_exp_si/ /A/ /i/ /var/ /ctx/ +--+-- Return the exponent of the variable /var/ of the term of index /i/. This+-- function throws if the exponent does not fit into a @ulong@ (resp.+-- @slong@).+foreign import ccall "nmod_mpoly.h nmod_mpoly_get_term_var_exp_si"+ nmod_mpoly_get_term_var_exp_si :: Ptr CNModMPoly -> CLong -> CLong -> Ptr CNModMPolyCtx -> IO CLong++-- | /nmod_mpoly_set_term_exp_fmpz/ /A/ /i/ /exp/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_set_term_exp_fmpz"+ nmod_mpoly_set_term_exp_fmpz :: Ptr CNModMPoly -> CLong -> Ptr (Ptr CFmpz) -> Ptr CNModMPolyCtx -> IO ()+-- | /nmod_mpoly_set_term_exp_ui/ /A/ /i/ /exp/ /ctx/ +--+-- Set the exponent of the term of index /i/ to /exp/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_set_term_exp_ui"+ nmod_mpoly_set_term_exp_ui :: Ptr CNModMPoly -> CLong -> Ptr CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_get_term/ /M/ /A/ /i/ /ctx/ +--+-- Set /M/ to the term of index /i/ in /A/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_get_term"+ nmod_mpoly_get_term :: Ptr CNModMPoly -> Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_get_term_monomial/ /M/ /A/ /i/ /ctx/ +--+-- Set /M/ to the monomial of the term of index /i/ in /A/. The coefficient+-- of /M/ will be one.+foreign import ccall "nmod_mpoly.h nmod_mpoly_get_term_monomial"+ nmod_mpoly_get_term_monomial :: Ptr CNModMPoly -> Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_push_term_ui_fmpz/ /A/ /c/ /exp/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_push_term_ui_fmpz"+ nmod_mpoly_push_term_ui_fmpz :: Ptr CNModMPoly -> CULong -> Ptr (Ptr CFmpz) -> Ptr CNModMPolyCtx -> IO ()+-- | /nmod_mpoly_push_term_ui_ui/ /A/ /c/ /exp/ /ctx/ +--+-- Append a term to /A/ with coefficient /c/ and exponent vector /exp/.+-- This function runs in constant average time.+foreign import ccall "nmod_mpoly.h nmod_mpoly_push_term_ui_ui"+ nmod_mpoly_push_term_ui_ui :: Ptr CNModMPoly -> CULong -> Ptr CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_sort_terms/ /A/ /ctx/ +--+-- Sort the terms of /A/ into the canonical ordering dictated by the+-- ordering in /ctx/. This function simply reorders the terms: It does not+-- combine like terms, nor does it delete terms with coefficient zero. This+-- function runs in linear time in the bit size of /A/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_sort_terms"+ nmod_mpoly_sort_terms :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_combine_like_terms/ /A/ /ctx/ +--+-- Combine adjacent like terms in /A/ and delete terms with coefficient+-- zero. If the terms of /A/ were sorted to begin with, the result will be+-- in canonical form. This function runs in linear time in the bit size of+-- /A/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_combine_like_terms"+ nmod_mpoly_combine_like_terms :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_reverse/ /A/ /B/ /ctx/ +--+-- Set /A/ to the reversal of /B/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_reverse"+ nmod_mpoly_reverse :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- Random generation -----------------------------------------------------------++-- | /nmod_mpoly_randtest_bound/ /A/ /state/ /length/ /exp_bound/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents in+-- the range @[0, exp_bound - 1]@. The exponents of each variable are+-- generated by calls to @n_randint(state, exp_bound)@.+foreign import ccall "nmod_mpoly.h nmod_mpoly_randtest_bound"+ nmod_mpoly_randtest_bound :: Ptr CNModMPoly -> Ptr CFRandState -> CLong -> CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_randtest_bounds/ /A/ /state/ /length/ /exp_bounds/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents in+-- the range @[0, exp_bounds[i] - 1]@. The exponents of the variable of+-- index /i/ are generated by calls to @n_randint(state, exp_bounds[i])@.+foreign import ccall "nmod_mpoly.h nmod_mpoly_randtest_bounds"+ nmod_mpoly_randtest_bounds :: Ptr CNModMPoly -> Ptr CFRandState -> CLong -> CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_randtest_bits/ /A/ /state/ /length/ /exp_bits/ /ctx/ +--+-- Generate a random polynomial with length up to /length/ and exponents+-- whose packed form does not exceed the given bit count.+foreign import ccall "nmod_mpoly.h nmod_mpoly_randtest_bits"+ nmod_mpoly_randtest_bits :: Ptr CNModMPoly -> Ptr CFRandState -> CLong -> CMpLimb -> Ptr CNModMPolyCtx -> IO ()++-- Addition\/Subtraction -------------------------------------------------------++-- | /nmod_mpoly_add_ui/ /A/ /B/ /c/ /ctx/ +--+-- Set /A/ to \(B + c\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_add_ui"+ nmod_mpoly_add_ui :: Ptr CNModMPoly -> Ptr CNModMPoly -> CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_sub_ui/ /A/ /B/ /c/ /ctx/ +--+-- Set /A/ to \(B - c\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_sub_ui"+ nmod_mpoly_sub_ui :: Ptr CNModMPoly -> Ptr CNModMPoly -> CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_add/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B + C\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_add"+ nmod_mpoly_add :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_sub/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B - C\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_sub"+ nmod_mpoly_sub :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- Scalar operations -----------------------------------------------------------++-- | /nmod_mpoly_neg/ /A/ /B/ /ctx/ +--+-- Set /A/ to \(-B\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_neg"+ nmod_mpoly_neg :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_scalar_mul_ui/ /A/ /B/ /c/ /ctx/ +--+-- Set /A/ to \(B \times c\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_scalar_mul_ui"+ nmod_mpoly_scalar_mul_ui :: Ptr CNModMPoly -> Ptr CNModMPoly -> CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_make_monic/ /A/ /B/ /ctx/ +--+-- Set /A/ to /B/ divided by the leading coefficient of /B/. This throws if+-- /B/ is zero or the leading coefficient is not invertible.+foreign import ccall "nmod_mpoly.h nmod_mpoly_make_monic"+ nmod_mpoly_make_monic :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- Differentiation -------------------------------------------------------------++-- | /nmod_mpoly_derivative/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to the derivative of /B/ with respect to the variable of index+-- /var/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_derivative"+ nmod_mpoly_derivative :: Ptr CNModMPoly -> Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- Evaluation ------------------------------------------------------------------++-- | /nmod_mpoly_evaluate_all_ui/ /A/ /vals/ /ctx/ +--+-- Return the evaluation of /A/ where the variables are replaced by the+-- corresponding elements of the array /vals/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_evaluate_all_ui"+ nmod_mpoly_evaluate_all_ui :: Ptr CNModMPoly -> Ptr CULong -> Ptr CNModMPolyCtx -> IO CULong++-- | /nmod_mpoly_evaluate_one_ui/ /A/ /B/ /var/ /val/ /ctx/ +--+-- Set /A/ to the evaluation of /B/ where the variable of index /var/ is+-- replaced by /val/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_evaluate_one_ui"+ nmod_mpoly_evaluate_one_ui :: Ptr CNModMPoly -> Ptr CNModMPoly -> CULong -> CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_compose_nmod_poly/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to the evaluation of /B/ where the variables are replaced by the+-- corresponding elements of the array /C/. The context object of /B/ is+-- /ctxB/. Return \(1\) for success and \(0\) for failure.+foreign import ccall "nmod_mpoly.h nmod_mpoly_compose_nmod_poly"+ nmod_mpoly_compose_nmod_poly :: Ptr CNModPoly -> Ptr CNModMPoly -> Ptr (Ptr (Ptr CNModPoly)) -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_compose_nmod_mpoly_geobucket/ /A/ /B/ /C/ /ctxB/ /ctxAC/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_compose_nmod_mpoly_geobucket"+ nmod_mpoly_compose_nmod_mpoly_geobucket :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr (Ptr (Ptr CNModMPoly)) -> Ptr CNModMPolyCtx -> Ptr CNModMPolyCtx -> IO CInt+-- | /nmod_mpoly_compose_nmod_mpoly_horner/ /A/ /B/ /C/ /ctxB/ /ctxAC/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_compose_nmod_mpoly_horner"+ nmod_mpoly_compose_nmod_mpoly_horner :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr (Ptr (Ptr CNModMPoly)) -> Ptr CNModMPolyCtx -> Ptr CNModMPolyCtx -> IO CInt+-- | /nmod_mpoly_compose_nmod_mpoly/ /A/ /B/ /C/ /ctxB/ /ctxAC/ +--+-- Set /A/ to the evaluation of /B/ where the variables are replaced by the+-- corresponding elements of the array /C/. Both /A/ and the elements of+-- /C/ have context object /ctxAC/, while /B/ has context object /ctxB/.+-- Neither of /A/ and /B/ is allowed to alias any other polynomial. Return+-- \(1\) for success and \(0\) for failure. The main method attempts to+-- perform the calculation using matrices and chooses heuristically between+-- the @geobucket@ and @horner@ methods if needed.+foreign import ccall "nmod_mpoly.h nmod_mpoly_compose_nmod_mpoly"+ nmod_mpoly_compose_nmod_mpoly :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr (Ptr (Ptr CNModMPoly)) -> Ptr CNModMPolyCtx -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_compose_nmod_mpoly_gen/ /A/ /B/ /c/ /ctxB/ /ctxAC/ +--+-- Set /A/ to the evaluation of /B/ where the variable of index /i/ in+-- /ctxB/ is replaced by the variable of index @c[i]@ in /ctxAC/. The+-- length of the array /C/ is the number of variables in /ctxB/. If any+-- @c[i]@ is negative, the corresponding variable of /B/ is replaced by+-- zero. Otherwise, it is expected that @c[i]@ is less than the number of+-- variables in /ctxAC/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_compose_nmod_mpoly_gen"+ nmod_mpoly_compose_nmod_mpoly_gen :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CLong -> Ptr CNModMPolyCtx -> Ptr CNModMPolyCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /nmod_mpoly_mul/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B \times C\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_mul"+ nmod_mpoly_mul :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_mul_johnson/ /A/ /B/ /C/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_mul_johnson"+ nmod_mpoly_mul_johnson :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()+-- | /nmod_mpoly_mul_heap_threaded/ /A/ /B/ /C/ /ctx/ +--+-- Set /A/ to \(B \times C\) using Johnson\'s heap-based method. The first+-- version always uses one thread.+foreign import ccall "nmod_mpoly.h nmod_mpoly_mul_heap_threaded"+ nmod_mpoly_mul_heap_threaded :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_mul_array/ /A/ /B/ /C/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_mul_array"+ nmod_mpoly_mul_array :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt+-- | /nmod_mpoly_mul_array_threaded/ /A/ /B/ /C/ /ctx/ +--+-- Try to set /A/ to \(B \times C\) using arrays. If the return is \(0\),+-- the operation was unsuccessful. Otherwise, it was successful, and the+-- return is \(1\). The first version always uses one thread.+foreign import ccall "nmod_mpoly.h nmod_mpoly_mul_array_threaded"+ nmod_mpoly_mul_array_threaded :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_mul_dense/ /A/ /B/ /C/ /ctx/ +--+-- Try to set /A/ to \(B \times C\) using univariate arithmetic. If the+-- return is \(0\), the operation was unsuccessful. Otherwise, it was+-- successful and the return is \(1\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_mul_dense"+ nmod_mpoly_mul_dense :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- Powering --------------------------------------------------------------------+++++-- | /nmod_mpoly_pow_fmpz/ /A/ /B/ /k/ /ctx/ +--+-- Set /A/ to /B/ raised to the /k/-th power. Return \(1\) for success and+-- \(0\) for failure.+foreign import ccall "nmod_mpoly.h nmod_mpoly_pow_fmpz"+ nmod_mpoly_pow_fmpz :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CFmpz -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_pow_ui/ /A/ /B/ /k/ /ctx/ +--+-- Set /A/ to /B/ raised to the /k/-th power. Return \(1\) for success and+-- \(0\) for failure.+foreign import ccall "nmod_mpoly.h nmod_mpoly_pow_ui"+ nmod_mpoly_pow_ui :: Ptr CNModMPoly -> Ptr CNModMPoly -> CULong -> Ptr CNModMPolyCtx -> IO CInt++-- Division --------------------------------------------------------------------++-- The division functions assume that the modulus is prime.+--+-- | /nmod_mpoly_divides/ /Q/ /A/ /B/ /ctx/ +--+-- If /A/ is divisible by /B/, set /Q/ to the exact quotient and return+-- \(1\). Otherwise, set /Q/ to zero and return \(0\). Note that the+-- function @nmod_mpoly_div@ below may be faster if the quotient is known+-- to be exact.+foreign import ccall "nmod_mpoly.h nmod_mpoly_divides"+ nmod_mpoly_divides :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_div/ /Q/ /A/ /B/ /ctx/ +--+-- Set /Q/ to the quotient of /A/ by /B/, discarding the remainder.+foreign import ccall "nmod_mpoly.h nmod_mpoly_div"+ nmod_mpoly_div :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_divrem/ /Q/ /R/ /A/ /B/ /ctx/ +--+-- Set /Q/ and /R/ to the quotient and remainder of /A/ divided by /B/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_divrem"+ nmod_mpoly_divrem :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_divrem_ideal/ /Q/ /R/ /A/ /B/ /len/ /ctx/ +--+-- This function is as per @nmod_mpoly_divrem@ except that it takes an+-- array of divisor polynomials /B/ and it returns an array of quotient+-- polynomials /Q/. The number of divisor (and hence quotient) polynomials,+-- is given by /len/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_divrem_ideal"+ nmod_mpoly_divrem_ideal :: Ptr (Ptr (Ptr CNModMPoly)) -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr (Ptr (Ptr CNModMPoly)) -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_divides_dense/ /Q/ /A/ /B/ /ctx/ +--+-- Try to do the operation of @nmod_mpoly_divides@ using univariate+-- arithmetic. If the return is \(-1\), the operation was unsuccessful.+-- Otherwise, it was successful and the return is \(0\) or \(1\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_divides_dense"+ nmod_mpoly_divides_dense :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_divides_monagan_pearce/ /Q/ /A/ /B/ /ctx/ +--+-- Do the operation of @nmod_mpoly_divides@ using the algorithm of Michael+-- Monagan and Roman Pearce.+foreign import ccall "nmod_mpoly.h nmod_mpoly_divides_monagan_pearce"+ nmod_mpoly_divides_monagan_pearce :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_divides_heap_threaded/ /Q/ /A/ /B/ /ctx/ +--+-- Do the operation of @nmod_mpoly_divides@ using a heap and multiple+-- threads. This function should only be called once @global_thread_pool@+-- has been initialized.+foreign import ccall "nmod_mpoly.h nmod_mpoly_divides_heap_threaded"+ nmod_mpoly_divides_heap_threaded :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- Greatest Common Divisor -----------------------------------------------------++-- The greatest common divisor functions assume that the modulus is prime.+--+-- | /nmod_mpoly_term_content/ /M/ /A/ /ctx/ +--+-- Set /M/ to the GCD of the terms of /A/. If /A/ is zero, /M/ will be+-- zero. Otherwise, /M/ will be a monomial with coefficient one.+foreign import ccall "nmod_mpoly.h nmod_mpoly_term_content"+ nmod_mpoly_term_content :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_content_vars/ /g/ /A/ /vars/ /vars_length/ /ctx/ +--+-- Set /g/ to the GCD of the coefficients of /A/ when viewed as a+-- polynomial in the variables /vars/. Return \(1\) for success and \(0\)+-- for failure. Upon success, /g/ will be independent of the variables+-- /vars/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_content_vars"+ nmod_mpoly_content_vars :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CLong -> CLong -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_gcd/ /G/ /A/ /B/ /ctx/ +--+-- Try to set /G/ to the monic GCD of /A/ and /B/. The GCD of zero and zero+-- is defined to be zero. If the return is \(1\) the function was+-- successful. Otherwise the return is \(0\) and /G/ is left untouched.+foreign import ccall "nmod_mpoly.h nmod_mpoly_gcd"+ nmod_mpoly_gcd :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_gcd_cofactors/ /G/ /Abar/ /Bbar/ /A/ /B/ /ctx/ +--+-- Do the operation of @nmod_mpoly_gcd@ and also compute \(Abar = A/G\) and+-- \(Bbar = B/G\) if successful.+foreign import ccall "nmod_mpoly.h nmod_mpoly_gcd_cofactors"+ nmod_mpoly_gcd_cofactors :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_gcd_brown/ /G/ /A/ /B/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_gcd_brown"+ nmod_mpoly_gcd_brown :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt+-- | /nmod_mpoly_gcd_hensel/ /G/ /A/ /B/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_gcd_hensel"+ nmod_mpoly_gcd_hensel :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt+-- | /nmod_mpoly_gcd_zippel/ /G/ /A/ /B/ /ctx/ +--+-- Try to set /G/ to the GCD of /A/ and /B/ using various algorithms.+foreign import ccall "nmod_mpoly.h nmod_mpoly_gcd_zippel"+ nmod_mpoly_gcd_zippel :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_resultant/ /R/ /A/ /B/ /var/ /ctx/ +--+-- Try to set /R/ to the resultant of /A/ and /B/ with respect to the+-- variable of index /var/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_resultant"+ nmod_mpoly_resultant :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_discriminant/ /D/ /A/ /var/ /ctx/ +--+-- Try to set /D/ to the discriminant of /A/ with respect to the variable+-- of index /var/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_discriminant"+ nmod_mpoly_discriminant :: Ptr CNModMPoly -> Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO CInt++-- Square Root -----------------------------------------------------------------++-- The square root functions assume that the modulus is prime for correct+-- operation.+--+-- | /nmod_mpoly_sqrt/ /Q/ /A/ /ctx/ +--+-- If \(Q^2=A\) has a solution, set /Q/ to a solution and return \(1\),+-- otherwise return \(0\) and set /Q/ to zero.+foreign import ccall "nmod_mpoly.h nmod_mpoly_sqrt"+ nmod_mpoly_sqrt :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_is_square/ /A/ /ctx/ +--+-- Return \(1\) if /A/ is a perfect square, otherwise return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_is_square"+ nmod_mpoly_is_square :: Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_quadratic_root/ /Q/ /A/ /B/ /ctx/ +--+-- If \(Q^2+AQ=B\) has a solution, set /Q/ to a solution and return \(1\),+-- otherwise return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_quadratic_root"+ nmod_mpoly_quadratic_root :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- Univariate Functions --------------------------------------------------------++-- | /nmod_mpoly_univar_init/ /A/ /ctx/ +--+-- Initialize /A/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_univar_init"+ nmod_mpoly_univar_init :: Ptr CNModMPolyUnivar -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_univar_clear/ /A/ /ctx/ +--+-- Clear /A/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_univar_clear"+ nmod_mpoly_univar_clear :: Ptr CNModMPolyUnivar -> Ptr CNModMPolyCtx -> IO ()++foreign import ccall "nmod_mpoly.h &nmod_mpoly_univar_clear"+ p_nmod_mpoly_univar_clear :: FunPtr (Ptr CNModMPolyUnivar -> Ptr CNModMPolyCtx -> IO ())++-- | /nmod_mpoly_univar_swap/ /A/ /B/ /ctx/ +--+-- Swap /A/ and /B/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_univar_swap"+ nmod_mpoly_univar_swap :: Ptr CNModMPolyUnivar -> Ptr CNModMPolyUnivar -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_to_univar/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to a univariate form of /B/ by pulling out the variable of index+-- /var/. The coefficients of /A/ will still belong to the content /ctx/+-- but will not depend on the variable of index /var/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_to_univar"+ nmod_mpoly_to_univar :: Ptr CNModMPolyUnivar -> Ptr CNModMPoly -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_from_univar/ /A/ /B/ /var/ /ctx/ +--+-- Set /A/ to the normal form of /B/ by putting in the variable of index+-- /var/. This function is undefined if the coefficients of /B/ depend on+-- the variable of index /var/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_from_univar"+ nmod_mpoly_from_univar :: Ptr CNModMPoly -> Ptr CNModMPolyUnivar -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_univar_degree_fits_si/ /A/ /ctx/ +--+-- Return \(1\) if the degree of /A/ with respect to the main variable fits+-- an @slong@. Otherwise, return \(0\).+foreign import ccall "nmod_mpoly.h nmod_mpoly_univar_degree_fits_si"+ nmod_mpoly_univar_degree_fits_si :: Ptr CNModMPolyUnivar -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_univar_length/ /A/ /ctx/ +--+-- Return the number of terms in /A/ with respect to the main variable.+foreign import ccall "nmod_mpoly.h nmod_mpoly_univar_length"+ nmod_mpoly_univar_length :: Ptr CNModMPolyUnivar -> Ptr CNModMPolyCtx -> IO CLong++-- | /nmod_mpoly_univar_get_term_exp_si/ /A/ /i/ /ctx/ +--+-- Return the exponent of the term of index /i/ of /A/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_univar_get_term_exp_si"+ nmod_mpoly_univar_get_term_exp_si :: Ptr CNModMPolyUnivar -> CLong -> Ptr CNModMPolyCtx -> IO CLong++-- | /nmod_mpoly_univar_get_term_coeff/ /c/ /A/ /i/ /ctx/ +foreign import ccall "nmod_mpoly.h nmod_mpoly_univar_get_term_coeff"+ nmod_mpoly_univar_get_term_coeff :: Ptr CNModMPoly -> Ptr CNModMPolyUnivar -> CLong -> Ptr CNModMPolyCtx -> IO ()+-- | /nmod_mpoly_univar_swap_term_coeff/ /c/ /A/ /i/ /ctx/ +--+-- Set (resp. swap) /c/ to (resp. with) the coefficient of the term of+-- index /i/ of /A/.+foreign import ccall "nmod_mpoly.h nmod_mpoly_univar_swap_term_coeff"+ nmod_mpoly_univar_swap_term_coeff :: Ptr CNModMPoly -> Ptr CNModMPolyUnivar -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- Internal Functions ----------------------------------------------------------++-- | /nmod_mpoly_pow_rmul/ /A/ /B/ /k/ /ctx/ +--+-- Set /A/ to /B/ raised to the /k/-th power using repeated+-- multiplications.+foreign import ccall "nmod_mpoly.h nmod_mpoly_pow_rmul"+ nmod_mpoly_pow_rmul :: Ptr CNModMPoly -> Ptr CNModMPoly -> CULong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_div_monagan_pearce/ /polyq/ /poly2/ /poly3/ /ctx/ +--+-- Set @polyq@ to the quotient of @poly2@ by @poly3@, discarding the+-- remainder (with notional remainder coefficients reduced modulo the+-- leading coefficient of @poly3@). Implements \"Polynomial division using+-- dynamic arrays, heaps and packed exponents\" by Michael Monagan and+-- Roman Pearce. This function is exceptionally efficient if the division+-- is known to be exact.+foreign import ccall "nmod_mpoly.h nmod_mpoly_div_monagan_pearce"+ nmod_mpoly_div_monagan_pearce :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_divrem_monagan_pearce/ /q/ /r/ /poly2/ /poly3/ /ctx/ +--+-- Set @polyq@ and @polyr@ to the quotient and remainder of @poly2@ divided+-- by @poly3@, (with remainder coefficients reduced modulo the leading+-- coefficient of @poly3@). Implements \"Polynomial division using dynamic+-- arrays, heaps and packed exponents\" by Michael Monagan and Roman+-- Pearce.+foreign import ccall "nmod_mpoly.h nmod_mpoly_divrem_monagan_pearce"+ nmod_mpoly_divrem_monagan_pearce :: Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_divrem_ideal_monagan_pearce/ /q/ /r/ /poly2/ /poly3/ /len/ /ctx/ +--+-- This function is as per @nmod_mpoly_divrem_monagan_pearce@ except that+-- it takes an array of divisor polynomials @poly3@, and it returns an+-- array of quotient polynomials @q@. The number of divisor (and hence+-- quotient) polynomials, is given by /len/. The function computes+-- polynomials \(q_i = q[i]\) such that @poly2@ is+-- \(r + \sum_{i=0}^{\mbox{len - 1}} q_ib_i\), where \(b_i =\) @poly3[i]@.+foreign import ccall "nmod_mpoly.h nmod_mpoly_divrem_ideal_monagan_pearce"+ nmod_mpoly_divrem_ideal_monagan_pearce :: Ptr (Ptr (Ptr CNModMPoly)) -> Ptr CNModMPoly -> Ptr CNModMPoly -> Ptr (Ptr (Ptr CNModMPoly)) -> CLong -> Ptr CNModMPolyCtx -> IO ()+
+ src/Data/Number/Flint/NMod/MPoly/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.NMod.MPoly.Factor (+ module Data.Number.Flint.NMod.MPoly.Factor.FFI+ ) where++import Data.Number.Flint.NMod.MPoly.Factor.FFI
+ src/Data/Number/Flint/NMod/MPoly/Factor/FFI.hsc view
@@ -0,0 +1,163 @@+{-|+module : Data.Number.Flint.NMod.MPoly.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NMod.MPoly.Factor.FFI (+ -- * Factorisation of multivariate polynomials over integers mod n+ -- (word-size n)+ NModMPolyFactor (..)+ , CNModMPolyFactor (..)+ , newNModMPolyFactor+ , withNModMPolyFactor+ -- * Memory managment+ , nmod_mpoly_factor_init+ , nmod_mpoly_factor_clear+ -- * Basic manipulation+ , nmod_mpoly_factor_swap+ , nmod_mpoly_factor_length+ , nmod_mpoly_factor_get_constant_ui+ , nmod_mpoly_factor_get_base+ , nmod_mpoly_factor_swap_base+ , nmod_mpoly_factor_get_exp_si+ , nmod_mpoly_factor_sort+ -- * Factorisation+ , nmod_mpoly_factor_squarefree+ , nmod_mpoly_factor+) where ++-- Factorisation of multivariate polynomials over integers mod n (word-size n) -++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.MPoly+import Data.Number.Flint.NMod+import Data.Number.Flint.NMod.Types+import Data.Number.Flint.NMod.MPoly++#include <flint/flint.h>+#include <flint/nmod.h>+#include <flint/nmod_poly.h>+#include <flint/nmod_mpoly.h>++-- Types -----------------------------------------------------------------------++data NModMPolyFactor =+ NModMPolyFactor {-# UNPACK #-} !(ForeignPtr CNModMPolyFactor)+data CNModMPolyFactor =+ CNModMPolyFactor CMpLimb (Ptr CNModMPoly)+ (Ptr CFmpz) CLong CLong++instance Storable CNModMPolyFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_mpoly_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_mpoly_factor_t}+ peek ptr = CNModMPolyFactor+ <$> #{peek nmod_mpoly_factor_struct, constant } ptr+ <*> #{peek nmod_mpoly_factor_struct, poly } ptr+ <*> #{peek nmod_mpoly_factor_struct, exp } ptr+ <*> #{peek nmod_mpoly_factor_struct, num } ptr+ <*> #{peek nmod_mpoly_factor_struct, alloc } ptr+ poke = error "CNModMPolyFactor.poke: Not defined"++newNModMPolyFactor ctx@(NModMPolyCtx pctx) = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withNModMPolyCtx ctx $ \ctx -> do+ nmod_mpoly_factor_init x ctx+ addForeignPtrFinalizerEnv p_nmod_mpoly_factor_clear x pctx+ return $ NModMPolyFactor x++withNModMPolyFactor (NModMPolyFactor p) f = do+ withForeignPtr p $ \fp -> f fp >>= return . (NModMPolyFactor p,)+ +-- Memory management -----------------------------------------------------------++-- | /nmod_mpoly_factor_init/ /f/ /ctx/ +--+-- Initialise /f/.+foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_init"+ nmod_mpoly_factor_init :: Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_factor_clear/ /f/ /ctx/ +--+-- Clear /f/.+foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_clear"+ nmod_mpoly_factor_clear :: Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ()++foreign import ccall "nmod_mpoly_factor.h &nmod_mpoly_factor_clear"+ p_nmod_mpoly_factor_clear :: FunPtr (Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ())++-- Basic manipulation ----------------------------------------------------------++-- | /nmod_mpoly_factor_swap/ /f/ /g/ /ctx/ +--+-- Efficiently swap /f/ and /g/.+foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_swap"+ nmod_mpoly_factor_swap :: Ptr CNModMPolyFactor -> Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_factor_length/ /f/ /ctx/ +--+-- Return the length of the product in /f/.+foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_length"+ nmod_mpoly_factor_length :: Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO CLong++-- | /nmod_mpoly_factor_get_constant_ui/ /f/ /ctx/ +--+-- Return the constant of /f/.+foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_get_constant_ui"+ nmod_mpoly_factor_get_constant_ui :: Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_factor_get_base/ /p/ /f/ /i/ /ctx/ +foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_get_base"+ nmod_mpoly_factor_get_base :: Ptr CNModMPoly -> Ptr CNModMPolyFactor -> CLong -> Ptr CNModMPolyCtx -> IO ()+-- | /nmod_mpoly_factor_swap_base/ /p/ /f/ /i/ /ctx/ +--+-- Set (resp. swap) /B/ to (resp. with) the base of the term of index \(i\)+-- in /A/.+foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_swap_base"+ nmod_mpoly_factor_swap_base :: Ptr CNModMPoly -> Ptr CNModMPolyFactor -> CLong -> Ptr CNModMPolyCtx -> IO ()++-- | /nmod_mpoly_factor_get_exp_si/ /f/ /i/ /ctx/ +--+-- Return the exponent of the term of index \(i\) in /A/. It is assumed to+-- fit an @slong@.+foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_get_exp_si"+ nmod_mpoly_factor_get_exp_si :: Ptr CNModMPolyFactor -> CLong -> Ptr CNModMPolyCtx -> IO CLong++-- | /nmod_mpoly_factor_sort/ /f/ /ctx/ +--+-- Sort the product of /f/ first by exponent and then by base.+foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_sort"+ nmod_mpoly_factor_sort :: Ptr CNModMPolyFactor -> Ptr CNModMPolyCtx -> IO ()++-- Factorisation ---------------------------------------------------------------++-- | /nmod_mpoly_factor_squarefree/ /f/ /A/ /ctx/ +--+-- Set /f/ to a factorization of /A/ where the bases are primitive and+-- pairwise relatively prime. If the product of all irreducible factors+-- with a given exponent is desired, it is recommended to call+-- @nmod_mpoly_factor_sort@ and then multiply the bases with the desired+-- exponent.+foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor_squarefree"+ nmod_mpoly_factor_squarefree :: Ptr CNModMPolyFactor -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt++-- | /nmod_mpoly_factor/ /f/ /A/ /ctx/ +--+-- Set /f/ to a factorization of /A/ where the bases are irreducible.+foreign import ccall "nmod_mpoly_factor.h nmod_mpoly_factor"+ nmod_mpoly_factor :: Ptr CNModMPolyFactor -> Ptr CNModMPoly -> Ptr CNModMPolyCtx -> IO CInt+
+ src/Data/Number/Flint/NMod/Mat.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.NMod.Mat (+ module Data.Number.Flint.NMod.Mat.FFI+ ) where++import Data.Number.Flint.NMod.Mat.FFI
+ src/Data/Number/Flint/NMod/Mat/FFI.hsc view
@@ -0,0 +1,915 @@+{-|+module : Data.Number.Flint.NMod.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NMod.Mat.FFI (+ -- * Matrices over integers mod n (word-size n)+ NModMat (..)+ , CNModMat (..)+ , newNModMat+ , withNModMat+ -- * Memory management+ , nmod_mat_init+ , nmod_mat_init_set+ , nmod_mat_clear+ , nmod_mat_set+ , nmod_mat_swap+ , nmod_mat_swap_entrywise+ -- * Basic properties and manipulation+ , nmod_mat_entry+ , nmod_mat_get_entry+ , nmod_mat_entry_ptr+ , nmod_mat_set_entry+ , nmod_mat_nrows+ , nmod_mat_ncols+ , nmod_mat_zero+ , nmod_mat_is_zero+ -- * Window+ , nmod_mat_window_init+ , nmod_mat_window_clear+ -- * Concatenate+ , nmod_mat_concat_vertical+ , nmod_mat_concat_horizontal+ -- * Printing+ , nmod_mat_print_pretty+ -- * Random matrix generation+ , nmod_mat_randtest+ , nmod_mat_randfull+ , nmod_mat_randpermdiag+ , nmod_mat_randrank+ , nmod_mat_randops+ , nmod_mat_randtril+ , nmod_mat_randtriu+ -- * Comparison+ , nmod_mat_equal+ , nmod_mat_is_zero_row+ -- * Transposition and permutations+ , nmod_mat_transpose+ , nmod_mat_swap_rows+ , nmod_mat_swap_cols+ , nmod_mat_invert_rows+ , nmod_mat_invert_cols+ , nmod_mat_permute_rows+ -- * Addition and subtraction+ , nmod_mat_add+ , nmod_mat_sub+ , nmod_mat_neg+ -- * Matrix-scalar arithmetic+ , nmod_mat_scalar_mul+ , nmod_mat_scalar_addmul_ui+ , nmod_mat_scalar_mul_fmpz+ -- * Matrix multiplication+ , nmod_mat_mul+ , _nmod_mat_mul_classical_op+ , nmod_mat_mul_classical+ , _nmod_mat_mul_classical_threaded_pool_op+ , _nmod_mat_mul_classical_threaded_op+ , nmod_mat_mul_classical_threaded+ , nmod_mat_mul_strassen+ , nmod_mat_mul_blas+ , nmod_mat_addmul+ , nmod_mat_submul+ , nmod_mat_mul_nmod_vec+ , nmod_mat_nmod_vec_mul+ -- * Matrix Exponentiation+ , _nmod_mat_pow+ , nmod_mat_pow+ -- * Trace+ , nmod_mat_trace+ -- * Determinant and rank+ , nmod_mat_det_howell+ , nmod_mat_det+ , nmod_mat_rank+ -- * Inverse+ , nmod_mat_inv+ -- * Triangular solving+ , nmod_mat_solve_tril+ , nmod_mat_solve_tril_classical+ , nmod_mat_solve_tril_recursive+ , nmod_mat_solve_triu+ , nmod_mat_solve_triu_classical+ , nmod_mat_solve_triu_recursive+ -- * Nonsingular square solving+ , nmod_mat_solve+ , nmod_mat_can_solve_inner+ , nmod_mat_can_solve+ , nmod_mat_solve_vec+ -- * LU decomposition+ , nmod_mat_lu+ -- * Reduced row echelon form+ , nmod_mat_rref+ , nmod_mat_reduce_row+ -- * Nullspace+ , nmod_mat_nullspace+ -- * Transforms+ , nmod_mat_similarity+ -- * Characteristic polynomial+ , nmod_mat_charpoly_berkowitz+ -- * Minimal polynomial+ , nmod_mat_minpoly+ -- * Strong echelon form and Howell form+ , nmod_mat_strong_echelon_form+ , nmod_mat_howell_form+) where++-- Matrices over integers mod n (word-size n) ----------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr)++import Data.Number.Flint.Flint+import Data.Number.Flint.ThreadPool++import Data.Number.Flint.Fmpz+import Data.Number.Flint.NMod+import Data.Number.Flint.NMod.Vec+import Data.Number.Flint.NMod.Types++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/nmod_vec.h>+#include <flint/nmod_mat.h>++-- nmod_mat_t -----------------------------------------------------------------++newNModMat rows cols n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> nmod_mat_init x rows cols n+ addForeignPtrFinalizer p_nmod_mat_clear x+ return $ NModMat x++{-# INLINE withNModMat #-}+withNModMat (NModMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (NModMat x,)++-- Memory management -----------------------------------------------------------++-- | /nmod_mat_init/ /mat/ /rows/ /cols/ /n/ +-- +-- Initialises @mat@ to a @rows@-by-@cols@ matrix with coefficients modulo+-- \(n\), where \(n\) can be any nonzero integer that fits in a limb. All+-- elements are set to zero.+foreign import ccall "nmod_mat.h nmod_mat_init"+ nmod_mat_init :: Ptr CNModMat -> CLong -> CLong -> CMpLimb -> IO ()++-- | /nmod_mat_init_set/ /mat/ /src/ +-- +-- Initialises @mat@ and sets its dimensions, modulus and elements to those+-- of @src@.+foreign import ccall "nmod_mat.h nmod_mat_init_set"+ nmod_mat_init_set :: Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /nmod_mat_clear/ /mat/ +-- +-- Clears the matrix and releases any memory it used. The matrix cannot be+-- used again until it is initialised. This function must be called exactly+-- once when finished using an @nmod_mat_t@ object.+foreign import ccall "nmod_mat.h nmod_mat_clear"+ nmod_mat_clear :: Ptr CNModMat -> IO ()++foreign import ccall "nmod_mat.h &nmod_mat_clear"+ p_nmod_mat_clear :: FunPtr (Ptr CNModMat -> IO ())++nmod_mat_entry mat i j = do+ CNModMat entries r c rows mod <- peek mat+ return $ entries `advancePtr` (fromIntegral (i*c + j))+ +-- | /nmod_mat_set/ /mat/ /src/ +-- +-- Sets @mat@ to a copy of @src@. It is assumed that @mat@ and @src@ have+-- identical dimensions.+foreign import ccall "nmod_mat.h nmod_mat_set"+ nmod_mat_set :: Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /nmod_mat_swap/ /mat1/ /mat2/ +-- +-- Exchanges @mat1@ and @mat2@.+foreign import ccall "nmod_mat.h nmod_mat_swap"+ nmod_mat_swap :: Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /nmod_mat_swap_entrywise/ /mat1/ /mat2/ +-- +-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "nmod_mat.h nmod_mat_swap_entrywise"+ nmod_mat_swap_entrywise :: Ptr CNModMat -> Ptr CNModMat -> IO ()++-- Basic properties and manipulation -------------------------------------------++-- -- | /nmod_mat_entry/ /mat/ /i/ /j/ +-- -- +-- -- Directly accesses the entry in @mat@ in row \(i\) and column \(j\),+-- -- indexed from zero. No bounds checking is performed. This macro can be+-- -- used both for reading and writing coefficients.+-- foreign import ccall "nmod_mat.h nmod_mat_entry"+-- nmod_mat_entry :: Ptr CNModMat -> CLong -> CLong -> IO (Ptr CNMod)+ +-- nmod_mat_entry mat i j = do+-- ncols <- nmod_mat_nrows mat+-- return $ (castPtr mat) `advancePtr` (fromIntegral (ncols * i + ))++-- | /nmod_mat_get_entry/ /mat/ /i/ /j/ +-- +-- Get the entry at row \(i\) and column \(j\) of the matrix @mat@.+foreign import ccall "nmod_mat.h nmod_mat_get_entry"+ nmod_mat_get_entry :: Ptr CNModMat -> CLong -> CLong -> IO CMpLimb++-- | /nmod_mat_entry_ptr/ /mat/ /i/ /j/ +-- +-- Return a pointer to the entry at row \(i\) and column \(j\) of the+-- matrix @mat@.+foreign import ccall "nmod_mat.h nmod_mat_entry_ptr"+ nmod_mat_entry_ptr :: Ptr CNModMat -> CLong -> CLong -> IO (Ptr CMpLimb)++-- | /nmod_mat_set_entry/ /mat/ /i/ /j/ /x/ +-- +-- Set the entry at row \(i\) and column \(j\) of the matrix @mat@ to @x@.+foreign import ccall "nmod_mat.h nmod_mat_set_entry"+ nmod_mat_set_entry :: Ptr CNModMat -> CLong -> CLong -> CMpLimb -> IO ()++-- | /nmod_mat_nrows/ /mat/ +-- +-- Returns the number of rows in @mat@.+foreign import ccall "nmod_mat.h nmod_mat_nrows"+ nmod_mat_nrows :: Ptr CNModMat -> IO CLong++-- | /nmod_mat_ncols/ /mat/ +-- +-- Returns the number of columns in @mat@.+foreign import ccall "nmod_mat.h nmod_mat_ncols"+ nmod_mat_ncols :: Ptr CNModMat -> IO CLong++-- | /nmod_mat_zero/ /mat/ +-- +-- Sets all entries of the matrix @mat@ to zero.+foreign import ccall "nmod_mat.h nmod_mat_zero"+ nmod_mat_zero :: Ptr CNModMat -> IO ()++-- | /nmod_mat_is_zero/ /mat/ +-- +-- Returns \(1\) if all entries of the matrix @mat@ are zero.+foreign import ccall "nmod_mat.h nmod_mat_is_zero"+ nmod_mat_is_zero :: Ptr CNModMat -> IO CInt++-- Window ----------------------------------------------------------------------++-- | /nmod_mat_window_init/ /window/ /mat/ /r1/ /c1/ /r2/ /c2/ +-- +-- Initializes the matrix @window@ to be an @r2 - r1@ by @c2 - c1@+-- submatrix of @mat@ whose @(0,0)@ entry is the @(r1, c1)@ entry of @mat@.+-- The memory for the elements of @window@ is shared with @mat@.+foreign import ccall "nmod_mat.h nmod_mat_window_init"+ nmod_mat_window_init :: Ptr CNModMat -> Ptr CNModMat -> CLong -> CLong -> CLong -> CLong -> IO ()++-- | /nmod_mat_window_clear/ /window/ +-- +-- Clears the matrix @window@ and releases any memory that it uses. Note+-- that the memory to the underlying matrix that @window@ points to is not+-- freed.+foreign import ccall "nmod_mat.h nmod_mat_window_clear"+ nmod_mat_window_clear :: Ptr CNModMat -> IO ()++-- Concatenate -----------------------------------------------------------------++-- | /nmod_mat_concat_vertical/ /res/ /mat1/ /mat2/ +-- +-- Sets @res@ to vertical concatenation of (mat1, @mat2@) in that order.+-- Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ : \(k \times n\),+-- @res@ : \((m + k) \times n\).+foreign import ccall "nmod_mat.h nmod_mat_concat_vertical"+ nmod_mat_concat_vertical :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /nmod_mat_concat_horizontal/ /res/ /mat1/ /mat2/ +-- +-- Sets @res@ to horizontal concatenation of (@mat1@, @mat2@) in that+-- order. Matrix dimensions : @mat1@ : \(m \times n\), @mat2@ :+-- \(m \times k\), @res@ : \(m \times (n + k)\).+foreign import ccall "nmod_mat.h nmod_mat_concat_horizontal"+ nmod_mat_concat_horizontal :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO ()++-- Printing --------------------------------------------------------------------++-- | /nmod_mat_print_pretty/ /mat/ +-- +-- Pretty-prints @mat@ to @stdout@. A header is printed followed by the+-- rows enclosed in brackets. Each column is right-aligned to the width of+-- the modulus written in decimal, and the columns are separated by spaces.+-- For example:+-- +-- > <2 x 3 integer matrix mod 2903>+-- > [ 0 0 2607]+-- > [ 622 0 0]+foreign import ccall "nmod_mat.h nmod_mat_print_pretty"+ nmod_mat_print_pretty :: Ptr CNModMat -> IO ()++-- Random matrix generation ----------------------------------------------------++-- | /nmod_mat_randtest/ /mat/ /state/ +-- +-- Sets the elements to a random matrix with entries between \(0\) and+-- \(m-1\) inclusive, where \(m\) is the modulus of @mat@. A sparse matrix+-- is generated with increased probability.+foreign import ccall "nmod_mat.h nmod_mat_randtest"+ nmod_mat_randtest :: Ptr CNModMat -> Ptr CFRandState -> IO ()++-- | /nmod_mat_randfull/ /mat/ /state/ +-- +-- Sets the element to random numbers likely to be close to the modulus of+-- the matrix. This is used to test potential overflow-related bugs.+foreign import ccall "nmod_mat.h nmod_mat_randfull"+ nmod_mat_randfull :: Ptr CNModMat -> Ptr CFRandState -> IO ()++-- | /nmod_mat_randpermdiag/ /mat/ /state/ /diag/ /n/ +-- +-- Sets @mat@ to a random permutation of the diagonal matrix with \(n\)+-- leading entries given by the vector @diag@. It is assumed that the main+-- diagonal of @mat@ has room for at least \(n\) entries.+-- +-- Returns \(0\) or \(1\), depending on whether the permutation is even or+-- odd respectively.+foreign import ccall "nmod_mat.h nmod_mat_randpermdiag"+ nmod_mat_randpermdiag :: Ptr CNModMat -> Ptr CFRandState -> Ptr (Ptr CMp) -> CLong -> IO CInt++-- | /nmod_mat_randrank/ /mat/ /state/ /rank/ +-- +-- Sets @mat@ to a random sparse matrix with the given rank, having exactly+-- as many non-zero elements as the rank, with the non-zero elements being+-- uniformly random integers between \(0\) and \(m-1\) inclusive, where+-- \(m\) is the modulus of @mat@.+-- +-- The matrix can be transformed into a dense matrix with unchanged rank by+-- subsequently calling @nmod_mat_randops@.+foreign import ccall "nmod_mat.h nmod_mat_randrank"+ nmod_mat_randrank :: Ptr CNModMat -> Ptr CFRandState -> CLong -> IO ()++-- | /nmod_mat_randops/ /mat/ /count/ /state/ +-- +-- Randomises @mat@ by performing elementary row or column operations. More+-- precisely, at most @count@ random additions or subtractions of distinct+-- rows and columns will be performed. This leaves the rank (and for square+-- matrices, determinant) unchanged.+foreign import ccall "nmod_mat.h nmod_mat_randops"+ nmod_mat_randops :: Ptr CNModMat -> CLong -> Ptr CFRandState -> IO ()++-- | /nmod_mat_randtril/ /mat/ /state/ /unit/ +-- +-- Sets @mat@ to a random lower triangular matrix. If @unit@ is 1, it will+-- have ones on the main diagonal, otherwise it will have random nonzero+-- entries on the main diagonal.+foreign import ccall "nmod_mat.h nmod_mat_randtril"+ nmod_mat_randtril :: Ptr CNModMat -> Ptr CFRandState -> CInt -> IO ()++-- | /nmod_mat_randtriu/ /mat/ /state/ /unit/ +-- +-- Sets @mat@ to a random upper triangular matrix. If @unit@ is 1, it will+-- have ones on the main diagonal, otherwise it will have random nonzero+-- entries on the main diagonal.+foreign import ccall "nmod_mat.h nmod_mat_randtriu"+ nmod_mat_randtriu :: Ptr CNModMat -> Ptr CFRandState -> CInt -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /nmod_mat_equal/ /mat1/ /mat2/ +-- +-- Returns nonzero if @mat1@ and @mat2@ have the same dimensions and+-- elements, and zero otherwise. The moduli are ignored.+foreign import ccall "nmod_mat.h nmod_mat_equal"+ nmod_mat_equal :: Ptr CNModMat -> Ptr CNModMat -> IO CInt++-- | /nmod_mat_is_zero_row/ /mat/ /i/ +-- +-- Returns a non-zero value if row \(i\) of @mat@ is zero.+foreign import ccall "nmod_mat.h nmod_mat_is_zero_row"+ nmod_mat_is_zero_row :: Ptr CNModMat -> CLong -> IO CInt++-- Transposition and permutations ----------------------------------------------++-- | /nmod_mat_transpose/ /B/ /A/ +-- +-- Sets \(B\) to the transpose of \(A\). Dimensions must be compatible.+-- \(B\) and \(A\) may be the same object if and only if the matrix is+-- square.+foreign import ccall "nmod_mat.h nmod_mat_transpose"+ nmod_mat_transpose :: Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /nmod_mat_swap_rows/ /mat/ /perm/ /r/ /s/ +-- +-- Swaps rows @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the rows will also be applied to @perm@.+foreign import ccall "nmod_mat.h nmod_mat_swap_rows"+ nmod_mat_swap_rows :: Ptr CNModMat -> Ptr CLong -> CLong -> CLong -> IO ()++-- | /nmod_mat_swap_cols/ /mat/ /perm/ /r/ /s/ +-- +-- Swaps columns @r@ and @s@ of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the columns will also be applied to @perm@.+foreign import ccall "nmod_mat.h nmod_mat_swap_cols"+ nmod_mat_swap_cols :: Ptr CNModMat -> Ptr CLong -> CLong -> CLong -> IO ()++-- | /nmod_mat_invert_rows/ /mat/ /perm/ +-- +-- Swaps rows @i@ and @r - i@ of @mat@ for @0 \<= i \< r\/2@, where @r@ is+-- the number of rows of @mat@. If @perm@ is non-@NULL@, the permutation of+-- the rows will also be applied to @perm@.+foreign import ccall "nmod_mat.h nmod_mat_invert_rows"+ nmod_mat_invert_rows :: Ptr CNModMat -> Ptr CLong -> IO ()++-- | /nmod_mat_invert_cols/ /mat/ /perm/ +-- +-- Swaps columns @i@ and @c - i@ of @mat@ for @0 \<= i \< c\/2@, where @c@+-- is the number of columns of @mat@. If @perm@ is non-@NULL@, the+-- permutation of the columns will also be applied to @perm@.+foreign import ccall "nmod_mat.h nmod_mat_invert_cols"+ nmod_mat_invert_cols :: Ptr CNModMat -> Ptr CLong -> IO ()++-- | /nmod_mat_permute_rows/ /mat/ /perm_act/ /perm_store/ +-- +-- Permutes rows of the matrix @mat@ according to permutation @perm_act@+-- and, if @perm_store@ is not @NULL@, apply the same permutation to it.+foreign import ccall "nmod_mat.h nmod_mat_permute_rows"+ nmod_mat_permute_rows :: Ptr CNModMat -> Ptr CLong -> Ptr CLong -> IO ()++-- Addition and subtraction ----------------------------------------------------++-- | /nmod_mat_add/ /C/ /A/ /B/ +-- +-- Computes \(C = A + B\). Dimensions must be identical.+foreign import ccall "nmod_mat.h nmod_mat_add"+ nmod_mat_add :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /nmod_mat_sub/ /C/ /A/ /B/ +-- +-- Computes \(C = A - B\). Dimensions must be identical.+foreign import ccall "nmod_mat.h nmod_mat_sub"+ nmod_mat_sub :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /nmod_mat_neg/ /A/ /B/ +-- +-- Sets \(B = -A\). Dimensions must be identical.+foreign import ccall "nmod_mat.h nmod_mat_neg"+ nmod_mat_neg :: Ptr CNModMat -> Ptr CNModMat -> IO ()++-- Matrix-scalar arithmetic ----------------------------------------------------++-- | /nmod_mat_scalar_mul/ /B/ /A/ /c/ +-- +-- Sets \(B = cA\), where the scalar \(c\) is assumed to be reduced modulo+-- the modulus. Dimensions of \(A\) and \(B\) must be identical.+foreign import ccall "nmod_mat.h nmod_mat_scalar_mul"+ nmod_mat_scalar_mul :: Ptr CNModMat -> Ptr CNModMat -> CMpLimb -> IO ()++-- | /nmod_mat_scalar_addmul_ui/ /dest/ /X/ /Y/ /b/ +-- +-- Sets \(dest = X + bY\), where the scalar \(b\) is assumed to be reduced+-- modulo the modulus. Dimensions of dest, X and Y must be identical. dest+-- can be aliased with X or Y.+foreign import ccall "nmod_mat.h nmod_mat_scalar_addmul_ui"+ nmod_mat_scalar_addmul_ui :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> CMpLimb -> IO ()++-- | /nmod_mat_scalar_mul_fmpz/ /res/ /M/ /c/ +-- +-- Sets \(B = cA\), where the scalar \(c\) is of type @fmpz_t@. Dimensions+-- of \(A\) and \(B\) must be identical.+foreign import ccall "nmod_mat.h nmod_mat_scalar_mul_fmpz"+ nmod_mat_scalar_mul_fmpz :: Ptr CNModMat -> Ptr CNModMat -> Ptr CFmpz -> IO ()++-- Matrix multiplication -------------------------------------------------------++-- | /nmod_mat_mul/ /C/ /A/ /B/ +-- +-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. Aliasing is allowed. This function automatically chooses+-- between classical and Strassen multiplication.+foreign import ccall "nmod_mat.h nmod_mat_mul"+ nmod_mat_mul :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /_nmod_mat_mul_classical_op/ /D/ /C/ /A/ /B/ /op/ +-- +-- Sets @D = A*B op C@ where @op@ is @+1@ for addition, @-1@ for+-- subtraction and @0@ to ignore @C@.+foreign import ccall "nmod_mat.h _nmod_mat_mul_classical_op"+ _nmod_mat_mul_classical_op :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> CInt -> IO ()++-- | /nmod_mat_mul_classical/ /C/ /A/ /B/ +-- +-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. \(C\) is not allowed to be aliased with \(A\) or \(B\).+-- Uses classical matrix multiplication, creating a temporary transposed+-- copy of \(B\) to improve memory locality if the matrices are large+-- enough, and packing several entries of \(B\) into each word if the+-- modulus is very small.+foreign import ccall "nmod_mat.h nmod_mat_mul_classical"+ nmod_mat_mul_classical :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /_nmod_mat_mul_classical_threaded_pool_op/ /D/ /C/ /A/ /B/ /op/ /threads/ /num_threads/ +-- +-- Multithreaded version of @_nmod_mat_mul_classical@.+foreign import ccall "nmod_mat.h _nmod_mat_mul_classical_threaded_pool_op"+ _nmod_mat_mul_classical_threaded_pool_op :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> CInt -> Ptr CThreadPoolHandle -> CLong -> IO ()++-- | /_nmod_mat_mul_classical_threaded_op/ /D/ /C/ /A/ /B/ /op/ +-- +-- Multithreaded version of @_nmod_mat_mul_classical@.+foreign import ccall "nmod_mat.h _nmod_mat_mul_classical_threaded_op"+ _nmod_mat_mul_classical_threaded_op :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> CInt -> IO ()++-- | /nmod_mat_mul_classical_threaded/ /C/ /A/ /B/ +-- +-- Multithreaded version of @nmod_mat_mul_classical@.+foreign import ccall "nmod_mat.h nmod_mat_mul_classical_threaded"+ nmod_mat_mul_classical_threaded :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /nmod_mat_mul_strassen/ /C/ /A/ /B/ +-- +-- Sets \(C = AB\). Dimensions must be compatible for matrix+-- multiplication. \(C\) is not allowed to be aliased with \(A\) or \(B\).+-- Uses Strassen multiplication (the Strassen-Winograd variant).+foreign import ccall "nmod_mat.h nmod_mat_mul_strassen"+ nmod_mat_mul_strassen :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /nmod_mat_mul_blas/ /C/ /A/ /B/ +-- +-- Tries to set \(C = AB\) using BLAS and returns \(1\) for success and+-- \(0\) for failure. Dimensions must be compatible for matrix+-- multiplication.+foreign import ccall "nmod_mat.h nmod_mat_mul_blas"+ nmod_mat_mul_blas :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO CInt++-- | /nmod_mat_addmul/ /D/ /C/ /A/ /B/ +-- +-- Sets \(D = C + AB\). \(C\) and \(D\) may be aliased with each other but+-- not with \(A\) or \(B\). Automatically selects between classical and+-- Strassen multiplication.+foreign import ccall "nmod_mat.h nmod_mat_addmul"+ nmod_mat_addmul :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /nmod_mat_submul/ /D/ /C/ /A/ /B/ +-- +-- Sets \(D = C + AB\). \(C\) and \(D\) may be aliased with each other but+-- not with \(A\) or \(B\).+foreign import ccall "nmod_mat.h nmod_mat_submul"+ nmod_mat_submul :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO ()++-- | /nmod_mat_mul_nmod_vec/ /c/ /A/ /b/ /blen/ +-- +-- Compute a matrix-vector product of @A@ and @(b, blen)@ and store the+-- result in @c@. The vector @(b, blen)@ is either truncated or+-- zero-extended to the number of columns of @A@. The number entries+-- written to @c@ is always equal to the number of rows of @A@.+foreign import ccall "nmod_mat.h nmod_mat_mul_nmod_vec"+ nmod_mat_mul_nmod_vec :: Ptr CMpLimb -> Ptr CNModMat -> Ptr CMpLimb -> CLong -> IO ()++-- | /nmod_mat_nmod_vec_mul/ /c/ /a/ /alen/ /B/ +-- +-- Compute a vector-matrix product of @(a, alen)@ and @B@ and and store the+-- result in @c@. The vector @(a, alen)@ is either truncated or+-- zero-extended to the number of rows of @B@. The number entries written+-- to @c@ is always equal to the number of columns of @B@.+foreign import ccall "nmod_mat.h nmod_mat_nmod_vec_mul"+ nmod_mat_nmod_vec_mul :: Ptr CMpLimb -> Ptr CMpLimb -> CLong -> Ptr CNModMat -> IO ()++-- Matrix Exponentiation -------------------------------------------------------++-- | /_nmod_mat_pow/ /dest/ /mat/ /pow/ +-- +-- Sets \(dest = mat^{pow}\). @dest@ and @mat@ cannot be aliased.+-- Implements exponentiation by squaring.+foreign import ccall "nmod_mat.h _nmod_mat_pow"+ _nmod_mat_pow :: Ptr CNModMat -> Ptr CNModMat -> CULong -> IO ()++-- | /nmod_mat_pow/ /dest/ /mat/ /pow/ +-- +-- Sets \(dest = mat^{pow}\). @dest@ and @mat@ may be aliased. Implements+-- exponentiation by squaring.+foreign import ccall "nmod_mat.h nmod_mat_pow"+ nmod_mat_pow :: Ptr CNModMat -> Ptr CNModMat -> CULong -> IO ()++-- Trace -----------------------------------------------------------------------++-- | /nmod_mat_trace/ /mat/ +-- +-- Computes the trace of the matrix, i.e. the sum of the entries on the+-- main diagonal. The matrix is required to be square.+foreign import ccall "nmod_mat.h nmod_mat_trace"+ nmod_mat_trace :: Ptr CNModMat -> IO CMpLimb++-- Determinant and rank --------------------------------------------------------++-- | /nmod_mat_det_howell/ /A/ +-- +-- Returns the determinant of \(A\).+foreign import ccall "nmod_mat.h nmod_mat_det_howell"+ nmod_mat_det_howell :: Ptr CNModMat -> IO CMpLimb++-- | /nmod_mat_det/ /A/ +-- +-- Returns the determinant of \(A\).+foreign import ccall "nmod_mat.h nmod_mat_det"+ nmod_mat_det :: Ptr CNModMat -> IO CMpLimb++-- | /nmod_mat_rank/ /A/ +-- +-- Returns the rank of \(A\). The modulus of \(A\) must be a prime number.+foreign import ccall "nmod_mat.h nmod_mat_rank"+ nmod_mat_rank :: Ptr CNModMat -> IO CLong++-- Inverse ---------------------------------------------------------------------++-- | /nmod_mat_inv/ /B/ /A/ +-- +-- Sets \(B = A^{-1}\) and returns \(1\) if \(A\) is invertible. If \(A\)+-- is singular, returns \(0\) and sets the elements of \(B\) to undefined+-- values.+-- +-- \(A\) and \(B\) must be square matrices with the same dimensions and+-- modulus. The modulus must be prime.+foreign import ccall "nmod_mat.h nmod_mat_inv"+ nmod_mat_inv :: Ptr CNModMat -> Ptr CNModMat -> IO CInt++-- Triangular solving ----------------------------------------------------------++-- | /nmod_mat_solve_tril/ /X/ /L/ /B/ /unit/ +-- +-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- Automatically chooses between the classical and recursive algorithms.+foreign import ccall "nmod_mat.h nmod_mat_solve_tril"+ nmod_mat_solve_tril :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> CInt -> IO ()++-- | /nmod_mat_solve_tril_classical/ /X/ /L/ /B/ /unit/ +-- +-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed. Uses+-- forward substitution.+foreign import ccall "nmod_mat.h nmod_mat_solve_tril_classical"+ nmod_mat_solve_tril_classical :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> CInt -> IO ()++-- | /nmod_mat_solve_tril_recursive/ /X/ /L/ /B/ /unit/ +-- +-- Sets \(X = L^{-1} B\) where \(L\) is a full rank lower triangular square+-- matrix. If @unit@ = 1, \(L\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- +-- Uses the block inversion formula+-- +-- \[\begin{aligned}+-- `+-- \begin{pmatrix} A & 0 \\ C & D \end{pmatrix}^{-1}+-- \begin{pmatrix} X \\ Y \end{pmatrix} =+-- \begin{pmatrix} A^{-1} X \\ D^{-1} ( Y - C A^{-1} X ) \end{pmatrix}+-- \end{aligned}\]+-- +-- to reduce the problem to matrix multiplication and triangular solving of+-- smaller systems.+foreign import ccall "nmod_mat.h nmod_mat_solve_tril_recursive"+ nmod_mat_solve_tril_recursive :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> CInt -> IO ()++-- | /nmod_mat_solve_triu/ /X/ /U/ /B/ /unit/ +-- +-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- Automatically chooses between the classical and recursive algorithms.+foreign import ccall "nmod_mat.h nmod_mat_solve_triu"+ nmod_mat_solve_triu :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> CInt -> IO ()++-- | /nmod_mat_solve_triu_classical/ /X/ /U/ /B/ /unit/ +-- +-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed. Uses+-- forward substitution.+foreign import ccall "nmod_mat.h nmod_mat_solve_triu_classical"+ nmod_mat_solve_triu_classical :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> CInt -> IO ()++-- | /nmod_mat_solve_triu_recursive/ /X/ /U/ /B/ /unit/ +-- +-- Sets \(X = U^{-1} B\) where \(U\) is a full rank upper triangular square+-- matrix. If @unit@ = 1, \(U\) is assumed to have ones on its main+-- diagonal, and the main diagonal will not be read. \(X\) and \(B\) are+-- allowed to be the same matrix, but no other aliasing is allowed.+-- +-- Uses the block inversion formula+-- +-- \[\begin{aligned}+-- `+-- \begin{pmatrix} A & B \\ 0 & D \end{pmatrix}^{-1}+-- \begin{pmatrix} X \\ Y \end{pmatrix} =+-- \begin{pmatrix} A^{-1} (X - B D^{-1} Y) \\ D^{-1} Y \end{pmatrix}+-- \end{aligned}\]+-- +-- to reduce the problem to matrix multiplication and triangular solving of+-- smaller systems.+foreign import ccall "nmod_mat.h nmod_mat_solve_triu_recursive"+ nmod_mat_solve_triu_recursive :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> CInt -> IO ()++-- Nonsingular square solving --------------------------------------------------++-- | /nmod_mat_solve/ /X/ /A/ /B/ +-- +-- Solves the matrix-matrix equation \(AX = B\) over+-- \(\mathbb{Z} / p \mathbb{Z}\) where \(p\) is the modulus of \(X\) which+-- must be a prime number. \(X\), \(A\), and \(B\) should have the same+-- moduli.+-- +-- Returns \(1\) if \(A\) has full rank; otherwise returns \(0\) and sets+-- the elements of \(X\) to undefined values.+-- +-- The matrix \(A\) must be square.+foreign import ccall "nmod_mat.h nmod_mat_solve"+ nmod_mat_solve :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO CInt++-- | /nmod_mat_can_solve_inner/ /rank/ /perm/ /pivots/ /X/ /A/ /B/ +-- +-- As for @nmod_mat_can_solve@ except that if \(rank\) is not \(NULL\) the+-- value it points to will be set to the rank of \(A\). If \(perm\) is not+-- \(NULL\) then it must be a valid initialised permutation whose length is+-- the number of rows of \(A\). After the function call it will be set to+-- the row permutation given by LU decomposition of \(A\). If \(pivots\) is+-- not \(NULL\) then it must an initialised vector. Only the first+-- \(*rank\) of these will be set by the function call. They are set to the+-- columns of the pivots chosen by the LU decomposition of \(A\).+foreign import ccall "nmod_mat.h nmod_mat_can_solve_inner"+ nmod_mat_can_solve_inner :: Ptr CLong -> Ptr CLong -> Ptr CLong -> Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO CInt++-- | /nmod_mat_can_solve/ /X/ /A/ /B/ +-- +-- Solves the matrix-matrix equation \(AX = B\) over+-- \(\mathbb{Z} / p \mathbb{Z}\) where \(p\) is the modulus of \(X\) which+-- must be a prime number. \(X\), \(A\), and \(B\) should have the same+-- moduli.+-- +-- Returns \(1\) if a solution exists; otherwise returns \(0\) and sets the+-- elements of \(X\) to zero. If more than one solution exists, one of the+-- valid solutions is given.+-- +-- There are no restrictions on the shape of \(A\) and it may be singular.+foreign import ccall "nmod_mat.h nmod_mat_can_solve"+ nmod_mat_can_solve :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModMat -> IO CInt++-- | /nmod_mat_solve_vec/ /x/ /A/ /b/ +-- +-- Solves the matrix-vector equation \(Ax = b\) over+-- \(\mathbb{Z} / p \mathbb{Z}\) where \(p\) is the modulus of \(A\) which+-- must be a prime number.+-- +-- Returns \(1\) if \(A\) has full rank; otherwise returns \(0\) and sets+-- the elements of \(x\) to undefined values.+foreign import ccall "nmod_mat.h nmod_mat_solve_vec"+ nmod_mat_solve_vec :: Ptr CMpLimb -> Ptr CNModMat -> Ptr CMpLimb -> IO CInt++-- LU decomposition ------------------------------------------------------------++-- | /nmod_mat_lu/ /P/ /A/ /rank_check/ +-- +-- Computes a generalised LU decomposition \(LU = PA\) of a given matrix+-- \(A\), returning the rank of \(A\).+-- +-- If \(A\) is a nonsingular square matrix, it will be overwritten with a+-- unit diagonal lower triangular matrix \(L\) and an upper triangular+-- matrix \(U\) (the diagonal of \(L\) will not be stored explicitly).+-- +-- If \(A\) is an arbitrary matrix of rank \(r\), \(U\) will be in row+-- echelon form having \(r\) nonzero rows, and \(L\) will be lower+-- triangular but truncated to \(r\) columns, having implicit ones on the+-- \(r\) first entries of the main diagonal. All other entries will be+-- zero.+-- +-- If a nonzero value for @rank_check@ is passed, the function will abandon+-- the output matrix in an undefined state and return 0 if \(A\) is+-- detected to be rank-deficient.+-- +-- The /classical/ version uses direct Gaussian elimination. The+-- /classical_delayed/ version also uses Gaussian elimination, but performs+-- delayed modular reductions. The /recursive/ version uses block recursive+-- decomposition. The default function chooses an algorithm automatically.+foreign import ccall "nmod_mat.h nmod_mat_lu"+ nmod_mat_lu :: Ptr CLong -> Ptr CNModMat -> CInt -> IO CLong++-- Reduced row echelon form ----------------------------------------------------++-- | /nmod_mat_rref/ /A/ +-- +-- Puts \(A\) in reduced row echelon form and returns the rank of \(A\).+-- +-- The rref is computed by first obtaining an unreduced row echelon form+-- via LU decomposition and then solving an additional triangular system.+foreign import ccall "nmod_mat.h nmod_mat_rref"+ nmod_mat_rref :: Ptr CNModMat -> IO CLong++-- | /nmod_mat_reduce_row/ /A/ /P/ /L/ /n/ +-- +-- Reduce row n of the matrix \(A\), assuming the prior rows are in Gauss+-- form. However those rows may not be in order. The entry \(i\) of the+-- array \(P\) is the row of \(A\) which has a pivot in the \(i\)-th+-- column. If no such row exists, the entry of \(P\) will be \(-1\). The+-- function returns the column in which the \(n\)-th row has a pivot after+-- reduction. This will always be chosen to be the first available column+-- for a pivot from the left. This information is also updated in \(P\).+-- Entry \(i\) of the array \(L\) contains the number of possibly nonzero+-- columns of \(A\) row \(i\). This speeds up reduction in the case that+-- \(A\) is chambered on the right. Otherwise the entries of \(L\) can all+-- be set to the number of columns of \(A\). We require the entries of+-- \(L\) to be monotonic increasing.+foreign import ccall "nmod_mat.h nmod_mat_reduce_row"+ nmod_mat_reduce_row :: Ptr CNModMat -> Ptr CLong -> Ptr CLong -> CLong -> IO CLong++-- Nullspace -------------------------------------------------------------------++-- | /nmod_mat_nullspace/ /X/ /A/ +-- +-- Computes the nullspace of \(A\) and returns the nullity.+-- +-- More precisely, this function sets \(X\) to a maximum rank matrix such+-- that \(AX = 0\) and returns the rank of \(X\). The columns of \(X\) will+-- form a basis for the nullspace of \(A\).+-- +-- \(X\) must have sufficient space to store all basis vectors in the+-- nullspace.+-- +-- This function computes the reduced row echelon form and then reads off+-- the basis vectors.+foreign import ccall "nmod_mat.h nmod_mat_nullspace"+ nmod_mat_nullspace :: Ptr CNModMat -> Ptr CNModMat -> IO CLong++-- Transforms ------------------------------------------------------------------++-- | /nmod_mat_similarity/ /M/ /r/ /d/ +-- +-- Applies a similarity transform to the \(n\times n\) matrix \(M\)+-- in-place.+-- +-- If \(P\) is the \(n\times n\) identity matrix the zero entries of whose+-- row \(r\) (0-indexed) have been replaced by \(d\), this transform is+-- equivalent to \(M = P^{-1}MP\).+-- +-- Similarity transforms preserve the determinant, characteristic+-- polynomial and minimal polynomial.+-- +-- The value \(d\) is required to be reduced modulo the modulus of the+-- entries in the matrix.+foreign import ccall "nmod_mat.h nmod_mat_similarity"+ nmod_mat_similarity :: Ptr CNModMat -> CLong -> CULong -> IO ()++-- Characteristic polynomial ---------------------------------------------------++-- | /nmod_mat_charpoly_berkowitz/ /p/ /M/ +-- +-- Compute the characteristic polynomial \(p\) of the matrix \(M\). The+-- matrix is required to be square, otherwise an exception is raised. The+-- /danilevsky/ algorithm assumes that the modulus is prime.+foreign import ccall "nmod_mat.h nmod_mat_charpoly_berkowitz"+ nmod_mat_charpoly_berkowitz :: Ptr CNModPoly -> Ptr CNModMat -> IO ()++-- Minimal polynomial ----------------------------------------------------------++-- | /nmod_mat_minpoly/ /p/ /M/ +-- +-- Compute the minimal polynomial \(p\) of the matrix \(M\). The matrix is+-- required to be square, otherwise an exception is raised.+foreign import ccall "nmod_mat.h nmod_mat_minpoly"+ nmod_mat_minpoly :: Ptr CNModPoly -> Ptr CNModMat -> IO ()++-- Strong echelon form and Howell form -----------------------------------------++-- | /nmod_mat_strong_echelon_form/ /A/ +-- +-- Puts \(A\) into strong echelon form. The Howell form and the strong+-- echelon form are equal up to permutation of the rows, see+-- < [FieHof2014]> for a definition of the strong echelon form and the+-- algorithm used here. Note that < [FieHof2014]> defines strong echelon+-- form as a lower left normal form, while the implemented version returns+-- an upper right normal form, agreeing with the definition of Howell form+-- in < [StoMul1998]>.+-- +-- \(A\) must have at least as many rows as columns.+foreign import ccall "nmod_mat.h nmod_mat_strong_echelon_form"+ nmod_mat_strong_echelon_form :: Ptr CNModMat -> IO ()++-- | /nmod_mat_howell_form/ /A/ +-- +-- Puts \(A\) into Howell form and returns the number of non-zero rows. For+-- a definition of the Howell form see < [StoMul1998]>. The Howell form is+-- computed by first putting \(A\) into strong echelon form and then+-- ordering the rows.+-- +-- \(A\) must have at least as many rows as columns.+foreign import ccall "nmod_mat.h nmod_mat_howell_form"+ nmod_mat_howell_form :: Ptr CNModMat -> IO CLong+
+ src/Data/Number/Flint/NMod/Poly.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.NMod.Poly (+ module Data.Number.Flint.NMod.Poly.FFI+ ) where++import Data.Number.Flint.NMod.Poly.FFI
+ src/Data/Number/Flint/NMod/Poly/FFI.hsc view
@@ -0,0 +1,3412 @@+{-|+module : Data.Number.Flint.NMod.Poly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NMod.Poly.FFI (+ -- * Univariate polynomials over integers mod n (word-size n)+ -- * Types+ NModPoly (..)+ , CNModPoly (..)+ , newNModPoly+ , withNModPoly+ , withNewNModPoly+ -- * Helper functions+ , signed_mpn_sub_n+ -- * Memory management+ , nmod_poly_init+ , nmod_poly_init_preinv+ , nmod_poly_init_mod+ , nmod_poly_init2+ , nmod_poly_init2_preinv+ , nmod_poly_realloc+ , nmod_poly_clear+ , nmod_poly_fit_length+ , _nmod_poly_normalise+ -- * Polynomial properties+ , nmod_poly_length+ , nmod_poly_degree+ , nmod_poly_modulus+ , nmod_poly_max_bits+ -- * Assignment and basic manipulation+ , nmod_poly_set+ , nmod_poly_swap+ , nmod_poly_zero+ , nmod_poly_truncate+ , nmod_poly_set_trunc+ , _nmod_poly_reverse+ , nmod_poly_reverse+ -- * Randomization+ , nmod_poly_randtest+ , nmod_poly_randtest_irreducible+ , nmod_poly_randtest_monic+ , nmod_poly_randtest_monic_irreducible+ , nmod_poly_randtest_monic_primitive+ , nmod_poly_randtest_trinomial+ , nmod_poly_randtest_trinomial_irreducible+ , nmod_poly_randtest_pentomial+ , nmod_poly_randtest_pentomial_irreducible+ , nmod_poly_randtest_sparse_irreducible+ -- * Getting and setting coefficients+ , nmod_poly_get_coeff_ui+ , nmod_poly_set_coeff_ui+ -- * Input and output+ , nmod_poly_get_str+ , nmod_poly_get_str_pretty+ , nmod_poly_set_str+ , nmod_poly_print+ , nmod_poly_print_pretty+ , nmod_poly_fread+ , nmod_poly_fprint+ , nmod_poly_fprint_pretty+ , nmod_poly_read+ -- * Comparison+ , nmod_poly_equal+ , nmod_poly_equal_trunc+ , nmod_poly_is_zero+ , nmod_poly_is_one+ -- * Shifting+ , _nmod_poly_shift_left+ , nmod_poly_shift_left+ , _nmod_poly_shift_right+ , nmod_poly_shift_right+ -- * Addition and subtraction+ , _nmod_poly_add+ , nmod_poly_add+ , nmod_poly_add_series+ , _nmod_poly_sub+ , nmod_poly_sub+ , nmod_poly_sub_series+ , nmod_poly_neg+ -- * Scalar multiplication and division+ , nmod_poly_scalar_mul_nmod+ , _nmod_poly_make_monic+ , nmod_poly_make_monic+ -- * Bit packing and unpacking+ , _nmod_poly_bit_pack+ , _nmod_poly_bit_unpack+ , nmod_poly_bit_pack+ , nmod_poly_bit_unpack+ , _nmod_poly_KS2_pack1+ , _nmod_poly_KS2_pack+ , _nmod_poly_KS2_unpack1+ , _nmod_poly_KS2_unpack2+ , _nmod_poly_KS2_unpack3+ , _nmod_poly_KS2_unpack+ -- * KS2\/KS4 Reduction+ , _nmod_poly_KS2_reduce+ , _nmod_poly_KS2_recover_reduce1+ , _nmod_poly_KS2_recover_reduce2+ , _nmod_poly_KS2_recover_reduce2b+ , _nmod_poly_KS2_recover_reduce3+ , _nmod_poly_KS2_recover_reduce+ -- * Multiplication+ , _nmod_poly_mul_classical+ , nmod_poly_mul_classical+ , _nmod_poly_mullow_classical+ , nmod_poly_mullow_classical+ , _nmod_poly_mulhigh_classical+ , nmod_poly_mulhigh_classical+ , _nmod_poly_mul_KS+ , nmod_poly_mul_KS+ , _nmod_poly_mul_KS2+ , nmod_poly_mul_KS2+ , _nmod_poly_mul_KS4+ , nmod_poly_mul_KS4+ , _nmod_poly_mullow_KS+ , nmod_poly_mullow_KS+ , _nmod_poly_mul+ , nmod_poly_mul+ , _nmod_poly_mullow+ , nmod_poly_mullow+ , _nmod_poly_mulhigh+ , nmod_poly_mulhigh+ , _nmod_poly_mulmod+ , nmod_poly_mulmod+ , _nmod_poly_mulmod_preinv+ , nmod_poly_mulmod_preinv+ -- * Powering+ , _nmod_poly_pow_binexp+ , nmod_poly_pow_binexp+ , _nmod_poly_pow+ , nmod_poly_pow+ , _nmod_poly_pow_trunc_binexp+ , nmod_poly_pow_trunc_binexp+ , _nmod_poly_pow_trunc+ , nmod_poly_pow_trunc+ , _nmod_poly_powmod_ui_binexp+ , nmod_poly_powmod_ui_binexp+ , _nmod_poly_powmod_mpz_binexp+ , nmod_poly_powmod_mpz_binexp+ , _nmod_poly_powmod_fmpz_binexp+ , nmod_poly_powmod_fmpz_binexp+ , _nmod_poly_powmod_ui_binexp_preinv+ , nmod_poly_powmod_ui_binexp_preinv+ , _nmod_poly_powmod_mpz_binexp_preinv+ , nmod_poly_powmod_mpz_binexp_preinv+ , _nmod_poly_powmod_fmpz_binexp_preinv+ , nmod_poly_powmod_fmpz_binexp_preinv+ , _nmod_poly_powmod_x_ui_preinv+ , nmod_poly_powmod_x_ui_preinv+ , _nmod_poly_powmod_x_fmpz_preinv+ , nmod_poly_powmod_x_fmpz_preinv+ , _nmod_poly_powers_mod_preinv_naive+ , nmod_poly_powers_mod_naive+ , _nmod_poly_powers_mod_preinv_threaded_pool+ , _nmod_poly_powers_mod_preinv_threaded+ , nmod_poly_powers_mod_bsgs+ -- * Division+ , _nmod_poly_divrem_basecase+ , nmod_poly_divrem_basecase+ , _nmod_poly_divrem+ , nmod_poly_divrem+ , _nmod_poly_div+ , nmod_poly_div+ , _nmod_poly_rem_q1+ , _nmod_poly_rem+ , nmod_poly_rem+ , _nmod_poly_inv_series_basecase+ , nmod_poly_inv_series_basecase+ , _nmod_poly_inv_series_newton+ , nmod_poly_inv_series_newton+ , _nmod_poly_inv_series+ , nmod_poly_inv_series+ , _nmod_poly_div_series_basecase+ , nmod_poly_div_series_basecase+ , _nmod_poly_div_series+ , nmod_poly_div_series+ , _nmod_poly_div_newton_n_preinv+ , nmod_poly_div_newton_n_preinv+ , _nmod_poly_divrem_newton_n_preinv+ , nmod_poly_divrem_newton_n_preinv+ , _nmod_poly_div_root+ , nmod_poly_div_root+ -- * Divisibility testing+ , _nmod_poly_divides_classical+ , nmod_poly_divides_classical+ , _nmod_poly_divides+ , nmod_poly_divides+ -- * Derivative and integral+ , _nmod_poly_derivative+ , nmod_poly_derivative+ , _nmod_poly_integral+ , nmod_poly_integral+ -- * Evaluation+ , _nmod_poly_evaluate_nmod+ , nmod_poly_evaluate_nmod+ , nmod_poly_evaluate_mat_horner+ , nmod_poly_evaluate_mat_paterson_stockmeyer+ , nmod_poly_evaluate_mat+ -- * Multipoint evaluation+ , _nmod_poly_evaluate_nmod_vec_iter+ , nmod_poly_evaluate_nmod_vec_iter+ , _nmod_poly_evaluate_nmod_vec_fast_precomp+ , _nmod_poly_evaluate_nmod_vec_fast+ , nmod_poly_evaluate_nmod_vec_fast+ , _nmod_poly_evaluate_nmod_vec+ , nmod_poly_evaluate_nmod_vec+ -- * Interpolation+ , _nmod_poly_interpolate_nmod_vec+ , nmod_poly_interpolate_nmod_vec+ , _nmod_poly_interpolation_weights+ , _nmod_poly_interpolate_nmod_vec_fast_precomp+ , _nmod_poly_interpolate_nmod_vec_fast+ , nmod_poly_interpolate_nmod_vec_fast+ , _nmod_poly_interpolate_nmod_vec_newton+ , nmod_poly_interpolate_nmod_vec_newton+ , _nmod_poly_interpolate_nmod_vec_barycentric+ , nmod_poly_interpolate_nmod_vec_barycentric+ -- * Composition+ , _nmod_poly_compose_horner+ , nmod_poly_compose_horner+ --, _nmod_poly_compose_divconquer+ --, nmod_poly_compose_divconquer+ , _nmod_poly_compose+ , nmod_poly_compose+ -- * Taylor shift+ , _nmod_poly_taylor_shift_horner+ , nmod_poly_taylor_shift_horner+ , _nmod_poly_taylor_shift_convolution+ , nmod_poly_taylor_shift_convolution+ , _nmod_poly_taylor_shift+ , nmod_poly_taylor_shift+ -- * Modular composition+ , _nmod_poly_compose_mod_horner+ , nmod_poly_compose_mod_horner+ , _nmod_poly_compose_mod_brent_kung+ , nmod_poly_compose_mod_brent_kung+ , _nmod_poly_compose_mod_brent_kung_preinv+ , nmod_poly_compose_mod_brent_kung_preinv+ , _nmod_poly_reduce_matrix_mod_poly+ , _nmod_poly_precompute_matrix_worker+ , _nmod_poly_precompute_matrix+ , nmod_poly_precompute_matrix+ , _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker+ , _nmod_poly_compose_mod_brent_kung_precomp_preinv+ , nmod_poly_compose_mod_brent_kung_precomp_preinv+ , _nmod_poly_compose_mod_brent_kung_vec_preinv+ , nmod_poly_compose_mod_brent_kung_vec_preinv+ , _nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool+ , nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool+ , nmod_poly_compose_mod_brent_kung_vec_preinv_threaded+ , _nmod_poly_compose_mod+ , nmod_poly_compose_mod+ -- * Greatest common divisor+ , _nmod_poly_gcd_euclidean+ , nmod_poly_gcd_euclidean+ , _nmod_poly_hgcd+ , _nmod_poly_gcd_hgcd+ , nmod_poly_gcd_hgcd+ , _nmod_poly_gcd+ , nmod_poly_gcd+ , _nmod_poly_xgcd_euclidean+ , nmod_poly_xgcd_euclidean+ , _nmod_poly_xgcd_hgcd+ , nmod_poly_xgcd_hgcd+ , _nmod_poly_xgcd+ , nmod_poly_xgcd+ , _nmod_poly_resultant_euclidean+ , nmod_poly_resultant_euclidean+ , _nmod_poly_resultant_hgcd+ , nmod_poly_resultant_hgcd+ , _nmod_poly_resultant+ , nmod_poly_resultant+ , _nmod_poly_gcdinv+ , nmod_poly_gcdinv+ , _nmod_poly_invmod+ , nmod_poly_invmod+ -- * Power series composition+ , _nmod_poly_discriminant+ , nmod_poly_discriminant+ -- * Power series composition+ , _nmod_poly_compose_series+ , nmod_poly_compose_series+ -- * Power series reversion+ , _nmod_poly_revert_series_lagrange+ , nmod_poly_revert_series_lagrange+ , _nmod_poly_revert_series_lagrange_fast+ , nmod_poly_revert_series_lagrange_fast+ , _nmod_poly_revert_series_newton+ , nmod_poly_revert_series_newton+ , _nmod_poly_revert_series+ , nmod_poly_revert_series+ -- * Square roots+ , _nmod_poly_invsqrt_series+ , nmod_poly_invsqrt_series+ , _nmod_poly_sqrt_series+ , nmod_poly_sqrt_series+ , _nmod_poly_sqrt+ , nmod_poly_sqrt+ -- * Power sums+ , _nmod_poly_power_sums_naive+ , nmod_poly_power_sums_naive+ , _nmod_poly_power_sums_schoenhage+ , nmod_poly_power_sums_schoenhage+ , _nmod_poly_power_sums+ , nmod_poly_power_sums+ , _nmod_poly_power_sums_to_poly_naive+ , nmod_poly_power_sums_to_poly_naive+ , _nmod_poly_power_sums_to_poly_schoenhage+ , nmod_poly_power_sums_to_poly_schoenhage+ , _nmod_poly_power_sums_to_poly+ , nmod_poly_power_sums_to_poly+ -- * Transcendental functions+ , _nmod_poly_log_series+ , nmod_poly_log_series+ , _nmod_poly_exp_series+ , _nmod_poly_exp_expinv_series+ , nmod_poly_exp_series+ , _nmod_poly_atan_series+ , nmod_poly_atan_series+ , _nmod_poly_atanh_series+ , nmod_poly_atanh_series+ , _nmod_poly_asin_series+ , nmod_poly_asin_series+ , _nmod_poly_asinh_series+ , nmod_poly_asinh_series+ , _nmod_poly_sin_series+ , nmod_poly_sin_series+ , _nmod_poly_cos_series+ , nmod_poly_cos_series+ , _nmod_poly_tan_series+ , nmod_poly_tan_series+ , _nmod_poly_sinh_series+ , nmod_poly_sinh_series+ , _nmod_poly_cosh_series+ , nmod_poly_cosh_series+ , _nmod_poly_tanh_series+ , nmod_poly_tanh_series+ -- * Products+ , _nmod_poly_product_roots_nmod_vec+ , nmod_poly_product_roots_nmod_vec+ , nmod_poly_find_distinct_nonzero_roots+ -- * Subproduct trees+ , _nmod_poly_tree_alloc+ , _nmod_poly_tree_free+ , _nmod_poly_tree_build+ -- * Inflation and deflation+ , nmod_poly_inflate+ , nmod_poly_deflate+ , nmod_poly_deflation+ -- * Chinese Remaindering+ , nmod_poly_multi_crt_init+ , nmod_poly_multi_crt_precompute+ , nmod_poly_multi_crt_precomp+ , nmod_poly_multi_crt+ , nmod_poly_multi_crt_clear+ , _nmod_poly_multi_crt_local_size+ , _nmod_poly_multi_crt_run+ -- * Berlekamp-Massey Algorithm+ , nmod_berlekamp_massey_init+ , nmod_berlekamp_massey_clear+ , nmod_berlekamp_massey_start_over+ , nmod_berlekamp_massey_set_prime+ , nmod_berlekamp_massey_add_points+ , nmod_berlekamp_massey_reduce+ , nmod_berlekamp_massey_point_count+ , nmod_berlekamp_massey_points+ , nmod_berlekamp_massey_V_poly+ , nmod_berlekamp_massey_R_poly+) where ++-- Univariate polynomials over integers mod n (word-sizen) ---------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.NMod+import Data.Number.Flint.NMod.Types+import Data.Number.Flint.ThreadPool++#include <flint/nmod_poly.h>++-- Types -----------------------------------------------------------------------++newNModPoly n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> nmod_poly_init x n+ addForeignPtrFinalizer p_nmod_poly_clear x+ return $ NModPoly x++{-# INLINE withNModPoly #-}+withNModPoly (NModPoly x) f = do+ withForeignPtr x $ \px -> f px >>= return . (NModPoly x,)++{-# INLINE withNewNModPoly #-}+withNewNModPoly n f = do+ x <- newNModPoly n+ withNModPoly x $ \x -> f x++-- nmod_poly_crt_t -------------------------------------------------------------++data NModPolyMultiCRT = NModPolyCRT {-# UNPACK #-} !(ForeignPtr CNModPolyMultiCRT)+type CNModPolyMultiCRT = CFlint NModPolyMultiCRT++instance Storable CNModPolyMultiCRT where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_poly_multi_crt_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_poly_multi_crt_t}+ peek = undefined+ poke = undefined++-- nmod_berlekamp_massey_t -----------------------------------------------------++data NModBerlekampMassey = NModBerlekampMassey {-# UNPACK #-} !(ForeignPtr CNModBerlekampMassey)+type CNModBerlekampMassey = CFlint NModBerlekampMassey++instance Storable CNModBerlekampMassey where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_berlekamp_massey_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_berlekamp_massey_t}+ peek = undefined+ poke = undefined++newNModBerlekampMassey n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> nmod_berlekamp_massey_init x n+ addForeignPtrFinalizer p_nmod_berlekamp_massey_clear x+ return $ NModBerlekampMassey x++{-# INLINE withNModBerlekampMassey #-}+withNModBerlekampMassey (NModBerlekampMassey x) f = do+ withForeignPtr x $ \px -> f px >>= return . (NModBerlekampMassey x,)+ +-- Helper functions ------------------------------------------------------------++-- | /signed_mpn_sub_n/ /res/ /op1/ /op2/ /n/ +-- +-- If @op1 >= op2@ return 0 and set @res@ to @op1 - op2@ else return 1 and+-- set @res@ to @op2 - op1@.+foreign import ccall "nmod_poly.h signed_mpn_sub_n"+ signed_mpn_sub_n :: Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> IO CInt++-- Memory management -----------------------------------------------------------++-- | /nmod_poly_init/ /poly/ /n/ +-- +-- Initialises @poly@. It will have coefficients modulo~\`n\`.+foreign import ccall "nmod_poly.h nmod_poly_init"+ nmod_poly_init :: Ptr CNModPoly -> CMpLimb -> IO ()++-- | /nmod_poly_init_preinv/ /poly/ /n/ /ninv/ +-- +-- Initialises @poly@. It will have coefficients modulo~\`n\`. The caller+-- supplies a precomputed inverse limb generated by @n_preinvert_limb@.+foreign import ccall "nmod_poly.h nmod_poly_init_preinv"+ nmod_poly_init_preinv :: Ptr CNModPoly -> CMpLimb -> CMpLimb -> IO ()++-- | /nmod_poly_init_mod/ /poly/ /mod/ +-- +-- Initialises @poly@ using an already initialised modulus @mod@.+foreign import ccall "nmod_poly.h nmod_poly_init_mod"+ nmod_poly_init_mod :: Ptr CNModPoly -> Ptr CNMod -> IO ()++-- | /nmod_poly_init2/ /poly/ /n/ /alloc/ +-- +-- Initialises @poly@. It will have coefficients modulo~\`n\`. Up to+-- @alloc@ coefficients may be stored in @poly@.+foreign import ccall "nmod_poly.h nmod_poly_init2"+ nmod_poly_init2 :: Ptr CNModPoly -> CMpLimb -> CLong -> IO ()++-- | /nmod_poly_init2_preinv/ /poly/ /n/ /ninv/ /alloc/ +-- +-- Initialises @poly@. It will have coefficients modulo~\`n\`. The caller+-- supplies a precomputed inverse limb generated by @n_preinvert_limb@. Up+-- to @alloc@ coefficients may be stored in @poly@.+foreign import ccall "nmod_poly.h nmod_poly_init2_preinv"+ nmod_poly_init2_preinv :: Ptr CNModPoly -> CMpLimb -> CMpLimb -> CLong -> IO ()++-- | /nmod_poly_realloc/ /poly/ /alloc/ +-- +-- Reallocates @poly@ to the given length. If the current length is less+-- than @alloc@, the polynomial is truncated and normalised. If @alloc@ is+-- zero, the polynomial is cleared.+foreign import ccall "nmod_poly.h nmod_poly_realloc"+ nmod_poly_realloc :: Ptr CNModPoly -> CLong -> IO ()++-- | /nmod_poly_clear/ /poly/ +-- +-- Clears the polynomial and releases any memory it used. The polynomial+-- cannot be used again until it is initialised.+foreign import ccall "nmod_poly.h nmod_poly_clear"+ nmod_poly_clear :: Ptr CNModPoly -> IO ()++foreign import ccall "nmod_poly.h &nmod_poly_clear"+ p_nmod_poly_clear :: FunPtr (Ptr CNModPoly -> IO ())++-- | /nmod_poly_fit_length/ /poly/ /alloc/ +-- +-- Ensures @poly@ has space for at least @alloc@ coefficients. This+-- function only ever grows the allocated space, so no data loss can occur.+foreign import ccall "nmod_poly.h nmod_poly_fit_length"+ nmod_poly_fit_length :: Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_normalise/ /poly/ +-- +-- Internal function for normalising a polynomial so that the top+-- coefficient, if there is one at all, is not zero.+foreign import ccall "nmod_poly.h _nmod_poly_normalise"+ _nmod_poly_normalise :: Ptr CNModPoly -> IO ()++-- Polynomial properties -------------------------------------------------------++-- | /nmod_poly_length/ /poly/ +-- +-- Returns the length of the polynomial @poly@. The zero polynomial has+-- length zero.+foreign import ccall "nmod_poly.h nmod_poly_length"+ nmod_poly_length :: Ptr CNModPoly -> IO CLong++-- | /nmod_poly_degree/ /poly/ +-- +-- Returns the degree of the polynomial @poly@. The zero polynomial is+-- deemed to have degree~\`-1\`.+foreign import ccall "nmod_poly.h nmod_poly_degree"+ nmod_poly_degree :: Ptr CNModPoly -> IO CLong++-- | /nmod_poly_modulus/ /poly/ +-- +-- Returns the modulus of the polynomial @poly@. This will be a positive+-- integer.+foreign import ccall "nmod_poly.h nmod_poly_modulus"+ nmod_poly_modulus :: Ptr CNModPoly -> IO CMpLimb++-- | /nmod_poly_max_bits/ /poly/ +-- +-- Returns the maximum number of bits of any coefficient of @poly@.+foreign import ccall "nmod_poly.h nmod_poly_max_bits"+ nmod_poly_max_bits :: Ptr CNModPoly -> IO CFBitCnt++-- Assignment and basic manipulation -------------------------------------------++-- | /nmod_poly_set/ /a/ /b/ +-- +-- Sets @a@ to a copy of @b@.+foreign import ccall "nmod_poly.h nmod_poly_set"+ nmod_poly_set :: Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /nmod_poly_swap/ /poly1/ /poly2/ +-- +-- Efficiently swaps @poly1@ and @poly2@ by swapping pointers internally.+foreign import ccall "nmod_poly.h nmod_poly_swap"+ nmod_poly_swap :: Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /nmod_poly_zero/ /res/ +-- +-- Sets @res@ to the zero polynomial.+foreign import ccall "nmod_poly.h nmod_poly_zero"+ nmod_poly_zero :: Ptr CNModPoly -> IO ()++-- | /nmod_poly_truncate/ /poly/ /len/ +-- +-- Truncates @poly@ to the given length and normalises it. If @len@ is+-- greater than the current length of @poly@, then nothing happens.+foreign import ccall "nmod_poly.h nmod_poly_truncate"+ nmod_poly_truncate :: Ptr CNModPoly -> CLong -> IO ()++-- | /nmod_poly_set_trunc/ /res/ /poly/ /n/ +-- +-- Notionally truncate @poly@ to length \(n\) and set @res@ to the result.+-- The result is normalised.+foreign import ccall "nmod_poly.h nmod_poly_set_trunc"+ nmod_poly_set_trunc :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_reverse/ /output/ /input/ /len/ /m/ +-- +-- Sets @output@ to the reverse of @input@, which is of length @len@, but+-- thinking of it as a polynomial of length~@m@, notionally zero-padded if+-- necessary. The length~@m@ must be non-negative, but there are no other+-- restrictions. The polynomial @output@ must have space for @m@+-- coefficients. Supports aliasing of @output@ and @input@, but the+-- behaviour is undefined in case of partial overlap.+foreign import ccall "nmod_poly.h _nmod_poly_reverse"+ _nmod_poly_reverse :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> IO ()++-- | /nmod_poly_reverse/ /output/ /input/ /m/ +-- +-- Sets @output@ to the reverse of @input@, thinking of it as a polynomial+-- of length~@m@, notionally zero-padded if necessary). The length~@m@ must+-- be non-negative, but there are no other restrictions. The output+-- polynomial will be set to length~@m@ and then normalised.+foreign import ccall "nmod_poly.h nmod_poly_reverse"+ nmod_poly_reverse :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- Randomization ---------------------------------------------------------------++-- | /nmod_poly_randtest/ /poly/ /state/ /len/ +-- +-- Generates a random polynomial with length up to @len@.+foreign import ccall "nmod_poly.h nmod_poly_randtest"+ nmod_poly_randtest :: Ptr CNModPoly -> Ptr CFRandState -> CLong -> IO ()++-- | /nmod_poly_randtest_irreducible/ /poly/ /state/ /len/ +-- +-- Generates a random irreducible polynomial with length up to @len@.+foreign import ccall "nmod_poly.h nmod_poly_randtest_irreducible"+ nmod_poly_randtest_irreducible :: Ptr CNModPoly -> Ptr CFRandState -> CLong -> IO ()++-- | /nmod_poly_randtest_monic/ /poly/ /state/ /len/ +-- +-- Generates a random monic polynomial with length @len@.+foreign import ccall "nmod_poly.h nmod_poly_randtest_monic"+ nmod_poly_randtest_monic :: Ptr CNModPoly -> Ptr CFRandState -> CLong -> IO ()++-- | /nmod_poly_randtest_monic_irreducible/ /poly/ /state/ /len/ +-- +-- Generates a random monic irreducible polynomial with length @len@.+foreign import ccall "nmod_poly.h nmod_poly_randtest_monic_irreducible"+ nmod_poly_randtest_monic_irreducible :: Ptr CNModPoly -> Ptr CFRandState -> CLong -> IO ()++-- | /nmod_poly_randtest_monic_primitive/ /poly/ /state/ /len/ +-- +-- Generates a random monic irreducible primitive polynomial with length+-- @len@.+foreign import ccall "nmod_poly.h nmod_poly_randtest_monic_primitive"+ nmod_poly_randtest_monic_primitive :: Ptr CNModPoly -> Ptr CFRandState -> CLong -> IO ()++-- | /nmod_poly_randtest_trinomial/ /poly/ /state/ /len/ +-- +-- Generates a random monic trinomial of length @len@.+foreign import ccall "nmod_poly.h nmod_poly_randtest_trinomial"+ nmod_poly_randtest_trinomial :: Ptr CNModPoly -> Ptr CFRandState -> CLong -> IO ()++-- | /nmod_poly_randtest_trinomial_irreducible/ /poly/ /state/ /len/ /max_attempts/ +-- +-- Attempts to set @poly@ to a monic irreducible trinomial of length @len@.+-- It will generate up to @max_attempts@ trinomials in attempt to find an+-- irreducible one. If @max_attempts@ is @0@, then it will keep generating+-- trinomials until an irreducible one is found. Returns \(1\) if one is+-- found and \(0\) otherwise.+foreign import ccall "nmod_poly.h nmod_poly_randtest_trinomial_irreducible"+ nmod_poly_randtest_trinomial_irreducible :: Ptr CNModPoly -> Ptr CFRandState -> CLong -> CLong -> IO CInt++-- | /nmod_poly_randtest_pentomial/ /poly/ /state/ /len/ +-- +-- Generates a random monic pentomial of length @len@.+foreign import ccall "nmod_poly.h nmod_poly_randtest_pentomial"+ nmod_poly_randtest_pentomial :: Ptr CNModPoly -> Ptr CFRandState -> CLong -> IO ()++-- | /nmod_poly_randtest_pentomial_irreducible/ /poly/ /state/ /len/ /max_attempts/ +-- +-- Attempts to set @poly@ to a monic irreducible pentomial of length @len@.+-- It will generate up to @max_attempts@ pentomials in attempt to find an+-- irreducible one. If @max_attempts@ is @0@, then it will keep generating+-- pentomials until an irreducible one is found. Returns \(1\) if one is+-- found and \(0\) otherwise.+foreign import ccall "nmod_poly.h nmod_poly_randtest_pentomial_irreducible"+ nmod_poly_randtest_pentomial_irreducible :: Ptr CNModPoly -> Ptr CFRandState -> CLong -> CLong -> IO CInt++-- | /nmod_poly_randtest_sparse_irreducible/ /poly/ /state/ /len/ +-- +-- Attempts to set @poly@ to a sparse, monic irreducible polynomial with+-- length @len@. It attempts to find an irreducible trinomial. If that does+-- not succeed, it attempts to find a irreducible pentomial. If that fails,+-- then @poly@ is just set to a random monic irreducible polynomial.+foreign import ccall "nmod_poly.h nmod_poly_randtest_sparse_irreducible"+ nmod_poly_randtest_sparse_irreducible :: Ptr CNModPoly -> Ptr CFRandState -> CLong -> IO ()++-- Getting and setting coefficients --------------------------------------------++-- | /nmod_poly_get_coeff_ui/ /poly/ /j/ +-- +-- Returns the coefficient of @poly@ at index~@j@, where coefficients are+-- numbered with zero being the constant coefficient, and returns it as an+-- @ulong@. If @j@ refers to a coefficient beyond the end of @poly@, zero+-- is returned.+foreign import ccall "nmod_poly.h nmod_poly_get_coeff_ui"+ nmod_poly_get_coeff_ui :: Ptr CNModPoly -> CLong -> IO CULong++-- | /nmod_poly_set_coeff_ui/ /poly/ /j/ /c/ +-- +-- Sets the coefficient of @poly@ at index @j@, where coefficients are+-- numbered with zero being the constant coefficient, to the value @c@+-- reduced modulo the modulus of @poly@. If @j@ refers to a coefficient+-- beyond the current end of @poly@, the polynomial is first resized, with+-- intervening coefficients being set to zero.+foreign import ccall "nmod_poly.h nmod_poly_set_coeff_ui"+ nmod_poly_set_coeff_ui :: Ptr CNModPoly -> CLong -> CULong -> IO ()++-- Input and output ------------------------------------------------------------++-- | /nmod_poly_get_str/ /poly/ +-- +-- Writes @poly@ to a string representation. The format is as described for+-- @nmod_poly_print@. The string must be freed by the user when finished.+-- For this it is sufficient to call @flint_free@.+foreign import ccall "nmod_poly.h nmod_poly_get_str"+ nmod_poly_get_str :: Ptr CNModPoly -> IO CString++-- | /nmod_poly_get_str_pretty/ /poly/ /x/ +-- +-- Writes @poly@ to a pretty string representation. The format is as+-- described for @nmod_poly_print_pretty@. The string must be freed by the+-- user when finished. For this it is sufficient to call @flint_free@.+-- +-- It is assumed that the top coefficient is non-zero.+foreign import ccall "nmod_poly.h nmod_poly_get_str_pretty"+ nmod_poly_get_str_pretty :: Ptr CNModPoly -> CString -> IO CString++-- | /nmod_poly_set_str/ /poly/ /s/ +-- +-- Reads @poly@ from a string @s@. The format is as described for+-- @nmod_poly_print@. If a polynomial in the correct format is read, a+-- positive value is returned, otherwise a non-positive value is returned.+foreign import ccall "nmod_poly.h nmod_poly_set_str"+ nmod_poly_set_str :: Ptr CNModPoly -> CString -> IO CInt++-- | /nmod_poly_print/ /a/ +-- +-- Prints the polynomial to @stdout@. The length is printed, followed by a+-- space, then the modulus. If the length is zero this is all that is+-- printed, otherwise two spaces followed by a space separated list of+-- coefficients is printed, beginning with the constant coefficient.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+nmod_poly_print :: Ptr CNModPoly -> IO CInt+nmod_poly_print a = printCStr nmod_poly_get_str a++-- | /nmod_poly_print_pretty/ /a/ /x/ +-- +-- Prints the polynomial to @stdout@ using the string @x@ to represent the+-- indeterminate.+-- +-- It is assumed that the top coefficient is non-zero.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+nmod_poly_print_pretty :: Ptr CNModPoly -> CString -> IO CInt+nmod_poly_print_pretty a x = printCStr (flip nmod_poly_get_str_pretty x) a+ +-- | /nmod_poly_fread/ /f/ /poly/ +-- +-- Reads @poly@ from the file stream @f@. If this is a file that has just+-- been written, the file should be closed then opened again. The format is+-- as described for @nmod_poly_print@. If a polynomial in the correct+-- format is read, a positive value is returned, otherwise a non-positive+-- value is returned.+foreign import ccall "nmod_poly.h nmod_poly_fread"+ nmod_poly_fread :: Ptr CFile -> Ptr CNModPoly -> IO CInt++-- | /nmod_poly_fprint/ /f/ /poly/ +-- +-- Writes a polynomial to the file stream @f@. If this is a file then the+-- file should be closed and reopened before being read. The format is as+-- described for @nmod_poly_print@. If the polynomial is written correctly,+-- a positive value is returned, otherwise a non-positive value is+-- returned.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "nmod_poly.h nmod_poly_fprint"+ nmod_poly_fprint :: Ptr CFile -> Ptr CNModPoly -> IO CInt++-- | /nmod_poly_fprint_pretty/ /f/ /poly/ /x/ +-- +-- Writes a polynomial to the file stream @f@. If this is a file then the+-- file should be closed and reopened before being read. The format is as+-- described for @nmod_poly_print_pretty@. If the polynomial is written+-- correctly, a positive value is returned, otherwise a non-positive value+-- is returned.+-- +-- It is assumed that the top coefficient is non-zero.+-- +-- In case of success, returns a positive value. In case of failure,+-- returns a non-positive value.+foreign import ccall "nmod_poly.h nmod_poly_fprint_pretty"+ nmod_poly_fprint_pretty :: Ptr CFile -> Ptr CNModPoly -> CString -> IO CInt++-- | /nmod_poly_read/ /poly/ +-- +-- Read @poly@ from @stdin@. The format is as described for+-- @nmod_poly_print@. If a polynomial in the correct format is read, a+-- positive value is returned, otherwise a non-positive value is returned.+foreign import ccall "nmod_poly.h nmod_poly_read"+ nmod_poly_read :: Ptr CNModPoly -> IO CInt++-- Comparison ------------------------------------------------------------------++-- | /nmod_poly_equal/ /a/ /b/ +-- +-- Returns~\`1\` if the polynomials are equal, otherwise~\`0\`.+foreign import ccall "nmod_poly.h nmod_poly_equal"+ nmod_poly_equal :: Ptr CNModPoly -> Ptr CNModPoly -> IO CInt++-- | /nmod_poly_equal_trunc/ /poly1/ /poly2/ /n/ +-- +-- Notionally truncate @poly1@ and @poly2@ to length \(n\) and return \(1\)+-- if the truncations are equal, otherwise return \(0\).+foreign import ccall "nmod_poly.h nmod_poly_equal_trunc"+ nmod_poly_equal_trunc :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO CInt++-- | /nmod_poly_is_zero/ /poly/ +-- +-- Returns~\`1\` if the polynomial @poly@ is the zero polynomial, otherwise+-- returns~\`0\`.+foreign import ccall "nmod_poly.h nmod_poly_is_zero"+ nmod_poly_is_zero :: Ptr CNModPoly -> IO CInt++-- | /nmod_poly_is_one/ /poly/ +-- +-- Returns~\`1\` if the polynomial @poly@ is the constant polynomial 1,+-- otherwise returns~\`0\`.+foreign import ccall "nmod_poly.h nmod_poly_is_one"+ nmod_poly_is_one :: Ptr CNModPoly -> IO CInt++-- Shifting --------------------------------------------------------------------++-- | /_nmod_poly_shift_left/ /res/ /poly/ /len/ /k/ +-- +-- Sets @(res, len + k)@ to @(poly, len)@ shifted left by @k@ coefficients.+-- Assumes that @res@ has space for @len + k@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_shift_left"+ _nmod_poly_shift_left :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> IO ()++-- | /nmod_poly_shift_left/ /res/ /poly/ /k/ +-- +-- Sets @res@ to @poly@ shifted left by @k@ coefficients, i.e.multiplied by+-- \(x^k\).+foreign import ccall "nmod_poly.h nmod_poly_shift_left"+ nmod_poly_shift_left :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_shift_right/ /res/ /poly/ /len/ /k/ +-- +-- Sets @(res, len - k)@ to @(poly, len)@ shifted left by @k@ coefficients.+-- It is assumed that @k \<= len@ and that @res@ has space for at least+-- @len - k@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_shift_right"+ _nmod_poly_shift_right :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> IO ()++-- | /nmod_poly_shift_right/ /res/ /poly/ /k/ +-- +-- Sets @res@ to @poly@ shifted right by @k@ coefficients, i.e.divide by+-- \(x^k\) and throws away the remainder. If @k@ is greater than or equal+-- to the length of @poly@, the result is the zero polynomial.+foreign import ccall "nmod_poly.h nmod_poly_shift_right"+ nmod_poly_shift_right :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- Addition and subtraction ----------------------------------------------------++-- | /_nmod_poly_add/ /res/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- +-- Sets @res@ to the sum of @(poly1, len1)@ and @(poly2, len2)@. There are+-- no restrictions on the lengths.+foreign import ccall "nmod_poly.h _nmod_poly_add"+ _nmod_poly_add :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_add/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the sum of @poly1@ and @poly2@.+foreign import ccall "nmod_poly.h nmod_poly_add"+ nmod_poly_add :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /nmod_poly_add_series/ /res/ /poly1/ /poly2/ /n/ +-- +-- Notionally truncate @poly1@ and @poly2@ to length \(n\) and set @res@ to+-- the sum.+foreign import ccall "nmod_poly.h nmod_poly_add_series"+ nmod_poly_add_series :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_sub/ /res/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- +-- Sets @res@ to the difference of @(poly1, len1)@ and @(poly2, len2)@.+-- There are no restrictions on the lengths.+foreign import ccall "nmod_poly.h _nmod_poly_sub"+ _nmod_poly_sub :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_sub/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the difference of @poly1@ and @poly2@.+foreign import ccall "nmod_poly.h nmod_poly_sub"+ nmod_poly_sub :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /nmod_poly_sub_series/ /res/ /poly1/ /poly2/ /n/ +-- +-- Notionally truncate @poly1@ and @poly2@ to length \(n\) and set @res@ to+-- the difference.+foreign import ccall "nmod_poly.h nmod_poly_sub_series"+ nmod_poly_sub_series :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /nmod_poly_neg/ /res/ /poly/ +-- +-- Sets @res@ to the negation of @poly@.+foreign import ccall "nmod_poly.h nmod_poly_neg"+ nmod_poly_neg :: Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- Scalar multiplication and division ------------------------------------------++-- | /nmod_poly_scalar_mul_nmod/ /res/ /poly/ /c/ +-- +-- Sets @res@ to @(poly, len)@ multiplied by~\`c\`, where~\`c\` is reduced+-- modulo the modulus of @poly@.+foreign import ccall "nmod_poly.h nmod_poly_scalar_mul_nmod"+ nmod_poly_scalar_mul_nmod :: Ptr CNModPoly -> Ptr CNModPoly -> CULong -> IO ()++-- | /_nmod_poly_make_monic/ /output/ /input/ /len/ /mod/ +-- +-- Sets @output@ to be the scalar multiple of @input@ of length @len > 0@+-- that has leading coefficient one, if such a polynomial exists. If the+-- leading coefficient of @input@ is not invertible, @output@ is set to the+-- multiple of @input@ whose leading coefficient is the greatest common+-- divisor of the leading coefficient and the modulus of @input@.+foreign import ccall "nmod_poly.h _nmod_poly_make_monic"+ _nmod_poly_make_monic :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_make_monic/ /output/ /input/ +-- +-- Sets @output@ to be the scalar multiple of @input@ with leading+-- coefficient one, if such a polynomial exists. If @input@ is zero an+-- exception is raised. If the leading coefficient of @input@ is not+-- invertible, @output@ is set to the multiple of @input@ whose leading+-- coefficient is the greatest common divisor of the leading coefficient+-- and the modulus of @input@.+foreign import ccall "nmod_poly.h nmod_poly_make_monic"+ nmod_poly_make_monic :: Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- Bit packing and unpacking ---------------------------------------------------++-- | /_nmod_poly_bit_pack/ /res/ /poly/ /len/ /bits/ +-- +-- Packs @len@ coefficients of @poly@ into fields of the given number of+-- bits in the large integer @res@, i.e.evaluates @poly@ at @2^bits@ and+-- store the result in @res@. Assumes @len > 0@ and @bits > 0@. Also+-- assumes that no coefficient of @poly@ is bigger than @bits\/2@ bits. We+-- also assume @bits \< 3 * FLINT_BITS@.+foreign import ccall "nmod_poly.h _nmod_poly_bit_pack"+ _nmod_poly_bit_pack :: Ptr CMp -> Ptr CMp -> CLong -> CFBitCnt -> IO ()++-- | /_nmod_poly_bit_unpack/ /res/ /len/ /mpn/ /bits/ /mod/ +-- +-- Unpacks @len@ coefficients stored in the big integer @mpn@ in bit fields+-- of the given number of bits, reduces them modulo the given modulus, then+-- stores them in the polynomial @res@. We assume @len > 0@ and+-- @3 * FLINT_BITS > bits > 0@. There are no restrictions on the size of+-- the actual coefficients as stored within the bitfields.+foreign import ccall "nmod_poly.h _nmod_poly_bit_unpack"+ _nmod_poly_bit_unpack :: Ptr CMp -> CLong -> Ptr CMp -> CULong -> Ptr CNMod -> IO ()++-- | /nmod_poly_bit_pack/ /f/ /poly/ /bit_size/ +-- +-- Packs @poly@ into bitfields of size @bit_size@, writing the result to+-- @f@.+foreign import ccall "nmod_poly.h nmod_poly_bit_pack"+ nmod_poly_bit_pack :: Ptr CFmpz -> Ptr CNModPoly -> CFBitCnt -> IO ()++-- | /nmod_poly_bit_unpack/ /poly/ /f/ /bit_size/ +-- +-- Unpacks the polynomial from fields of size @bit_size@ as represented by+-- the integer @f@.+foreign import ccall "nmod_poly.h nmod_poly_bit_unpack"+ nmod_poly_bit_unpack :: Ptr CNModPoly -> Ptr CFmpz -> CFBitCnt -> IO ()++-- | /_nmod_poly_KS2_pack1/ /res/ /op/ /n/ /s/ /b/ /k/ /r/ +-- +-- Same as @_nmod_poly_KS2_pack@, but requires @b \<= FLINT_BITS@.+foreign import ccall "nmod_poly.h _nmod_poly_KS2_pack1"+ _nmod_poly_KS2_pack1 :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> CULong -> CULong -> CLong -> IO ()++-- | /_nmod_poly_KS2_pack/ /res/ /op/ /n/ /s/ /b/ /k/ /r/ +-- +-- Bit packing routine used by KS2 and KS4 multiplication.+foreign import ccall "nmod_poly.h _nmod_poly_KS2_pack"+ _nmod_poly_KS2_pack :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> CULong -> CULong -> CLong -> IO ()++-- | /_nmod_poly_KS2_unpack1/ /res/ /op/ /n/ /b/ /k/ +-- +-- Same as @_nmod_poly_KS2_unpack@, but requires @b \<= FLINT_BITS@ (i.e.+-- writes one word per coefficient).+foreign import ccall "nmod_poly.h _nmod_poly_KS2_unpack1"+ _nmod_poly_KS2_unpack1 :: Ptr CMp -> Ptr CMp -> CLong -> CULong -> CULong -> IO ()++-- | /_nmod_poly_KS2_unpack2/ /res/ /op/ /n/ /b/ /k/ +-- +-- Same as @_nmod_poly_KS2_unpack@, but requires+-- @FLINT_BITS \< b \<= 2 * FLINT_BITS@ (i.e. writes two words per+-- coefficient).+foreign import ccall "nmod_poly.h _nmod_poly_KS2_unpack2"+ _nmod_poly_KS2_unpack2 :: Ptr CMp -> Ptr CMp -> CLong -> CULong -> CULong -> IO ()++-- | /_nmod_poly_KS2_unpack3/ /res/ /op/ /n/ /b/ /k/ +-- +-- Same as @_nmod_poly_KS2_unpack@, but requires+-- @2 * FLINT_BITS \< b \< 3 * FLINT_BITS@ (i.e. writes three words per+-- coefficient).+foreign import ccall "nmod_poly.h _nmod_poly_KS2_unpack3"+ _nmod_poly_KS2_unpack3 :: Ptr CMp -> Ptr CMp -> CLong -> CULong -> CULong -> IO ()++-- | /_nmod_poly_KS2_unpack/ /res/ /op/ /n/ /b/ /k/ +-- +-- Bit unpacking code used by KS2 and KS4 multiplication.+foreign import ccall "nmod_poly.h _nmod_poly_KS2_unpack"+ _nmod_poly_KS2_unpack :: Ptr CMp -> Ptr CMp -> CLong -> CULong -> CULong -> IO ()++-- KS2\/KS4 Reduction ----------------------------------------------------------++-- | /_nmod_poly_KS2_reduce/ /res/ /s/ /op/ /n/ /w/ /mod/ +-- +-- Reduction code used by KS2 and KS4 multiplication.+foreign import ccall "nmod_poly.h _nmod_poly_KS2_reduce"+ _nmod_poly_KS2_reduce :: Ptr CMp -> CLong -> Ptr CMp -> CLong -> CULong -> Ptr CNMod -> IO ()++-- | /_nmod_poly_KS2_recover_reduce1/ /res/ /s/ /op1/ /op2/ /n/ /b/ /mod/ +-- +-- Same as @_nmod_poly_KS2_recover_reduce@, but requires+-- @0 \< 2 * b \<= FLINT_BITS@.+foreign import ccall "nmod_poly.h _nmod_poly_KS2_recover_reduce1"+ _nmod_poly_KS2_recover_reduce1 :: Ptr CMp -> CLong -> Ptr CMp -> Ptr CMp -> CLong -> CULong -> Ptr CNMod -> IO ()++-- | /_nmod_poly_KS2_recover_reduce2/ /res/ /s/ /op1/ /op2/ /n/ /b/ /mod/ +-- +-- Same as @_nmod_poly_KS2_recover_reduce@, but requires+-- @FLINT_BITS \< 2 * b \< 2*FLINT_BITS@.+foreign import ccall "nmod_poly.h _nmod_poly_KS2_recover_reduce2"+ _nmod_poly_KS2_recover_reduce2 :: Ptr CMp -> CLong -> Ptr CMp -> Ptr CMp -> CLong -> CULong -> Ptr CNMod -> IO ()++-- | /_nmod_poly_KS2_recover_reduce2b/ /res/ /s/ /op1/ /op2/ /n/ /b/ /mod/ +-- +-- Same as @_nmod_poly_KS2_recover_reduce@, but requires @b == FLINT_BITS@.+foreign import ccall "nmod_poly.h _nmod_poly_KS2_recover_reduce2b"+ _nmod_poly_KS2_recover_reduce2b :: Ptr CMp -> CLong -> Ptr CMp -> Ptr CMp -> CLong -> CULong -> Ptr CNMod -> IO ()++-- | /_nmod_poly_KS2_recover_reduce3/ /res/ /s/ /op1/ /op2/ /n/ /b/ /mod/ +-- +-- Same as @_nmod_poly_KS2_recover_reduce@, but requires+-- @2 * FLINT_BITS \< 2 * b \<= 3 * FLINT_BITS@.+foreign import ccall "nmod_poly.h _nmod_poly_KS2_recover_reduce3"+ _nmod_poly_KS2_recover_reduce3 :: Ptr CMp -> CLong -> Ptr CMp -> Ptr CMp -> CLong -> CULong -> Ptr CNMod -> IO ()++-- | /_nmod_poly_KS2_recover_reduce/ /res/ /s/ /op1/ /op2/ /n/ /b/ /mod/ +-- +-- Reduction code used by KS4 multiplication.+foreign import ccall "nmod_poly.h _nmod_poly_KS2_recover_reduce"+ _nmod_poly_KS2_recover_reduce :: Ptr CMp -> CLong -> Ptr CMp -> Ptr CMp -> CLong -> CULong -> Ptr CNMod -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /_nmod_poly_mul_classical/ /res/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- +-- Sets @(res, len1 + len2 - 1)@ to the product of @(poly1, len1)@ and+-- @(poly2, len2)@. Assumes @len1 >= len2 > 0@. Aliasing of inputs and+-- output is not permitted.+foreign import ccall "nmod_poly.h _nmod_poly_mul_classical"+ _nmod_poly_mul_classical :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_mul_classical/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@.+foreign import ccall "nmod_poly.h nmod_poly_mul_classical"+ nmod_poly_mul_classical :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_mullow_classical/ /res/ /poly1/ /len1/ /poly2/ /len2/ /trunc/ /mod/ +-- +-- Sets @res@ to the lower @trunc@ coefficients of the product of+-- @(poly1, len1)@ and @(poly2, len2)@. Assumes that @len1 >= len2 > 0@ and+-- @trunc > 0@. Aliasing of inputs and output is not permitted.+foreign import ccall "nmod_poly.h _nmod_poly_mullow_classical"+ _nmod_poly_mullow_classical :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_mullow_classical/ /res/ /poly1/ /poly2/ /trunc/ +-- +-- Sets @res@ to the lower @trunc@ coefficients of the product of @poly1@+-- and @poly2@.+foreign import ccall "nmod_poly.h nmod_poly_mullow_classical"+ nmod_poly_mullow_classical :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_mulhigh_classical/ /res/ /poly1/ /len1/ /poly2/ /len2/ /start/ /mod/ +-- +-- Computes the product of @(poly1, len1)@ and @(poly2, len2)@ and writes+-- the coefficients from @start@ onwards into the high coefficients of+-- @res@, the remaining coefficients being arbitrary but reduced. Assumes+-- that @len1 >= len2 > 0@. Aliasing of inputs and output is not permitted.+foreign import ccall "nmod_poly.h _nmod_poly_mulhigh_classical"+ _nmod_poly_mulhigh_classical :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_mulhigh_classical/ /res/ /poly1/ /poly2/ /start/ +-- +-- Computes the product of @poly1@ and @poly2@ and writes the coefficients+-- from @start@ onwards into the high coefficients of @res@, the remaining+-- coefficients being arbitrary but reduced.+foreign import ccall "nmod_poly.h nmod_poly_mulhigh_classical"+ nmod_poly_mulhigh_classical :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_mul_KS/ /out/ /in1/ /len1/ /in2/ /len2/ /bits/ /mod/ +-- +-- Sets @res@ to the product of @in1@ and @in2@ assuming the output+-- coefficients are at most the given number of bits wide. If @bits@ is set+-- to \(0\) an appropriate value is computed automatically. Assumes that+-- @len1 >= len2 > 0@.+foreign import ccall "nmod_poly.h _nmod_poly_mul_KS"+ _nmod_poly_mul_KS :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> CFBitCnt -> Ptr CNMod -> IO ()++-- | /nmod_poly_mul_KS/ /res/ /poly1/ /poly2/ /bits/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@ assuming the output+-- coefficients are at most the given number of bits wide. If @bits@ is set+-- to \(0\) an appropriate value is computed automatically.+foreign import ccall "nmod_poly.h nmod_poly_mul_KS"+ nmod_poly_mul_KS :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> CFBitCnt -> IO ()++-- | /_nmod_poly_mul_KS2/ /res/ /op1/ /n1/ /op2/ /n2/ /mod/ +-- +-- Sets @res@ to the product of @op1@ and @op2@. Assumes that+-- @len1 >= len2 > 0@.+foreign import ccall "nmod_poly.h _nmod_poly_mul_KS2"+ _nmod_poly_mul_KS2 :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_mul_KS2/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@.+foreign import ccall "nmod_poly.h nmod_poly_mul_KS2"+ nmod_poly_mul_KS2 :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_mul_KS4/ /res/ /op1/ /n1/ /op2/ /n2/ /mod/ +-- +-- Sets @res@ to the product of @op1@ and @op2@. Assumes that+-- @len1 >= len2 > 0@.+foreign import ccall "nmod_poly.h _nmod_poly_mul_KS4"+ _nmod_poly_mul_KS4 :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_mul_KS4/ /res/ /poly1/ /poly2/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@.+foreign import ccall "nmod_poly.h nmod_poly_mul_KS4"+ nmod_poly_mul_KS4 :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_mullow_KS/ /out/ /in1/ /len1/ /in2/ /len2/ /bits/ /n/ /mod/ +-- +-- Sets @out@ to the low \(n\) coefficients of @in1@ of length @len1@ times+-- @in2@ of length @len2@. The output must have space for @n@ coefficients.+-- We assume that @len1 >= len2 > 0@ and that @0 \< n \<= len1 + len2 - 1@.+foreign import ccall "nmod_poly.h _nmod_poly_mullow_KS"+ _nmod_poly_mullow_KS :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> CFBitCnt -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_mullow_KS/ /res/ /poly1/ /poly2/ /bits/ /n/ +-- +-- Set @res@ to the low \(n\) coefficients of @in1@ of length @len1@ times+-- @in2@ of length @len2@.+foreign import ccall "nmod_poly.h nmod_poly_mullow_KS"+ nmod_poly_mullow_KS :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> CFBitCnt -> CLong -> IO ()++-- | /_nmod_poly_mul/ /res/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- +-- Sets @res@ to the product of @poly1@ of length @len1@ and @poly2@ of+-- length @len2@. Assumes @len1 >= len2 > 0@. No aliasing is permitted+-- between the inputs and the output.+foreign import ccall "nmod_poly.h _nmod_poly_mul"+ _nmod_poly_mul :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_mul/ /res/ /poly/ /poly2/ +-- +-- Sets @res@ to the product of @poly1@ and @poly2@.+foreign import ccall "nmod_poly.h nmod_poly_mul"+ nmod_poly_mul :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_mullow/ /res/ /poly1/ /len1/ /poly2/ /len2/ /n/ /mod/ +-- +-- Sets @res@ to the first @n@ coefficients of the product of @poly1@ of+-- length @len1@ and @poly2@ of length @len2@. It is assumed that+-- @0 \< n \<= len1 + len2 - 1@ and that @len1 >= len2 > 0@. No aliasing of+-- inputs and output is permitted.+foreign import ccall "nmod_poly.h _nmod_poly_mullow"+ _nmod_poly_mullow :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_mullow/ /res/ /poly1/ /poly2/ /trunc/ +-- +-- Sets @res@ to the first @trunc@ coefficients of the product of @poly1@+-- and @poly2@.+foreign import ccall "nmod_poly.h nmod_poly_mullow"+ nmod_poly_mullow :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_mulhigh/ /res/ /poly1/ /len1/ /poly2/ /len2/ /n/ /mod/ +-- +-- Sets all but the low \(n\) coefficients of @res@ to the corresponding+-- coefficients of the product of @poly1@ of length @len1@ and @poly2@ of+-- length @len2@, the other coefficients being arbitrary. It is assumed+-- that @len1 >= len2 > 0@ and that @0 \< n \<= len1 + len2 - 1@. Aliasing+-- of inputs and output is not permitted.+foreign import ccall "nmod_poly.h _nmod_poly_mulhigh"+ _nmod_poly_mulhigh :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_mulhigh/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets all but the low \(n\) coefficients of @res@ to the corresponding+-- coefficients of the product of @poly1@ and @poly2@, the remaining+-- coefficients being arbitrary.+foreign import ccall "nmod_poly.h nmod_poly_mulhigh"+ nmod_poly_mulhigh :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_mulmod/ /res/ /poly1/ /len1/ /poly2/ /len2/ /f/ /lenf/ /mod/ +-- +-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+-- +-- It is required that @len1 + len2 - lenf > 0@, which is equivalent to+-- requiring that the result will actually be reduced. Otherwise, simply+-- use @_nmod_poly_mul@ instead.+-- +-- Aliasing of @f@ and @res@ is not permitted.+foreign import ccall "nmod_poly.h _nmod_poly_mulmod"+ _nmod_poly_mulmod :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_mulmod/ /res/ /poly1/ /poly2/ /f/ +-- +-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+foreign import ccall "nmod_poly.h nmod_poly_mulmod"+ nmod_poly_mulmod :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_mulmod_preinv/ /res/ /poly1/ /len1/ /poly2/ /len2/ /f/ /lenf/ /finv/ /lenfinv/ /mod/ +-- +-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@.+-- +-- It is required that @finv@ is the inverse of the reverse of @f@ mod+-- @x^lenf@. It is required that @len1 + len2 - lenf > 0@, which is+-- equivalent to requiring that the result will actually be reduced. It is+-- required that @len1 \< lenf@ and @len2 \< lenf@. Otherwise, simply use+-- @_nmod_poly_mul@ instead.+-- +-- Aliasing of @\`res@ with any of the inputs is not permitted.+foreign import ccall "nmod_poly.h _nmod_poly_mulmod_preinv"+ _nmod_poly_mulmod_preinv :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_mulmod_preinv/ /res/ /poly1/ /poly2/ /f/ /finv/ +-- +-- Sets @res@ to the remainder of the product of @poly1@ and @poly2@ upon+-- polynomial division by @f@. @finv@ is the inverse of the reverse of @f@.+-- It is required that @poly1@ and @poly2@ are reduced modulo @f@.+foreign import ccall "nmod_poly.h nmod_poly_mulmod_preinv"+ nmod_poly_mulmod_preinv :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- Powering --------------------------------------------------------------------++-- | /_nmod_poly_pow_binexp/ /res/ /poly/ /len/ /e/ /mod/ +-- +-- Raises @poly@ of length @len@ to the power @e@ and sets @res@ to the+-- result. We require that @res@ has enough space for @(len - 1)*e + 1@+-- coefficients. Assumes that @len > 0@, @e > 1@. Aliasing is not+-- permitted. Uses the binary exponentiation method.+foreign import ccall "nmod_poly.h _nmod_poly_pow_binexp"+ _nmod_poly_pow_binexp :: Ptr CMp -> Ptr CMp -> CLong -> CULong -> Ptr CNMod -> IO ()++-- | /nmod_poly_pow_binexp/ /res/ /poly/ /e/ +-- +-- Raises @poly@ to the power @e@ and sets @res@ to the result. Uses the+-- binary exponentiation method.+foreign import ccall "nmod_poly.h nmod_poly_pow_binexp"+ nmod_poly_pow_binexp :: Ptr CNModPoly -> Ptr CNModPoly -> CULong -> IO ()++-- | /_nmod_poly_pow/ /res/ /poly/ /len/ /e/ /mod/ +-- +-- Raises @poly@ of length @len@ to the power @e@ and sets @res@ to the+-- result. We require that @res@ has enough space for @(len - 1)*e + 1@+-- coefficients. Assumes that @len > 0@, @e > 1@. Aliasing is not+-- permitted.+foreign import ccall "nmod_poly.h _nmod_poly_pow"+ _nmod_poly_pow :: Ptr CMp -> Ptr CMp -> CLong -> CULong -> Ptr CNMod -> IO ()++-- | /nmod_poly_pow/ /res/ /poly/ /e/ +-- +-- Raises @poly@ to the power @e@ and sets @res@ to the result.+foreign import ccall "nmod_poly.h nmod_poly_pow"+ nmod_poly_pow :: Ptr CNModPoly -> Ptr CNModPoly -> CULong -> IO ()++-- | /_nmod_poly_pow_trunc_binexp/ /res/ /poly/ /e/ /trunc/ /mod/ +-- +-- Sets @res@ to the low @trunc@ coefficients of @poly@ (assumed to be zero+-- padded if necessary to length @trunc@) to the power @e@. This is+-- equivalent to doing a powering followed by a truncation. We require that+-- @res@ has enough space for @trunc@ coefficients, that @trunc > 0@ and+-- that @e > 1@. Aliasing is not permitted. Uses the binary exponentiation+-- method.+foreign import ccall "nmod_poly.h _nmod_poly_pow_trunc_binexp"+ _nmod_poly_pow_trunc_binexp :: Ptr CMp -> Ptr CMp -> CULong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_pow_trunc_binexp/ /res/ /poly/ /e/ /trunc/ +-- +-- Sets @res@ to the low @trunc@ coefficients of @poly@ to the power @e@.+-- This is equivalent to doing a powering followed by a truncation. Uses+-- the binary exponentiation method.+foreign import ccall "nmod_poly.h nmod_poly_pow_trunc_binexp"+ nmod_poly_pow_trunc_binexp :: Ptr CNModPoly -> Ptr CNModPoly -> CULong -> CLong -> IO ()++-- | /_nmod_poly_pow_trunc/ /res/ /poly/ /e/ /trunc/ /mod/ +-- +-- Sets @res@ to the low @trunc@ coefficients of @poly@ (assumed to be zero+-- padded if necessary to length @trunc@) to the power @e@. This is+-- equivalent to doing a powering followed by a truncation. We require that+-- @res@ has enough space for @trunc@ coefficients, that @trunc > 0@ and+-- that @e > 1@. Aliasing is not permitted.+foreign import ccall "nmod_poly.h _nmod_poly_pow_trunc"+ _nmod_poly_pow_trunc :: Ptr CMp -> Ptr CMp -> CULong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_pow_trunc/ /res/ /poly/ /e/ /trunc/ +-- +-- Sets @res@ to the low @trunc@ coefficients of @poly@ to the power @e@.+-- This is equivalent to doing a powering followed by a truncation.+foreign import ccall "nmod_poly.h nmod_poly_pow_trunc"+ nmod_poly_pow_trunc :: Ptr CNModPoly -> Ptr CNModPoly -> CULong -> CLong -> IO ()++-- | /_nmod_poly_powmod_ui_binexp/ /res/ /poly/ /e/ /f/ /lenf/ /mod/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_powmod_ui_binexp"+ _nmod_poly_powmod_ui_binexp :: Ptr CMp -> Ptr CMp -> CULong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_powmod_ui_binexp/ /res/ /poly/ /e/ /f/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@.+foreign import ccall "nmod_poly.h nmod_poly_powmod_ui_binexp"+ nmod_poly_powmod_ui_binexp :: Ptr CNModPoly -> Ptr CNModPoly -> CULong -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_powmod_mpz_binexp/ /res/ /poly/ /e/ /f/ /lenf/ /mod/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_powmod_mpz_binexp"+ _nmod_poly_powmod_mpz_binexp :: Ptr CMp -> Ptr CMp -> Ptr CMpz -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_powmod_mpz_binexp/ /res/ /poly/ /e/ /f/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@.+foreign import ccall "nmod_poly.h nmod_poly_powmod_mpz_binexp"+ nmod_poly_powmod_mpz_binexp :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CMpz -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_powmod_fmpz_binexp/ /res/ /poly/ /e/ /f/ /lenf/ /mod/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_powmod_fmpz_binexp"+ _nmod_poly_powmod_fmpz_binexp :: Ptr CMp -> Ptr CMp -> Ptr CFmpz -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_powmod_fmpz_binexp/ /res/ /poly/ /e/ /f/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@.+foreign import ccall "nmod_poly.h nmod_poly_powmod_fmpz_binexp"+ nmod_poly_powmod_fmpz_binexp :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CFmpz -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_powmod_ui_binexp_preinv/ /res/ /poly/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /mod/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_powmod_ui_binexp_preinv"+ _nmod_poly_powmod_ui_binexp_preinv :: Ptr CMp -> Ptr CMp -> CULong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_powmod_ui_binexp_preinv/ /res/ /poly/ /e/ /f/ /finv/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+foreign import ccall "nmod_poly.h nmod_poly_powmod_ui_binexp_preinv"+ nmod_poly_powmod_ui_binexp_preinv :: Ptr CNModPoly -> Ptr CNModPoly -> CULong -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_powmod_mpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /mod/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@. We require @finv@ to be the inverse+-- of the reverse of @f@. We require @lenf > 1@. It is assumed that @poly@+-- is already reduced modulo @f@ and zero-padded as necessary to have+-- length exactly @lenf - 1@. The output @res@ must have room for+-- @lenf - 1@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_powmod_mpz_binexp_preinv"+ _nmod_poly_powmod_mpz_binexp_preinv :: Ptr CMp -> Ptr CMp -> Ptr CMpz -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_powmod_mpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /finv/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+foreign import ccall "nmod_poly.h nmod_poly_powmod_mpz_binexp_preinv"+ nmod_poly_powmod_mpz_binexp_preinv :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CMpz -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_powmod_fmpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /mod/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e > 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+-- +-- We require @lenf > 1@. It is assumed that @poly@ is already reduced+-- modulo @f@ and zero-padded as necessary to have length exactly+-- @lenf - 1@. The output @res@ must have room for @lenf - 1@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_powmod_fmpz_binexp_preinv"+ _nmod_poly_powmod_fmpz_binexp_preinv :: Ptr CMp -> Ptr CMp -> Ptr CFmpz -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_powmod_fmpz_binexp_preinv/ /res/ /poly/ /e/ /f/ /finv/ +-- +-- Sets @res@ to @poly@ raised to the power @e@ modulo @f@, using binary+-- exponentiation. We require @e >= 0@. We require @finv@ to be the inverse+-- of the reverse of @f@.+foreign import ccall "nmod_poly.h nmod_poly_powmod_fmpz_binexp_preinv"+ nmod_poly_powmod_fmpz_binexp_preinv :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CFmpz -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_powmod_x_ui_preinv/ /res/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /mod/ +-- +-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e > 0@. We require @finv@ to be the+-- inverse of the reverse of @f@.+-- +-- We require @lenf > 2@. The output @res@ must have room for @lenf - 1@+-- coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_powmod_x_ui_preinv"+ _nmod_poly_powmod_x_ui_preinv :: Ptr CMp -> CULong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_powmod_x_ui_preinv/ /res/ /e/ /f/ /finv/ +-- +-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e >= 0@. We require @finv@ to be the+-- inverse of the reverse of @f@.+foreign import ccall "nmod_poly.h nmod_poly_powmod_x_ui_preinv"+ nmod_poly_powmod_x_ui_preinv :: Ptr CNModPoly -> CULong -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_powmod_x_fmpz_preinv/ /res/ /e/ /f/ /lenf/ /finv/ /lenfinv/ /mod/ +-- +-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e > 0@. We require @finv@ to be the+-- inverse of the reverse of @f@.+-- +-- We require @lenf > 2@. The output @res@ must have room for @lenf - 1@+-- coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_powmod_x_fmpz_preinv"+ _nmod_poly_powmod_x_fmpz_preinv :: Ptr CMp -> Ptr CFmpz -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_powmod_x_fmpz_preinv/ /res/ /e/ /f/ /finv/ +-- +-- Sets @res@ to @x@ raised to the power @e@ modulo @f@, using sliding+-- window exponentiation. We require @e >= 0@. We require @finv@ to be the+-- inverse of the reverse of @f@.+foreign import ccall "nmod_poly.h nmod_poly_powmod_x_fmpz_preinv"+ nmod_poly_powmod_x_fmpz_preinv :: Ptr CNModPoly -> Ptr CFmpz -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_powers_mod_preinv_naive/ /res/ /f/ /flen/ /n/ /g/ /glen/ /ginv/ /ginvlen/ /mod/ +-- +-- Compute @f^0, f^1, ..., f^(n-1) mod g@, where @g@ has length @glen@ and+-- @f@ is reduced mod @g@ and has length @flen@ (possibly zero spaced).+-- Assumes @res@ is an array of @n@ arrays each with space for at least+-- @glen - 1@ coefficients and that @flen > 0@. We require that @ginv@ of+-- length @ginvlen@ is set to the power series inverse of the reverse of+-- @g@.+foreign import ccall "nmod_poly.h _nmod_poly_powers_mod_preinv_naive"+ _nmod_poly_powers_mod_preinv_naive :: Ptr (Ptr CMp) -> Ptr CMp -> CLong -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_powers_mod_naive/ /res/ /f/ /n/ /g/ +-- +-- Set the entries of the array @res@ to @f^0, f^1, ..., f^(n-1) mod g@. No+-- aliasing is permitted between the entries of @res@ and either of the+-- inputs.+foreign import ccall "nmod_poly.h nmod_poly_powers_mod_naive"+ nmod_poly_powers_mod_naive :: Ptr (Ptr CNModPoly) -> Ptr CNModPoly -> CLong -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_powers_mod_preinv_threaded_pool/ /res/ /f/ /flen/ /n/ /g/ /glen/ /ginv/ /ginvlen/ /mod/ /threads/ /num_threads/ +-- +-- Compute @f^0, f^1, ..., f^(n-1) mod g@, where @g@ has length @glen@ and+-- @f@ is reduced mod @g@ and has length @flen@ (possibly zero spaced).+-- Assumes @res@ is an array of @n@ arrays each with space for at least+-- @glen - 1@ coefficients and that @flen > 0@. We require that @ginv@ of+-- length @ginvlen@ is set to the power series inverse of the reverse of+-- @g@.+foreign import ccall "nmod_poly.h _nmod_poly_powers_mod_preinv_threaded_pool"+ _nmod_poly_powers_mod_preinv_threaded_pool :: Ptr (Ptr CMp) -> Ptr CMp -> CLong -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> Ptr CThreadPoolHandle -> CLong -> IO ()++-- | /_nmod_poly_powers_mod_preinv_threaded/ /res/ /f/ /flen/ /n/ /g/ /glen/ /ginv/ /ginvlen/ /mod/ +-- +-- Compute @f^0, f^1, ..., f^(n-1) mod g@, where @g@ has length @glen@ and+-- @f@ is reduced mod @g@ and has length @flen@ (possibly zero spaced).+-- Assumes @res@ is an array of @n@ arrays each with space for at least+-- @glen - 1@ coefficients and that @flen > 0@. We require that @ginv@ of+-- length @ginvlen@ is set to the power series inverse of the reverse of+-- @g@.+foreign import ccall "nmod_poly.h _nmod_poly_powers_mod_preinv_threaded"+ _nmod_poly_powers_mod_preinv_threaded :: Ptr (Ptr CMp) -> Ptr CMp -> CLong -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_powers_mod_bsgs/ /res/ /f/ /n/ /g/ +-- +-- Set the entries of the array @res@ to @f^0, f^1, ..., f^(n-1) mod g@. No+-- aliasing is permitted between the entries of @res@ and either of the+-- inputs.+foreign import ccall "nmod_poly.h nmod_poly_powers_mod_bsgs"+ nmod_poly_powers_mod_bsgs :: Ptr (Ptr CNModPoly) -> Ptr CNModPoly -> CLong -> Ptr CNModPoly -> IO ()++-- Division --------------------------------------------------------------------++-- | /_nmod_poly_divrem_basecase/ /Q/ /R/ /W/ /A/ /A_len/ /B/ /B_len/ /mod/ +-- +-- Finds \(Q\) and \(R\) such that \(A = B Q + R\) with+-- \(\operatorname{len}(R) < \operatorname{len}(B)\). If+-- \(\operatorname{len}(B) = 0\) an exception is raised. We require that+-- @W@ is temporary space of @NMOD_DIVREM_BC_ITCH(A_len, B_len, mod)@+-- coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_divrem_basecase"+ _nmod_poly_divrem_basecase :: Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_divrem_basecase/ /Q/ /R/ /A/ /B/ +-- +-- Finds \(Q\) and \(R\) such that \(A = B Q + R\) with+-- \(\operatorname{len}(R) < \operatorname{len}(B)\). If+-- \(\operatorname{len}(B) = 0\) an exception is raised.+foreign import ccall "nmod_poly.h nmod_poly_divrem_basecase"+ nmod_poly_divrem_basecase :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_divrem/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R)\) less than @lenB@, where @A@ is of length+-- @lenA@ and @B@ is of length @lenB@. We require that @Q@ have space for+-- @lenA - lenB + 1@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_divrem"+ _nmod_poly_divrem :: Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_divrem/ /Q/ /R/ /A/ /B/ +-- +-- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R) < \operatorname{len}(B)\).+foreign import ccall "nmod_poly.h nmod_poly_divrem"+ nmod_poly_divrem :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_div/ /Q/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Notionally computes polynomials \(Q\) and \(R\) such that \(A = BQ + R\)+-- with \(\operatorname{len}(R)\) less than @lenB@, where @A@ is of length+-- @lenA@ and @B@ is of length @lenB@, but returns only @Q@. We require+-- that @Q@ have space for @lenA - lenB + 1@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_div"+ _nmod_poly_div :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_div/ /Q/ /A/ /B/ +-- +-- Computes the quotient \(Q\) on polynomial division of \(A\) and \(B\).+foreign import ccall "nmod_poly.h nmod_poly_div"+ nmod_poly_div :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++foreign import ccall "nmod_poly.h _nmod_poly_rem_q1"+ _nmod_poly_rem_q1 :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /_nmod_poly_rem/ /R/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Computes the remainder \(R\) on polynomial division of \(A\) by \(B\).+foreign import ccall "nmod_poly.h _nmod_poly_rem"+ _nmod_poly_rem :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_rem/ /R/ /A/ /B/ +-- +-- Computes the remainder \(R\) on polynomial division of \(A\) by \(B\).+foreign import ccall "nmod_poly.h nmod_poly_rem"+ nmod_poly_rem :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_inv_series_basecase/ /Qinv/ /Q/ /Qlen/ /n/ /mod/ +-- +-- Given @Q@ of length @Qlen@ whose leading coefficient is invertible+-- modulo the given modulus, finds a polynomial @Qinv@ of length @n@ such+-- that the top @n@ coefficients of the product @Q * Qinv@ is+-- \(x^{n - 1}\). Requires that @n > 0@. This function can be viewed as+-- inverting a power series.+foreign import ccall "nmod_poly.h _nmod_poly_inv_series_basecase"+ _nmod_poly_inv_series_basecase :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_inv_series_basecase/ /Qinv/ /Q/ /n/ +-- +-- Given @Q@ of length at least @n@ find @Qinv@ of length @n@ such that the+-- top @n@ coefficients of the product @Q * Qinv@ is \(x^{n - 1}\). An+-- exception is raised if @n = 0@ or if the length of @Q@ is less than @n@.+-- The leading coefficient of @Q@ must be invertible modulo the modulus of+-- @Q@. This function can be viewed as inverting a power series.+foreign import ccall "nmod_poly.h nmod_poly_inv_series_basecase"+ nmod_poly_inv_series_basecase :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_inv_series_newton/ /Qinv/ /Q/ /Qlen/ /n/ /mod/ +-- +-- Given @Q@ of length @Qlen@ whose constant coefficient is invertible+-- modulo the given modulus, find a polynomial @Qinv@ of length @n@ such+-- that @Q * Qinv@ is @1@ modulo \(x^n\). Requires @n > 0@. This function+-- can be viewed as inverting a power series via Newton iteration.+foreign import ccall "nmod_poly.h _nmod_poly_inv_series_newton"+ _nmod_poly_inv_series_newton :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_inv_series_newton/ /Qinv/ /Q/ /n/ +-- +-- Given @Q@ find @Qinv@ such that @Q * Qinv@ is @1@ modulo \(x^n\). The+-- constant coefficient of @Q@ must be invertible modulo the modulus of+-- @Q@. An exception is raised if this is not the case or if @n = 0@. This+-- function can be viewed as inverting a power series via Newton iteration.+foreign import ccall "nmod_poly.h nmod_poly_inv_series_newton"+ nmod_poly_inv_series_newton :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_inv_series/ /Qinv/ /Q/ /Qlen/ /n/ /mod/ +-- +-- Given @Q@ of length @Qlenn@ whose constant coefficient is invertible+-- modulo the given modulus, find a polynomial @Qinv@ of length @n@ such+-- that @Q * Qinv@ is @1@ modulo \(x^n\). Requires @n > 0@. This function+-- can be viewed as inverting a power series.+foreign import ccall "nmod_poly.h _nmod_poly_inv_series"+ _nmod_poly_inv_series :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_inv_series/ /Qinv/ /Q/ /n/ +-- +-- Given @Q@ find @Qinv@ such that @Q * Qinv@ is @1@ modulo \(x^n\). The+-- constant coefficient of @Q@ must be invertible modulo the modulus of+-- @Q@. An exception is raised if this is not the case or if @n = 0@. This+-- function can be viewed as inverting a power series.+foreign import ccall "nmod_poly.h nmod_poly_inv_series"+ nmod_poly_inv_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_div_series_basecase/ /Q/ /A/ /Alen/ /B/ /Blen/ /n/ /mod/ +-- +-- Given polynomials @A@ and @B@ of length @Alen@ and @Blen@, finds the+-- polynomial @Q@ of length @n@ such that @Q * B = A@ modulo \(x^n\). We+-- assume @n > 0@ and that the constant coefficient of @B@ is invertible+-- modulo the given modulus. The polynomial @Q@ must have space for @n@+-- coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_div_series_basecase"+ _nmod_poly_div_series_basecase :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_div_series_basecase/ /Q/ /A/ /B/ /n/ +-- +-- Given polynomials @A@ and @B@ considered modulo @n@, finds the+-- polynomial @Q@ of length at most @n@ such that @Q * B = A@ modulo+-- \(x^n\). We assume @n > 0@ and that the constant coefficient of @B@ is+-- invertible modulo the modulus. An exception is raised if @n == 0@ or the+-- constant coefficient of @B@ is zero.+foreign import ccall "nmod_poly.h nmod_poly_div_series_basecase"+ nmod_poly_div_series_basecase :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_div_series/ /Q/ /A/ /Alen/ /B/ /Blen/ /n/ /mod/ +-- +-- Given polynomials @A@ and @B@ of length @Alen@ and @Blen@, finds the+-- polynomial @Q@ of length @n@ such that @Q * B = A@ modulo \(x^n\). We+-- assume @n > 0@ and that the constant coefficient of @B@ is invertible+-- modulo the given modulus. The polynomial @Q@ must have space for @n@+-- coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_div_series"+ _nmod_poly_div_series :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_div_series/ /Q/ /A/ /B/ /n/ +-- +-- Given polynomials @A@ and @B@ considered modulo @n@, finds the+-- polynomial @Q@ of length at most @n@ such that @Q * B = A@ modulo+-- \(x^n\). We assume @n > 0@ and that the constant coefficient of @B@ is+-- invertible modulo the modulus. An exception is raised if @n == 0@ or the+-- constant coefficient of @B@ is zero.+foreign import ccall "nmod_poly.h nmod_poly_div_series"+ nmod_poly_div_series :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_div_newton_n_preinv/ /Q/ /A/ /lenA/ /B/ /lenB/ /Binv/ /lenBinv/ /mod/ +-- +-- Notionally computes polynomials \(Q\) and \(R\) such that \(A = BQ + R\)+-- with \(\operatorname{len}(R)\) less than @lenB@, where @A@ is of length+-- @lenA@ and @B@ is of length @lenB@, but return only \(Q\).+-- +-- We require that \(Q\) have space for @lenA - lenB + 1@ coefficients and+-- assume that the leading coefficient of \(B\) is a unit. Furthermore, we+-- assume that \(Binv\) is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\).+-- +-- The algorithm used is to reverse the polynomials and divide the+-- resulting power series, then reverse the result.+foreign import ccall "nmod_poly.h _nmod_poly_div_newton_n_preinv"+ _nmod_poly_div_newton_n_preinv :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_div_newton_n_preinv/ /Q/ /A/ /B/ /Binv/ +-- +-- Notionally computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R) < \operatorname{len}(B)\), but returns only+-- \(Q\).+-- +-- We assume that the leading coefficient of \(B\) is a unit and that+-- \(Binv\) is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\).+-- +-- It is required that the length of \(A\) is less than or equal to 2*the+-- length of \(B\) - 2.+-- +-- The algorithm used is to reverse the polynomials and divide the+-- resulting power series, then reverse the result.+foreign import ccall "nmod_poly.h nmod_poly_div_newton_n_preinv"+ nmod_poly_div_newton_n_preinv :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_divrem_newton_n_preinv/ /Q/ /R/ /A/ /lenA/ /B/ /lenB/ /Binv/ /lenBinv/ /mod/ +-- +-- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R)\) less than @lenB@, where \(A\) is of length+-- @lenA@ and \(B\) is of length @lenB@. We require that \(Q\) have space+-- for @lenA - lenB + 1@ coefficients. Furthermore, we assume that \(Binv\)+-- is the inverse of the reverse of \(B\) mod+-- \(x^{\operatorname{len}(B)}\). The algorithm used is to call+-- @div_newton_n_preinv@ and then multiply out and compute the remainder.+foreign import ccall "nmod_poly.h _nmod_poly_divrem_newton_n_preinv"+ _nmod_poly_divrem_newton_n_preinv :: Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_divrem_newton_n_preinv/ /Q/ /R/ /A/ /B/ /Binv/ +-- +-- Computes \(Q\) and \(R\) such that \(A = BQ + R\) with+-- \(\operatorname{len}(R) < \operatorname{len}(B)\). We assume \(Binv\) is+-- the inverse of the reverse of \(B\) mod \(x^{\operatorname{len}(B)}\).+-- +-- It is required that the length of \(A\) is less than or equal to 2*the+-- length of \(B\) - 2.+-- +-- The algorithm used is to call @div_newton_n@ and then multiply out and+-- compute the remainder.+foreign import ccall "nmod_poly.h nmod_poly_divrem_newton_n_preinv"+ nmod_poly_divrem_newton_n_preinv :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_div_root/ /Q/ /A/ /len/ /c/ /mod/ +-- +-- Sets @(Q, len-1)@ to the quotient of @(A, len)@ on division by+-- \((x - c)\), and returns the remainder, equal to the value of \(A\)+-- evaluated at \(c\). \(A\) and \(Q\) are allowed to be the same, but may+-- not overlap partially in any other way.+foreign import ccall "nmod_poly.h _nmod_poly_div_root"+ _nmod_poly_div_root :: Ptr CMp -> Ptr CMp -> CLong -> CMpLimb -> Ptr CNMod -> IO CMpLimb++-- | /nmod_poly_div_root/ /Q/ /A/ /c/ +-- +-- Sets \(Q\) to the quotient of \(A\) on division by \((x - c)\), and+-- returns the remainder, equal to the value of \(A\) evaluated at \(c\).+foreign import ccall "nmod_poly.h nmod_poly_div_root"+ nmod_poly_div_root :: Ptr CNModPoly -> Ptr CNModPoly -> CMpLimb -> IO CMpLimb++-- Divisibility testing --------------------------------------------------------++-- | /_nmod_poly_divides_classical/ /Q/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Returns \(1\) if \((B, lenB)\) divides \((A, lenA)\) and sets+-- \((Q, lenA - lenB + 1)\) to the quotient. Otherwise, returns \(0\) and+-- sets \((Q, lenA - lenB + 1)\) to zero. We require that+-- \(lenA >= lenB > 0\).+foreign import ccall "nmod_poly.h _nmod_poly_divides_classical"+ _nmod_poly_divides_classical :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CInt++-- | /nmod_poly_divides_classical/ /Q/ /A/ /B/ +-- +-- Returns \(1\) if \(B\) divides \(A\) and sets \(Q\) to the quotient.+-- Otherwise returns \(0\) and sets \(Q\) to zero.+foreign import ccall "nmod_poly.h nmod_poly_divides_classical"+ nmod_poly_divides_classical :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO CInt++-- | /_nmod_poly_divides/ /Q/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Returns \(1\) if \((B, lenB)\) divides \((A, lenA)\) and sets+-- \((Q, lenA - lenB + 1)\) to the quotient. Otherwise, returns \(0\) and+-- sets \((Q, lenA - lenB + 1)\) to zero. We require that+-- \(lenA >= lenB > 0\).+foreign import ccall "nmod_poly.h _nmod_poly_divides"+ _nmod_poly_divides :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CInt++-- | /nmod_poly_divides/ /Q/ /A/ /B/ +-- +-- Returns \(1\) if \(B\) divides \(A\) and sets \(Q\) to the quotient.+-- Otherwise returns \(0\) and sets \(Q\) to zero.+foreign import ccall "nmod_poly.h nmod_poly_divides"+ nmod_poly_divides :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO CInt++-- Derivative and integral -----------------------------------------------------++-- | /_nmod_poly_derivative/ /x_prime/ /x/ /len/ /mod/ +-- +-- Sets the first @len - 1@ coefficients of @x_prime@ to the derivative of+-- @x@ which is assumed to be of length @len@. It is assumed that+-- @len > 0@.+foreign import ccall "nmod_poly.h _nmod_poly_derivative"+ _nmod_poly_derivative :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_derivative/ /x_prime/ /x/ +-- +-- Sets @x_prime@ to the derivative of @x@.+foreign import ccall "nmod_poly.h nmod_poly_derivative"+ nmod_poly_derivative :: Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_integral/ /x_int/ /x/ /len/ /mod/ +-- +-- Set the first @len@ coefficients of @x_int@ to the integral of @x@ which+-- is assumed to be of length @len - 1@. The constant term of @x_int@ is+-- set to zero. It is assumed that @len > 0@. The result is only+-- well-defined if the modulus is a prime number strictly larger than the+-- degree of @x@. Supports aliasing between the two polynomials.+foreign import ccall "nmod_poly.h _nmod_poly_integral"+ _nmod_poly_integral :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_integral/ /x_int/ /x/ +-- +-- Set @x_int@ to the indefinite integral of @x@ with constant term zero.+-- The result is only well-defined if the modulus is a prime number+-- strictly larger than the degree of @x@.+foreign import ccall "nmod_poly.h nmod_poly_integral"+ nmod_poly_integral :: Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- Evaluation ------------------------------------------------------------------++-- | /_nmod_poly_evaluate_nmod/ /poly/ /len/ /c/ /mod/ +-- +-- Evaluates @poly@ at the value~@c@ and reduces modulo the given modulus+-- of @poly@. The value~@c@ should be reduced modulo the modulus. The+-- algorithm used is Horner\'s method.+foreign import ccall "nmod_poly.h _nmod_poly_evaluate_nmod"+ _nmod_poly_evaluate_nmod :: Ptr CMp -> CLong -> CMpLimb -> Ptr CNMod -> IO CMpLimb++-- | /nmod_poly_evaluate_nmod/ /poly/ /c/ +-- +-- Evaluates @poly@ at the value~@c@ and reduces modulo the modulus of+-- @poly@. The value~@c@ should be reduced modulo the modulus. The+-- algorithm used is Horner\'s method.+foreign import ccall "nmod_poly.h nmod_poly_evaluate_nmod"+ nmod_poly_evaluate_nmod :: Ptr CNModPoly -> CMpLimb -> IO CMpLimb++-- | /nmod_poly_evaluate_mat_horner/ /dest/ /poly/ /c/ +-- +-- Evaluates @poly@ with matrix as an argument at the value @c@ and stores+-- the result in @dest@. The dimension and modulus of @dest@ is assumed to+-- be same as that of @c@. @dest@ and @c@ may be aliased. Horner\'s Method+-- is used to compute the result.+foreign import ccall "nmod_poly.h nmod_poly_evaluate_mat_horner"+ nmod_poly_evaluate_mat_horner :: Ptr CNModMat -> Ptr CNModPoly -> Ptr CNModMat -> IO ()++-- | /nmod_poly_evaluate_mat_paterson_stockmeyer/ /dest/ /poly/ /c/ +-- +-- Evaluates @poly@ with matrix as an argument at the value @c@ and stores+-- the result in @dest@. The dimension and modulus of @dest@ is assumed to+-- be same as that of @c@. @dest@ and @c@ may be aliased.+-- Paterson-Stockmeyer algorithm is used to compute the result. The+-- algorithm is described in < [Paterson1973]>.+foreign import ccall "nmod_poly.h nmod_poly_evaluate_mat_paterson_stockmeyer"+ nmod_poly_evaluate_mat_paterson_stockmeyer :: Ptr CNModMat -> Ptr CNModPoly -> Ptr CNModMat -> IO ()++-- | /nmod_poly_evaluate_mat/ /dest/ /poly/ /c/ +-- +-- Evaluates @poly@ with matrix as an argument at the value @c@ and stores+-- the result in @dest@. The dimension and modulus of @dest@ is assumed to+-- be same as that of @c@. @dest@ and @c@ may be aliased. This function+-- automatically switches between Horner\'s method and the+-- Paterson-Stockmeyer algorithm.+foreign import ccall "nmod_poly.h nmod_poly_evaluate_mat"+ nmod_poly_evaluate_mat :: Ptr CNModMat -> Ptr CNModPoly -> Ptr CNModMat -> IO ()++-- Multipoint evaluation -------------------------------------------------------++-- | /_nmod_poly_evaluate_nmod_vec_iter/ /ys/ /poly/ /len/ /xs/ /n/ /mod/ +-- +-- Evaluates (@coeffs@, @len@) at the @n@ values given in the vector @xs@,+-- writing the output values to @ys@. The values in @xs@ should be reduced+-- modulo the modulus.+-- +-- Uses Horner\'s method iteratively.+foreign import ccall "nmod_poly.h _nmod_poly_evaluate_nmod_vec_iter"+ _nmod_poly_evaluate_nmod_vec_iter :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_evaluate_nmod_vec_iter/ /ys/ /poly/ /xs/ /n/ +-- +-- Evaluates @poly@ at the @n@ values given in the vector @xs@, writing the+-- output values to @ys@. The values in @xs@ should be reduced modulo the+-- modulus.+-- +-- Uses Horner\'s method iteratively.+foreign import ccall "nmod_poly.h nmod_poly_evaluate_nmod_vec_iter"+ nmod_poly_evaluate_nmod_vec_iter :: Ptr CMp -> Ptr CNModPoly -> Ptr CMp -> CLong -> IO ()++-- | /_nmod_poly_evaluate_nmod_vec_fast_precomp/ /vs/ /poly/ /plen/ /tree/ /len/ /mod/ +-- +-- Evaluates (@poly@, @plen@) at the @len@ values given by the precomputed+-- subproduct tree @tree@.+foreign import ccall "nmod_poly.h _nmod_poly_evaluate_nmod_vec_fast_precomp"+ _nmod_poly_evaluate_nmod_vec_fast_precomp :: Ptr CMp -> Ptr CMp -> CLong -> Ptr (Ptr CMp) -> CLong -> Ptr CNMod -> IO ()++-- | /_nmod_poly_evaluate_nmod_vec_fast/ /ys/ /poly/ /len/ /xs/ /n/ /mod/ +-- +-- Evaluates (@coeffs@, @len@) at the @n@ values given in the vector @xs@,+-- writing the output values to @ys@. The values in @xs@ should be reduced+-- modulo the modulus.+-- +-- Uses fast multipoint evaluation, building a temporary subproduct tree.+foreign import ccall "nmod_poly.h _nmod_poly_evaluate_nmod_vec_fast"+ _nmod_poly_evaluate_nmod_vec_fast :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_evaluate_nmod_vec_fast/ /ys/ /poly/ /xs/ /n/ +-- +-- Evaluates @poly@ at the @n@ values given in the vector @xs@, writing the+-- output values to @ys@. The values in @xs@ should be reduced modulo the+-- modulus.+-- +-- Uses fast multipoint evaluation, building a temporary subproduct tree.+foreign import ccall "nmod_poly.h nmod_poly_evaluate_nmod_vec_fast"+ nmod_poly_evaluate_nmod_vec_fast :: Ptr CMp -> Ptr CNModPoly -> Ptr CMp -> CLong -> IO ()++-- | /_nmod_poly_evaluate_nmod_vec/ /ys/ /poly/ /len/ /xs/ /n/ /mod/ +-- +-- Evaluates (@poly@, @len@) at the @n@ values given in the vector @xs@,+-- writing the output values to @ys@. The values in @xs@ should be reduced+-- modulo the modulus.+foreign import ccall "nmod_poly.h _nmod_poly_evaluate_nmod_vec"+ _nmod_poly_evaluate_nmod_vec :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_evaluate_nmod_vec/ /ys/ /poly/ /xs/ /n/ +-- +-- Evaluates @poly@ at the @n@ values given in the vector @xs@, writing the+-- output values to @ys@. The values in @xs@ should be reduced modulo the+-- modulus.+foreign import ccall "nmod_poly.h nmod_poly_evaluate_nmod_vec"+ nmod_poly_evaluate_nmod_vec :: Ptr CMp -> Ptr CNModPoly -> Ptr CMp -> CLong -> IO ()++-- Interpolation ---------------------------------------------------------------++-- | /_nmod_poly_interpolate_nmod_vec/ /poly/ /xs/ /ys/ /n/ /mod/ +-- +-- Sets @poly@ to the unique polynomial of length at most @n@ that+-- interpolates the @n@ given evaluation points @xs@ and values @ys@. If+-- the interpolating polynomial is shorter than length @n@, the leading+-- coefficients are set to zero.+-- +-- The values in @xs@ and @ys@ should be reduced modulo the modulus, and+-- all @xs@ must be distinct. Aliasing between @poly@ and @xs@ or @ys@ is+-- not allowed.+foreign import ccall "nmod_poly.h _nmod_poly_interpolate_nmod_vec"+ _nmod_poly_interpolate_nmod_vec :: Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_interpolate_nmod_vec/ /poly/ /xs/ /ys/ /n/ +-- +-- Sets @poly@ to the unique polynomial of length @n@ that interpolates the+-- @n@ given evaluation points @xs@ and values @ys@. The values in @xs@ and+-- @ys@ should be reduced modulo the modulus, and all @xs@ must be+-- distinct.+foreign import ccall "nmod_poly.h nmod_poly_interpolate_nmod_vec"+ nmod_poly_interpolate_nmod_vec :: Ptr CNModPoly -> Ptr CMp -> Ptr CMp -> CLong -> IO ()++-- | /_nmod_poly_interpolation_weights/ /w/ /tree/ /len/ /mod/ +-- +-- Sets @w@ to the barycentric interpolation weights for fast Lagrange+-- interpolation with respect to a given subproduct tree.+foreign import ccall "nmod_poly.h _nmod_poly_interpolation_weights"+ _nmod_poly_interpolation_weights :: Ptr CMp -> Ptr (Ptr CMp) -> CLong -> Ptr CNMod -> IO ()++-- | /_nmod_poly_interpolate_nmod_vec_fast_precomp/ /poly/ /ys/ /tree/ /weights/ /len/ /mod/ +-- +-- Performs interpolation using the fast Lagrange interpolation algorithm,+-- generating a temporary subproduct tree.+-- +-- The function values are given as @ys@. The function takes a precomputed+-- subproduct tree @tree@ and barycentric interpolation weights @weights@+-- corresponding to the roots.+foreign import ccall "nmod_poly.h _nmod_poly_interpolate_nmod_vec_fast_precomp"+ _nmod_poly_interpolate_nmod_vec_fast_precomp :: Ptr CMp -> Ptr CMp -> Ptr (Ptr CMp) -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /_nmod_poly_interpolate_nmod_vec_fast/ /poly/ /xs/ /ys/ /n/ /mod/ +-- +-- Performs interpolation using the fast Lagrange interpolation algorithm,+-- generating a temporary subproduct tree.+foreign import ccall "nmod_poly.h _nmod_poly_interpolate_nmod_vec_fast"+ _nmod_poly_interpolate_nmod_vec_fast :: Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_interpolate_nmod_vec_fast/ /poly/ /xs/ /ys/ /n/ +-- +-- Performs interpolation using the fast Lagrange interpolation algorithm,+-- generating a temporary subproduct tree.+foreign import ccall "nmod_poly.h nmod_poly_interpolate_nmod_vec_fast"+ nmod_poly_interpolate_nmod_vec_fast :: Ptr CNModPoly -> Ptr CMp -> Ptr CMp -> CLong -> IO ()++-- | /_nmod_poly_interpolate_nmod_vec_newton/ /poly/ /xs/ /ys/ /n/ /mod/ +-- +-- Forms the interpolating polynomial in the Newton basis using the method+-- of divided differences and then converts it to monomial form.+foreign import ccall "nmod_poly.h _nmod_poly_interpolate_nmod_vec_newton"+ _nmod_poly_interpolate_nmod_vec_newton :: Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_interpolate_nmod_vec_newton/ /poly/ /xs/ /ys/ /n/ +-- +-- Forms the interpolating polynomial in the Newton basis using the method+-- of divided differences and then converts it to monomial form.+foreign import ccall "nmod_poly.h nmod_poly_interpolate_nmod_vec_newton"+ nmod_poly_interpolate_nmod_vec_newton :: Ptr CNModPoly -> Ptr CMp -> Ptr CMp -> CLong -> IO ()++-- | /_nmod_poly_interpolate_nmod_vec_barycentric/ /poly/ /xs/ /ys/ /n/ /mod/ +-- +-- Forms the interpolating polynomial using a naive implementation of the+-- barycentric form of Lagrange interpolation.+foreign import ccall "nmod_poly.h _nmod_poly_interpolate_nmod_vec_barycentric"+ _nmod_poly_interpolate_nmod_vec_barycentric :: Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_interpolate_nmod_vec_barycentric/ /poly/ /xs/ /ys/ /n/ +-- +-- Forms the interpolating polynomial using a naive implementation of the+-- barycentric form of Lagrange interpolation.+foreign import ccall "nmod_poly.h nmod_poly_interpolate_nmod_vec_barycentric"+ nmod_poly_interpolate_nmod_vec_barycentric :: Ptr CNModPoly -> Ptr CMp -> Ptr CMp -> CLong -> IO ()++-- Composition -----------------------------------------------------------------++-- | /_nmod_poly_compose_horner/ /res/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- +-- Composes @poly1@ of length @len1@ with @poly2@ of length @len2@ and sets+-- @res@ to the result, i.e.evaluates @poly1@ at @poly2@. The algorithm+-- used is Horner\'s algorithm. We require that @res@ have space for+-- @(len1 - 1)*(len2 - 1) + 1@ coefficients. It is assumed that @len1 > 0@+-- and @len2 > 0@.+foreign import ccall "nmod_poly.h _nmod_poly_compose_horner"+ _nmod_poly_compose_horner :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_compose_horner/ /res/ /poly1/ /poly2/ +-- +-- Composes @poly1@ with @poly2@ and sets @res@ to the result,+-- i.e.evaluates @poly1@ at @poly2@. The algorithm used is Horner\'s+-- algorithm.+foreign import ccall "nmod_poly.h nmod_poly_compose_horner"+ nmod_poly_compose_horner :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- -- | /_nmod_poly_compose_divconquer/ /res/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- -- +-- -- Composes @poly1@ of length @len1@ with @poly2@ of length @len2@ and sets+-- -- @res@ to the result, i.e.evaluates @poly1@ at @poly2@. The algorithm+-- -- used is the divide and conquer algorithm. We require that @res@ have+-- -- space for @(len1 - 1)*(len2 - 1) + 1@ coefficients. It is assumed that+-- -- @len1 > 0@ and @len2 > 0@.+-- foreign import ccall "nmod_poly.h _nmod_poly_compose_divconquer"+-- _nmod_poly_compose_divconquer :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- -- | /nmod_poly_compose_divconquer/ /res/ /poly1/ /poly2/ +-- -- +-- -- Composes @poly1@ with @poly2@ and sets @res@ to the result,+-- -- i.e.evaluates @poly1@ at @poly2@. The algorithm used is the divide and+-- -- conquer algorithm.+-- foreign import ccall "nmod_poly.h nmod_poly_compose_divconquer"+-- nmod_poly_compose_divconquer :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_compose/ /res/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- +-- Composes @poly1@ of length @len1@ with @poly2@ of length @len2@ and sets+-- @res@ to the result, i.e.evaluates @poly1@ at @poly2@. We require that+-- @res@ have space for @(len1 - 1)*(len2 - 1) + 1@ coefficients. It is+-- assumed that @len1 > 0@ and @len2 > 0@.+foreign import ccall "nmod_poly.h _nmod_poly_compose"+ _nmod_poly_compose :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_compose/ /res/ /poly1/ /poly2/ +-- +-- Composes @poly1@ with @poly2@ and sets @res@ to the result, that is,+-- evaluates @poly1@ at @poly2@.+foreign import ccall "nmod_poly.h nmod_poly_compose"+ nmod_poly_compose :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- Taylor shift ----------------------------------------------------------------++-- | /_nmod_poly_taylor_shift_horner/ /poly/ /c/ /len/ /mod/ +-- +-- Performs the Taylor shift composing @poly@ by \(x+c\) in-place. Uses an+-- efficient version Horner\'s rule.+foreign import ccall "nmod_poly.h _nmod_poly_taylor_shift_horner"+ _nmod_poly_taylor_shift_horner :: Ptr CMp -> CMpLimb -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_taylor_shift_horner/ /g/ /f/ /c/ +-- +-- Performs the Taylor shift composing @f@ by \(x+c\).+foreign import ccall "nmod_poly.h nmod_poly_taylor_shift_horner"+ nmod_poly_taylor_shift_horner :: Ptr CNModPoly -> Ptr CNModPoly -> CMpLimb -> IO ()++-- | /_nmod_poly_taylor_shift_convolution/ /poly/ /c/ /len/ /mod/ +-- +-- Performs the Taylor shift composing @poly@ by \(x+c\) in-place. Writes+-- the composition as a single convolution with cost \(O(M(n))\). We+-- require that the modulus is a prime at least as large as the length.+foreign import ccall "nmod_poly.h _nmod_poly_taylor_shift_convolution"+ _nmod_poly_taylor_shift_convolution :: Ptr CMp -> CMpLimb -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_taylor_shift_convolution/ /g/ /f/ /c/ +-- +-- Performs the Taylor shift composing @f@ by \(x+c\). Writes the+-- composition as a single convolution with cost \(O(M(n))\). We require+-- that the modulus is a prime at least as large as the length.+foreign import ccall "nmod_poly.h nmod_poly_taylor_shift_convolution"+ nmod_poly_taylor_shift_convolution :: Ptr CNModPoly -> Ptr CNModPoly -> CMpLimb -> IO ()++-- | /_nmod_poly_taylor_shift/ /poly/ /c/ /len/ /mod/ +-- +-- Performs the Taylor shift composing @poly@ by \(x+c\) in-place. We+-- require that the modulus is a prime.+foreign import ccall "nmod_poly.h _nmod_poly_taylor_shift"+ _nmod_poly_taylor_shift :: Ptr CMp -> CMpLimb -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_taylor_shift/ /g/ /f/ /c/ +-- +-- Performs the Taylor shift composing @f@ by \(x+c\). We require that the+-- modulus is a prime.+foreign import ccall "nmod_poly.h nmod_poly_taylor_shift"+ nmod_poly_taylor_shift :: Ptr CNModPoly -> Ptr CNModPoly -> CMpLimb -> IO ()++-- Modular composition ---------------------------------------------------------++-- | /_nmod_poly_compose_mod_horner/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /mod/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). The output is not allowed+-- to be aliased with any of the inputs.+-- +-- The algorithm used is Horner\'s rule.+foreign import ccall "nmod_poly.h _nmod_poly_compose_mod_horner"+ _nmod_poly_compose_mod_horner :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_compose_mod_horner/ /res/ /f/ /g/ /h/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero. The algorithm used is Horner\'s rule.+foreign import ccall "nmod_poly.h nmod_poly_compose_mod_horner"+ nmod_poly_compose_mod_horner :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_compose_mod_brent_kung/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /mod/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). The output is not+-- allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "nmod_poly.h _nmod_poly_compose_mod_brent_kung"+ _nmod_poly_compose_mod_brent_kung :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_compose_mod_brent_kung/ /res/ /f/ /g/ /h/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\). The+-- algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "nmod_poly.h nmod_poly_compose_mod_brent_kung"+ nmod_poly_compose_mod_brent_kung :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_compose_mod_brent_kung_preinv/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /hinv/ /lenhinv/ /mod/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). We also require that the+-- length of \(f\) is less than the length of \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "nmod_poly.h _nmod_poly_compose_mod_brent_kung_preinv"+ _nmod_poly_compose_mod_brent_kung_preinv :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_compose_mod_brent_kung_preinv/ /res/ /f/ /g/ /h/ /hinv/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "nmod_poly.h nmod_poly_compose_mod_brent_kung_preinv"+ nmod_poly_compose_mod_brent_kung_preinv :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_reduce_matrix_mod_poly/ /A/ /B/ /f/ +-- +-- Sets the ith row of @A@ to the reduction of the ith row of \(B\) modulo+-- \(f\) for \(i=1,\ldots,\sqrt{\deg(f)}\). We require \(B\) to be at least+-- a \(\sqrt{\deg(f)}\times \deg(f)\) matrix and \(f\) to be nonzero.+foreign import ccall "nmod_poly.h _nmod_poly_reduce_matrix_mod_poly"+ _nmod_poly_reduce_matrix_mod_poly :: Ptr CNModMat -> Ptr CNModMat -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_precompute_matrix_worker/ /arg_ptr/ +-- +-- Worker function version of @_nmod_poly_precompute_matrix@. Input\/output+-- is stored in @nmod_poly_matrix_precompute_arg_t@.+foreign import ccall "nmod_poly.h _nmod_poly_precompute_matrix_worker"+ _nmod_poly_precompute_matrix_worker :: Ptr () -> IO ()++-- | /_nmod_poly_precompute_matrix/ /A/ /f/ /g/ /leng/ /ginv/ /lenginv/ /mod/ +-- +-- Sets the ith row of @A@ to \(f^i\) modulo \(g\) for+-- \(i=1,\ldots,\sqrt{\deg(g)}\). We require \(A\) to be a+-- \(\sqrt{\deg(g)}\times \deg(g)\) matrix. We require @ginv@ to be the+-- inverse of the reverse of @g@ and \(g\) to be nonzero. @f@ has to be+-- reduced modulo @g@ and of length one less than @leng@ (possibly with+-- zero padding).+foreign import ccall "nmod_poly.h _nmod_poly_precompute_matrix"+ _nmod_poly_precompute_matrix :: Ptr CNModMat -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_precompute_matrix/ /A/ /f/ /g/ /ginv/ +-- +-- Sets the ith row of @A@ to \(f^i\) modulo \(g\) for+-- \(i=1,\ldots,\sqrt{\deg(g)}\). We require \(A\) to be a+-- \(\sqrt{\deg(g)}\times \deg(g)\) matrix. We require @ginv@ to be the+-- inverse of the reverse of @g@.+foreign import ccall "nmod_poly.h nmod_poly_precompute_matrix"+ nmod_poly_precompute_matrix :: Ptr CNModMat -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_compose_mod_brent_kung_precomp_preinv_worker/ /arg_ptr/ +-- +-- Worker function version of+-- @_nmod_poly_compose_mod_brent_kung_precomp_preinv@. Input\/output is+-- stored in @nmod_poly_compose_mod_precomp_preinv_arg_t@.+foreign import ccall "nmod_poly.h _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker"+ _nmod_poly_compose_mod_brent_kung_precomp_preinv_worker :: Ptr () -> IO ()++-- | /_nmod_poly_compose_mod_brent_kung_precomp_preinv/ /res/ /f/ /lenf/ /A/ /h/ /lenh/ /hinv/ /lenhinv/ /mod/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero. We require that the ith row of \(A\) contains \(g^i\)+-- for \(i=1,\ldots,\sqrt{\deg(h)}\), i.e. \(A\) is a+-- \(\sqrt{\deg(h)}\times \deg(h)\) matrix. We also require that the length+-- of \(f\) is less than the length of \(h\). Furthermore, we require+-- @hinv@ to be the inverse of the reverse of @h@. The output is not+-- allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "nmod_poly.h _nmod_poly_compose_mod_brent_kung_precomp_preinv"+ _nmod_poly_compose_mod_brent_kung_precomp_preinv :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNModMat -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_compose_mod_brent_kung_precomp_preinv/ /res/ /f/ /A/ /h/ /hinv/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that the+-- ith row of \(A\) contains \(g^i\) for \(i=1,\ldots,\sqrt{\deg(h)}\),+-- i.e. \(A\) is a \(\sqrt{\deg(h)}\times \deg(h)\) matrix. We require that+-- \(h\) is nonzero and that \(f\) has smaller degree than \(h\).+-- Furthermore, we require @hinv@ to be the inverse of the reverse of @h@.+-- This version of Brent-Kung modular composition is particularly useful if+-- one has to perform several modular composition of the form \(f(g)\)+-- modulo \(h\) for fixed \(g\) and \(h\).+foreign import ccall "nmod_poly.h nmod_poly_compose_mod_brent_kung_precomp_preinv"+ nmod_poly_compose_mod_brent_kung_precomp_preinv :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModMat -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_compose_mod_brent_kung_vec_preinv/ /res/ /polys/ /len1/ /l/ /g/ /leng/ /h/ /lenh/ /hinv/ /lenhinv/ /mod/ +-- +-- Sets @res@ to the composition \(f_i(g)\) modulo \(h\) for+-- \(1\leq i \leq l\), where \(f_i\) are the first @l@ elements of @polys@.+-- We require that \(h\) is nonzero and that the length of \(g\) is less+-- than the length of \(h\). We also require that the length of \(f_i\) is+-- less than the length of \(h\). We require @res@ to have enough memory+-- allocated to hold @l@ @nmod_poly_struct@\'s. The entries of @res@ need+-- to be initialised and @l@ needs to be less than @len1@ Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. The output is+-- not allowed to be aliased with any of the inputs.+-- +-- The algorithm used is the Brent-Kung matrix algorithm.+foreign import ccall "nmod_poly.h _nmod_poly_compose_mod_brent_kung_vec_preinv"+ _nmod_poly_compose_mod_brent_kung_vec_preinv :: Ptr (Ptr CNModPoly) -> Ptr (Ptr CNModPoly) -> CLong -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_compose_mod_brent_kung_vec_preinv/ /res/ /polys/ /len1/ /n/ /g/ /h/ /hinv/ +-- +-- Sets @res@ to the composition \(f_i(g)\) modulo \(h\) for+-- \(1\leq i \leq n\) where \(f_i\) are the first @n@ elements of @polys@.+-- We require @res@ to have enough memory allocated to hold @n@+-- @nmod_poly_struct@. The entries of @res@ need to be initialised and @n@+-- needs to be less than @len1@. We require that \(h\) is nonzero and that+-- \(f_i\) and \(g\) have smaller degree than \(h\). Furthermore, we+-- require @hinv@ to be the inverse of the reverse of @h@. No aliasing of+-- @res@ and @polys@ is allowed. The algorithm used is the Brent-Kung+-- matrix algorithm.+foreign import ccall "nmod_poly.h nmod_poly_compose_mod_brent_kung_vec_preinv"+ nmod_poly_compose_mod_brent_kung_vec_preinv :: Ptr (Ptr CNModPoly) -> Ptr (Ptr CNModPoly) -> CLong -> CLong -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool/ /res/ /polys/ /lenpolys/ /l/ /g/ /glen/ /poly/ /len/ /polyinv/ /leninv/ /mod/ /threads/ /num_threads/ +-- +-- Multithreaded version of @_nmod_poly_compose_mod_brent_kung_vec_preinv@.+-- Distributing the Horner evaluations across @flint_get_num_threads@+-- threads.+foreign import ccall "nmod_poly.h _nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool"+ _nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool :: Ptr (Ptr CNModPoly) -> Ptr (Ptr CNModPoly) -> CLong -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> Ptr CThreadPoolHandle -> CLong -> IO ()++-- | /nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool/ /res/ /polys/ /len1/ /n/ /g/ /poly/ /polyinv/ /threads/ /num_threads/ +-- +-- Multithreaded version of @nmod_poly_compose_mod_brent_kung_vec_preinv@.+-- Distributing the Horner evaluations across @flint_get_num_threads@+-- threads.+foreign import ccall "nmod_poly.h nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool"+ nmod_poly_compose_mod_brent_kung_vec_preinv_threaded_pool :: Ptr (Ptr CNModPoly) -> Ptr (Ptr CNModPoly) -> CLong -> CLong -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CThreadPoolHandle -> CLong -> IO ()++-- | /nmod_poly_compose_mod_brent_kung_vec_preinv_threaded/ /res/ /polys/ /len1/ /n/ /g/ /poly/ /polyinv/ +-- +-- Multithreaded version of @nmod_poly_compose_mod_brent_kung_vec_preinv@.+-- Distributing the Horner evaluations across @flint_get_num_threads@+-- threads.+foreign import ccall "nmod_poly.h nmod_poly_compose_mod_brent_kung_vec_preinv_threaded"+ nmod_poly_compose_mod_brent_kung_vec_preinv_threaded :: Ptr (Ptr CNModPoly) -> Ptr (Ptr CNModPoly) -> CLong -> CLong -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_compose_mod/ /res/ /f/ /lenf/ /g/ /h/ /lenh/ /mod/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero and that the length of \(g\) is one less than the+-- length of \(h\) (possibly with zero padding). The output is not allowed+-- to be aliased with any of the inputs.+foreign import ccall "nmod_poly.h _nmod_poly_compose_mod"+ _nmod_poly_compose_mod :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_compose_mod/ /res/ /f/ /g/ /h/ +-- +-- Sets @res@ to the composition \(f(g)\) modulo \(h\). We require that+-- \(h\) is nonzero.+foreign import ccall "nmod_poly.h nmod_poly_compose_mod"+ nmod_poly_compose_mod :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- Greatest common divisor -----------------------------------------------------++-- | /_nmod_poly_gcd_euclidean/ /G/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Computes the GCD of \(A\) of length @lenA@ and \(B\) of length @lenB@,+-- where @lenA >= lenB > 0@. The length of the GCD \(G\) is returned by the+-- function. No attempt is made to make the GCD monic. It is required that+-- \(G\) have space for @lenB@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_gcd_euclidean"+ _nmod_poly_gcd_euclidean :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CLong++-- | /nmod_poly_gcd_euclidean/ /G/ /A/ /B/ +-- +-- Computes the GCD of \(A\) and \(B\). The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+foreign import ccall "nmod_poly.h nmod_poly_gcd_euclidean"+ nmod_poly_gcd_euclidean :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_hgcd/ /M/ /lenM/ /A/ /lenA/ /B/ /lenB/ /a/ /lena/ /b/ /lenb/ /mod/ +-- +-- Computes the HGCD of \(a\) and \(b\), that is, a matrix~\`M\`, a+-- sign~\`sigma\` and two polynomials \(A\) and \(B\) such that+-- +-- \[`\]+-- \[(A,B)^t = M^{-1} (a,b)^t, \sigma = \det(M),\]+-- +-- and \(A\) and \(B\) are consecutive remainders in the Euclidean+-- remainder sequence for the division of \(a\) by \(b\) satisfying deg(A)+-- ge frac{deg(a)}{2} > deg(B). Furthermore, \(M\) will be the product of+-- @[[q 1][1 0]]@ for the quotients @q@ generated by such a remainder+-- sequence. Assumes that+-- \(\operatorname{len}(a) > \operatorname{len}(b) > 0\), i.e.+-- \(\deg(a) > :math:`deg(b) > 1\).+-- +-- Assumes that \(A\) and \(B\) have space of size at least+-- \(\operatorname{len}(a)\) and \(\operatorname{len}(b)\), respectively.+-- On exit, @*lenA@ and @*lenB@ will contain the correct lengths of \(A\)+-- and \(B\).+-- +-- Assumes that @M[0]@, @M[1]@, @M[2]@, and @M[3]@ each point to a vector+-- of size at least \(\operatorname{len}(a)\).+foreign import ccall "nmod_poly.h _nmod_poly_hgcd"+ _nmod_poly_hgcd :: Ptr (Ptr CMp) -> Ptr CLong -> Ptr CMp -> Ptr CLong -> Ptr CMp -> Ptr CLong -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CLong++-- | /_nmod_poly_gcd_hgcd/ /G/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Computes the monic GCD of \(A\) and \(B\), assuming that+-- \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\).+-- +-- Assumes that \(G\) has space for \(\operatorname{len}(B)\) coefficients+-- and returns the length of \(G\) on output.+foreign import ccall "nmod_poly.h _nmod_poly_gcd_hgcd"+ _nmod_poly_gcd_hgcd :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CLong++-- | /nmod_poly_gcd_hgcd/ /G/ /A/ /B/ +-- +-- Computes the monic GCD of \(A\) and \(B\) using the HGCD algorithm.+-- +-- As a special case, the GCD of two zero polynomials is defined to be the+-- zero polynomial.+-- +-- The time complexity of the algorithm is \(\mathcal{O}(n \log^2 n)\). For+-- further details, see~< [ThullYap1990]>.+foreign import ccall "nmod_poly.h nmod_poly_gcd_hgcd"+ nmod_poly_gcd_hgcd :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_gcd/ /G/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Computes the GCD of \(A\) of length @lenA@ and \(B\) of length @lenB@,+-- where @lenA >= lenB > 0@. The length of the GCD \(G\) is returned by the+-- function. No attempt is made to make the GCD monic. It is required that+-- \(G\) have space for @lenB@ coefficients.+foreign import ccall "nmod_poly.h _nmod_poly_gcd"+ _nmod_poly_gcd :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CLong++-- | /nmod_poly_gcd/ /G/ /A/ /B/ +-- +-- Computes the GCD of \(A\) and \(B\). The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+foreign import ccall "nmod_poly.h nmod_poly_gcd"+ nmod_poly_gcd :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_xgcd_euclidean/ /G/ /S/ /T/ /A/ /A_len/ /B/ /B_len/ /mod/ +-- +-- Computes the GCD of \(A\) and \(B\) together with cofactors \(S\) and+-- \(T\) such that \(S A + T B = G\). Returns the length of \(G\).+-- +-- Assumes that \(\operatorname{len}(A) \geq \operatorname{len}(B) \geq 1\)+-- and \((\operatorname{len}(A),\operatorname{len}(B)) \neq (1,1)\).+-- +-- No attempt is made to make the GCD monic.+-- +-- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- coefficients. Writes \(\operatorname{len}(B)-1\) and+-- \(\operatorname{len}(A)-1\) coefficients to \(S\) and \(T\),+-- respectively. Note that, in fact,+-- \(\operatorname{len}(S) \leq \max(\operatorname{len}(B) - \operatorname{len}(G), 1)\)+-- and+-- \(\operatorname{len}(T) \leq \max(\operatorname{len}(A) - \operatorname{len}(G), 1)\).+-- +-- No aliasing of input and output operands is permitted.+foreign import ccall "nmod_poly.h _nmod_poly_xgcd_euclidean"+ _nmod_poly_xgcd_euclidean :: Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CLong++-- | /nmod_poly_xgcd_euclidean/ /G/ /S/ /T/ /A/ /B/ +-- +-- Computes the GCD of \(A\) and \(B\). The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+-- +-- Polynomials @S@ and @T@ are computed such that @S*A + T*B = G@. The+-- length of @S@ will be at most @lenB@ and the length of @T@ will be at+-- most @lenA@.+foreign import ccall "nmod_poly.h nmod_poly_xgcd_euclidean"+ nmod_poly_xgcd_euclidean :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_xgcd_hgcd/ /G/ /S/ /T/ /A/ /A_len/ /B/ /B_len/ /mod/ +-- +-- Computes the GCD of \(A\) and \(B\), where+-- \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\), together with+-- cofactors \(S\) and \(T\) such that \(S A + T B = G\). Returns the+-- length of \(G\).+-- +-- No attempt is made to make the GCD monic.+-- +-- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- coefficients. Writes \(\operatorname{len}(B) - 1\) and+-- \(\operatorname{len}(A) - 1\) coefficients to \(S\) and \(T\),+-- respectively. Note that, in fact,+-- \(\operatorname{len}(S) \leq \operatorname{len}(B) - \operatorname{len}(G)\)+-- and+-- \(\operatorname{len}(T) \leq \operatorname{len}(A) - \operatorname{len}(G)\).+-- +-- Both \(S\) and \(T\) must have space for at least \(2\) coefficients.+-- +-- No aliasing of input and output operands is permitted.+foreign import ccall "nmod_poly.h _nmod_poly_xgcd_hgcd"+ _nmod_poly_xgcd_hgcd :: Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CLong++-- | /nmod_poly_xgcd_hgcd/ /G/ /S/ /T/ /A/ /B/ +-- +-- Computes the GCD of \(A\) and \(B\). The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+-- +-- Polynomials @S@ and @T@ are computed such that @S*A + T*B = G@. The+-- length of @S@ will be at most @lenB@ and the length of @T@ will be at+-- most @lenA@.+foreign import ccall "nmod_poly.h nmod_poly_xgcd_hgcd"+ nmod_poly_xgcd_hgcd :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_xgcd/ /G/ /S/ /T/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Computes the GCD of \(A\) and \(B\), where+-- \(\operatorname{len}(A) \geq \operatorname{len}(B) > 0\), together with+-- cofactors \(S\) and \(T\) such that \(S A + T B = G\). Returns the+-- length of \(G\).+-- +-- No attempt is made to make the GCD monic.+-- +-- Requires that \(G\) have space for \(\operatorname{len}(B)\)+-- coefficients. Writes \(\operatorname{len}(B) - 1\) and+-- \(\operatorname{len}(A) - 1\) coefficients to \(S\) and \(T\),+-- respectively. Note that, in fact,+-- \(\operatorname{len}(S) \leq \operatorname{len}(B) - \operatorname{len}(G)\)+-- and+-- \(\operatorname{len}(T) \leq \operatorname{len}(A) - \operatorname{len}(G)\).+-- +-- No aliasing of input and output operands is permitted.+foreign import ccall "nmod_poly.h _nmod_poly_xgcd"+ _nmod_poly_xgcd :: Ptr CMp -> Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CLong++-- | /nmod_poly_xgcd/ /G/ /S/ /T/ /A/ /B/ +-- +-- Computes the GCD of \(A\) and \(B\). The GCD of zero polynomials is+-- defined to be zero, whereas the GCD of the zero polynomial and some+-- other polynomial \(P\) is defined to be \(P\). Except in the case where+-- the GCD is zero, the GCD \(G\) is made monic.+-- +-- The polynomials @S@ and @T@ are set such that @S*A + T*B = G@. The+-- length of @S@ will be at most @lenB@ and the length of @T@ will be at+-- most @lenA@.+foreign import ccall "nmod_poly.h nmod_poly_xgcd"+ nmod_poly_xgcd :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_resultant_euclidean/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- +-- Returns the resultant of @(poly1, len1)@ and @(poly2, len2)@ using the+-- Euclidean algorithm.+-- +-- Assumes that @len1 >= len2 > 0@.+-- +-- Assumes that the modulus is prime.+foreign import ccall "nmod_poly.h _nmod_poly_resultant_euclidean"+ _nmod_poly_resultant_euclidean :: Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CMpLimb++-- | /nmod_poly_resultant_euclidean/ /f/ /g/ +-- +-- Computes the resultant of \(f\) and \(g\) using the Euclidean algorithm.+-- +-- For two non-zero polynomials \(f(x) = a_m x^m + \dotsb + a_0\) and+-- \(g(x) = b_n x^n + \dotsb + b_0\) of degrees \(m\) and \(n\), the+-- resultant is defined to be+-- +-- \[`+-- a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y).\]+-- +-- For convenience, we define the resultant to be equal to zero if either+-- of the two polynomials is zero.+foreign import ccall "nmod_poly.h nmod_poly_resultant_euclidean"+ nmod_poly_resultant_euclidean :: Ptr CNModPoly -> Ptr CNModPoly -> IO CMpLimb++-- | /_nmod_poly_resultant_hgcd/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- +-- Returns the resultant of @(poly1, len1)@ and @(poly2, len2)@ using the+-- half-gcd algorithm.+-- +-- This algorithm computes the half-gcd as per @_nmod_poly_gcd_hgcd@ but+-- additionally updates the resultant every time a division occurs. The+-- half-gcd algorithm computes the GCD recursively. Given inputs \(a\) and+-- \(b\) it lets @m = len(a)\/2@ and (recursively) performs all quotients+-- in the Euclidean algorithm which do not require the low \(m\)+-- coefficients of \(a\) and \(b\).+-- +-- This performs quotients in exactly the same order as the ordinary+-- Euclidean algorithm except that the low \(m\) coefficients of the+-- polynomials in the remainder sequence are not computed. A correction+-- step after hgcd has been called computes these low \(m\) coefficients+-- (by matrix multiplication by a transformation matrix also computed by+-- hgcd).+-- +-- This means that from the point of view of the resultant, all but the+-- last quotient performed by a recursive call to hgcd is an ordinary+-- quotient as per the usual Euclidean algorithm. However, the final+-- quotient may give a remainder of less than \(m + 1\) coefficients, which+-- won\'t be corrected until the hgcd correction step is performed+-- afterwards.+-- +-- To compute the adjustments to the resultant coming from this corrected+-- quotient, we save the relevant information in an @nmod_poly_res_t@+-- struct at the time the quotient is performed so that when the correction+-- step is performed later, the adjustments to the resultant can be+-- computed at that time also.+-- +-- The only time an adjustment to the resultant is not required after a+-- call to hgcd is if hgcd does nothing (the remainder may already have had+-- less than \(m + 1\) coefficients when hgcd was called).+-- +-- Assumes that @len1 >= len2 > 0@.+-- +-- Assumes that the modulus is prime.+foreign import ccall "nmod_poly.h _nmod_poly_resultant_hgcd"+ _nmod_poly_resultant_hgcd :: Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CMpLimb++-- | /nmod_poly_resultant_hgcd/ /f/ /g/ +-- +-- Computes the resultant of \(f\) and \(g\) using the half-gcd algorithm.+-- +-- For two non-zero polynomials \(f(x) = a_m x^m + \dotsb + a_0\) and+-- \(g(x) = b_n x^n + \dotsb + b_0\) of degrees \(m\) and \(n\), the+-- resultant is defined to be+-- +-- \[`\]+-- \[a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y).\]+-- +-- For convenience, we define the resultant to be equal to zero if either+-- of the two polynomials is zero.+foreign import ccall "nmod_poly.h nmod_poly_resultant_hgcd"+ nmod_poly_resultant_hgcd :: Ptr CNModPoly -> Ptr CNModPoly -> IO CMpLimb++-- | /_nmod_poly_resultant/ /poly1/ /len1/ /poly2/ /len2/ /mod/ +-- +-- Returns the resultant of @(poly1, len1)@ and @(poly2, len2)@.+-- +-- Assumes that @len1 >= len2 > 0@.+-- +-- Assumes that the modulus is prime.+foreign import ccall "nmod_poly.h _nmod_poly_resultant"+ _nmod_poly_resultant :: Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CMpLimb++-- | /nmod_poly_resultant/ /f/ /g/ +-- +-- Computes the resultant of \(f\) and \(g\).+-- +-- For two non-zero polynomials \(f(x) = a_m x^m + \dotsb + a_0\) and+-- \(g(x) = b_n x^n + \dotsb + b_0\) of degrees \(m\) and \(n\), the+-- resultant is defined to be+-- +-- \[`\]+-- \[a_m^n b_n^m \prod_{(x, y) : f(x) = g(y) = 0} (x - y).\]+-- +-- For convenience, we define the resultant to be equal to zero if either+-- of the two polynomials is zero.+foreign import ccall "nmod_poly.h nmod_poly_resultant"+ nmod_poly_resultant :: Ptr CNModPoly -> Ptr CNModPoly -> IO CMpLimb++-- | /_nmod_poly_gcdinv/ /G/ /S/ /A/ /lenA/ /B/ /lenB/ /mod/ +-- +-- Computes @(G, lenA)@, @(S, lenB-1)@ such that \(G \cong S A \pmod{B}\),+-- returning the actual length of \(G\).+-- +-- Assumes that \(0 < \operatorname{len}(A) < \operatorname{len}(B)\).+foreign import ccall "nmod_poly.h _nmod_poly_gcdinv"+ _nmod_poly_gcdinv :: Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CLong++-- | /nmod_poly_gcdinv/ /G/ /S/ /A/ /B/ +-- +-- Computes polynomials \(G\) and \(S\), both reduced modulo~\`B\`, such+-- that \(G \cong S A \pmod{B}\), where \(B\) is assumed to have+-- \(\operatorname{len}(B) \geq 2\).+-- +-- In the case that \(A = 0 \pmod{B}\), returns \(G = S = 0\).+foreign import ccall "nmod_poly.h nmod_poly_gcdinv"+ nmod_poly_gcdinv :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_invmod/ /A/ /B/ /lenB/ /P/ /lenP/ /mod/ +-- +-- Attempts to set @(A, lenP-1)@ to the inverse of @(B, lenB)@ modulo the+-- polynomial @(P, lenP)@. Returns \(1\) if @(B, lenB)@ is invertible and+-- \(0\) otherwise.+-- +-- Assumes that \(0 < \operatorname{len}(B) < \operatorname{len}(P)\), and+-- hence also \(\operatorname{len}(P) \geq 2\), but supports zero-padding+-- in @(B, lenB)@.+-- +-- Does not support aliasing.+-- +-- Assumes that \(mod\) is a prime number.+foreign import ccall "nmod_poly.h _nmod_poly_invmod"+ _nmod_poly_invmod :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> Ptr CNMod -> IO CInt++-- | /nmod_poly_invmod/ /A/ /B/ /P/ +-- +-- Attempts to set \(A\) to the inverse of \(B\) modulo \(P\) in the+-- polynomial ring \((\mathbf{Z}/p\mathbf{Z})[X]\), where we assume that+-- \(p\) is a prime number.+-- +-- If \(\operatorname{len}(P) < 2\), raises an exception.+-- +-- If the greatest common divisor of \(B\) and \(P\) is~\`1\`,+-- returns~\`1\` and sets \(A\) to the inverse of \(B\). Otherwise,+-- returns~\`0\` and the value of \(A\) on exit is undefined.+foreign import ccall "nmod_poly.h nmod_poly_invmod"+ nmod_poly_invmod :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> IO CInt++-- Power series composition ----------------------------------------------------++-- | /_nmod_poly_discriminant/ /poly/ /len/ /mod/ +-- +-- Return the discriminant of @(poly, len)@. Assumes @len > 1@.+foreign import ccall "nmod_poly.h _nmod_poly_discriminant"+ _nmod_poly_discriminant :: Ptr CMp -> CLong -> Ptr CNMod -> IO CMpLimb++-- | /nmod_poly_discriminant/ /f/ +-- +-- Return the discriminant of \(f\). We normalise the discriminant so that+-- \(\operatorname{disc}(f) = (-1)^(n(n-1)/2) \operatorname{res}(f, f') /+-- \operatorname{lc}(f)^(n - m - 2)\), where @n = len(f)@ and+-- @m = len(f\')@. Thus \(\operatorname{disc}(f) =+-- \operatorname{lc}(f)^(2n - 2) \prod_{i < j} (r_i - r_j)^2\), where+-- \(\operatorname{lc}(f)\) is the leading coefficient of \(f\) and \(r_i\)+-- are the roots of \(f\).+foreign import ccall "nmod_poly.h nmod_poly_discriminant"+ nmod_poly_discriminant :: Ptr CNModPoly -> IO CMpLimb++-- Power series composition ----------------------------------------------------++-- | /_nmod_poly_compose_series/ /res/ /poly1/ /len1/ /poly2/ /len2/ /n/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@ modulo \(x^n\),+-- where the constant term of @poly2@ is required to be zero.+-- +-- Assumes that @len1, len2, n > 0@, that @len1, len2 \<= n@, and that\\+-- @(len1-1) * (len2-1) + 1 \<= n@, and that @res@ has space for @n@+-- coefficients. Does not support aliasing between any of the inputs and+-- the output.+-- +-- Wraps @_gr_poly_compose_series@ which chooses automatically between+-- various algorithms.+foreign import ccall "nmod_poly.h _nmod_poly_compose_series"+ _nmod_poly_compose_series :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CMp -> CLong -> CLong -> IO ()++-- | /nmod_poly_compose_series/ /res/ /poly1/ /poly2/ /n/ +-- +-- Sets @res@ to the composition of @poly1@ and @poly2@ modulo \(x^n\),+-- where the constant term of @poly2@ is required to be zero.+foreign import ccall "nmod_poly.h nmod_poly_compose_series"+ nmod_poly_compose_series :: Ptr CNModPoly -> Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- Power series reversion ------------------------------------------------------++-- | /_nmod_poly_revert_series_lagrange/ /Qinv/ /Q/ /n/ /mod/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). The arguments must both+-- have length @n@ and may not be aliased.+-- +-- It is required that \(Q_0 = 0\) and that \(Q_1\) as well as the integers+-- \(1, 2, \ldots, n-1\) are invertible modulo the modulus.+-- +-- This implementation uses the Lagrange inversion formula.+foreign import ccall "nmod_poly.h _nmod_poly_revert_series_lagrange"+ _nmod_poly_revert_series_lagrange :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_revert_series_lagrange/ /Qinv/ /Q/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\).+-- +-- It is required that \(Q_0 = 0\) and that \(Q_1\) as well as the integers+-- \(1, 2, \ldots, n-1\) are invertible modulo the modulus.+-- +-- This implementation uses the Lagrange inversion formula.+foreign import ccall "nmod_poly.h nmod_poly_revert_series_lagrange"+ nmod_poly_revert_series_lagrange :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_revert_series_lagrange_fast/ /Qinv/ /Q/ /n/ /mod/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). The arguments must both+-- have length @n@ and may not be aliased.+-- +-- It is required that \(Q_0 = 0\) and that \(Q_1\) as well as the integers+-- \(1, 2, \ldots, n-1\) are invertible modulo the modulus.+-- +-- This implementation uses a reduced-complexity implementation of the+-- Lagrange inversion formula.+foreign import ccall "nmod_poly.h _nmod_poly_revert_series_lagrange_fast"+ _nmod_poly_revert_series_lagrange_fast :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_revert_series_lagrange_fast/ /Qinv/ /Q/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\).+-- +-- It is required that \(Q_0 = 0\) and that \(Q_1\) as well as the integers+-- \(1, 2, \ldots, n-1\) are invertible modulo the modulus.+-- +-- This implementation uses a reduced-complexity implementation of the+-- Lagrange inversion formula.+foreign import ccall "nmod_poly.h nmod_poly_revert_series_lagrange_fast"+ nmod_poly_revert_series_lagrange_fast :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_revert_series_newton/ /Qinv/ /Q/ /n/ /mod/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). The arguments must both+-- have length @n@ and may not be aliased.+-- +-- It is required that \(Q_0 = 0\) and that \(Q_1\) as well as the integers+-- \(1, 2, \ldots, n-1\) are invertible modulo the modulus.+-- +-- This implementation uses Newton iteration < [BrentKung1978]>.+foreign import ccall "nmod_poly.h _nmod_poly_revert_series_newton"+ _nmod_poly_revert_series_newton :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_revert_series_newton/ /Qinv/ /Q/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\).+-- +-- It is required that \(Q_0 = 0\) and that \(Q_1\) as well as the integers+-- \(1, 2, \ldots, n-1\) are invertible modulo the modulus.+-- +-- This implementation uses Newton iteration < [BrentKung1978]>.+foreign import ccall "nmod_poly.h nmod_poly_revert_series_newton"+ nmod_poly_revert_series_newton :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_revert_series/ /Qinv/ /Q/ /n/ /mod/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\). The arguments must both+-- have length @n@ and may not be aliased.+-- +-- It is required that \(Q_0 = 0\) and that \(Q_1\) as well as the integers+-- \(1, 2, \ldots, n-1\) are invertible modulo the modulus.+-- +-- This implementation automatically chooses between the Lagrange inversion+-- formula and Newton iteration based on the size of the input.+foreign import ccall "nmod_poly.h _nmod_poly_revert_series"+ _nmod_poly_revert_series :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_revert_series/ /Qinv/ /Q/ /n/ +-- +-- Sets @Qinv@ to the compositional inverse or reversion of @Q@ as a power+-- series, i.e. computes \(Q^{-1}\) such that+-- \(Q(Q^{-1}(x)) = Q^{-1}(Q(x)) = x \bmod x^n\).+-- +-- It is required that \(Q_0 = 0\) and that \(Q_1\) as well as the integers+-- \(1, 2, \ldots, n-1\) are invertible modulo the modulus.+-- +-- This implementation automatically chooses between the Lagrange inversion+-- formula and Newton iteration based on the size of the input.+foreign import ccall "nmod_poly.h nmod_poly_revert_series"+ nmod_poly_revert_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- Square roots ----------------------------------------------------------------++-- The series expansions for \(\sqrt{h}\) and \(1/\sqrt{h}\) are defined by+-- means of the generalised binomial theorem+-- @h^r = (1+y)^r = \\sum_{k=0}^{\\infty} {r \\choose k} y^k.@ It is+-- assumed that \(h\) has constant term \(1\) and that the coefficients+-- 2^{-k} exist in the coefficient ring (i.e. \(2\) must be invertible).+--+-- | /_nmod_poly_invsqrt_series/ /g/ /h/ /hlen/ /n/ /mod/ +-- +-- Set the first \(n\) terms of \(g\) to the series expansion of+-- \(1/\sqrt{h}\). It is assumed that \(n > 0\), that \(h\) has constant+-- term 1. Aliasing is not permitted.+foreign import ccall "nmod_poly.h _nmod_poly_invsqrt_series"+ _nmod_poly_invsqrt_series :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_invsqrt_series/ /g/ /h/ /n/ +-- +-- Set \(g\) to the series expansion of \(1/\sqrt{h}\) to order \(O(x^n)\).+-- It is assumed that \(h\) has constant term 1.+foreign import ccall "nmod_poly.h nmod_poly_invsqrt_series"+ nmod_poly_invsqrt_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_sqrt_series/ /g/ /h/ /hlen/ /n/ /mod/ +-- +-- Set the first \(n\) terms of \(g\) to the series expansion of+-- \(\sqrt{h}\). It is assumed that \(n > 0\), that \(h\) has constant term+-- 1. Aliasing is not permitted.+foreign import ccall "nmod_poly.h _nmod_poly_sqrt_series"+ _nmod_poly_sqrt_series :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_sqrt_series/ /g/ /h/ /n/ +-- +-- Set \(g\) to the series expansion of \(\sqrt{h}\) to order \(O(x^n)\).+-- It is assumed that \(h\) has constant term 1.+foreign import ccall "nmod_poly.h nmod_poly_sqrt_series"+ nmod_poly_sqrt_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_sqrt/ /s/ /p/ /n/ /mod/ +-- +-- If @(p, n)@ is a perfect square, sets @(s, n \/ 2 + 1)@ to a square root+-- of \(p\) and returns 1. Otherwise returns 0.+foreign import ccall "nmod_poly.h _nmod_poly_sqrt"+ _nmod_poly_sqrt :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO CInt++-- | /nmod_poly_sqrt/ /s/ /p/ +-- +-- If \(p\) is a perfect square, sets \(s\) to a square root of \(p\) and+-- returns 1. Otherwise returns 0.+foreign import ccall "nmod_poly.h nmod_poly_sqrt"+ nmod_poly_sqrt :: Ptr CNModPoly -> Ptr CNModPoly -> IO CInt++-- Power sums ------------------------------------------------------------------++-- | /_nmod_poly_power_sums_naive/ /res/ /poly/ /len/ /n/ /mod/ +-- +-- Compute the (truncated) power sums series of the polynomial @(poly,len)@+-- up to length \(n\) using Newton identities.+foreign import ccall "nmod_poly.h _nmod_poly_power_sums_naive"+ _nmod_poly_power_sums_naive :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_power_sums_naive/ /res/ /poly/ /n/ +-- +-- Compute the (truncated) power sum series of the polynomial @poly@ up to+-- length \(n\) using Newton identities.+foreign import ccall "nmod_poly.h nmod_poly_power_sums_naive"+ nmod_poly_power_sums_naive :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_power_sums_schoenhage/ /res/ /poly/ /len/ /n/ /mod/ +-- +-- Compute the (truncated) power sums series of the polynomial @(poly,len)@+-- up to length \(n\) using a series expansion (a formula due to+-- Schoenhage).+foreign import ccall "nmod_poly.h _nmod_poly_power_sums_schoenhage"+ _nmod_poly_power_sums_schoenhage :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_power_sums_schoenhage/ /res/ /poly/ /n/ +-- +-- Compute the (truncated) power sums series of the polynomial @poly@ up to+-- length \(n\) using a series expansion (a formula due to Schoenhage).+foreign import ccall "nmod_poly.h nmod_poly_power_sums_schoenhage"+ nmod_poly_power_sums_schoenhage :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_power_sums/ /res/ /poly/ /len/ /n/ /mod/ +-- +-- Compute the (truncated) power sums series of the polynomial @(poly,len)@+-- up to length \(n\).+foreign import ccall "nmod_poly.h _nmod_poly_power_sums"+ _nmod_poly_power_sums :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_power_sums/ /res/ /poly/ /n/ +-- +-- Compute the (truncated) power sums series of the polynomial @poly@ up to+-- length \(n\).+foreign import ccall "nmod_poly.h nmod_poly_power_sums"+ nmod_poly_power_sums :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_power_sums_to_poly_naive/ /res/ /poly/ /len/ /mod/ +-- +-- Compute the (monic) polynomial given by its power sums series+-- @(poly,len)@ using Newton identities.+foreign import ccall "nmod_poly.h _nmod_poly_power_sums_to_poly_naive"+ _nmod_poly_power_sums_to_poly_naive :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_power_sums_to_poly_naive/ /res/ /Q/ +-- +-- Compute the (monic) polynomial given by its power sums series @Q@ using+-- Newton identities.+foreign import ccall "nmod_poly.h nmod_poly_power_sums_to_poly_naive"+ nmod_poly_power_sums_to_poly_naive :: Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_power_sums_to_poly_schoenhage/ /res/ /poly/ /len/ /mod/ +-- +-- Compute the (monic) polynomial given by its power sums series+-- @(poly,len)@ using series expansion (a formula due to Schoenhage).+foreign import ccall "nmod_poly.h _nmod_poly_power_sums_to_poly_schoenhage"+ _nmod_poly_power_sums_to_poly_schoenhage :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_power_sums_to_poly_schoenhage/ /res/ /Q/ +-- +-- Compute the (monic) polynomial given by its power sums series @Q@ using+-- series expansion (a formula due to Schoenhage).+foreign import ccall "nmod_poly.h nmod_poly_power_sums_to_poly_schoenhage"+ nmod_poly_power_sums_to_poly_schoenhage :: Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- | /_nmod_poly_power_sums_to_poly/ /res/ /poly/ /len/ /mod/ +-- +-- Compute the (monic) polynomial given by its power sums series+-- @(poly,len)@.+foreign import ccall "nmod_poly.h _nmod_poly_power_sums_to_poly"+ _nmod_poly_power_sums_to_poly :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_power_sums_to_poly/ /res/ /Q/ +-- +-- Compute the (monic) polynomial given by its power sums series @Q@.+foreign import ccall "nmod_poly.h nmod_poly_power_sums_to_poly"+ nmod_poly_power_sums_to_poly :: Ptr CNModPoly -> Ptr CNModPoly -> IO ()++-- Transcendental functions ----------------------------------------------------++-- The elementary transcendental functions of a formal power series \(h\)+-- are defined as+--+-- exp(h(x)) = sum_{k=0}^{infty} frac{(h(x))^k}{k!}+--+-- log(h(x)) = int_0^x frac{h\'(t)}{h(t)} dt+--+-- operatorname{atan}(h(x)) = int_0^xfrac{h\'(t)}{1+(h(t))^2} dt+--+-- operatorname{atanh}(h(x)) = int_0^xfrac{h\'(t)}{1-(h(t))^2} dt+--+-- operatorname{asin}(h(x)) = int_0^xfrac{h\'(t)}{sqrt{1-(h(t))^2}} dt+--+-- operatorname{asinh}(h(x)) = int_0^xfrac{h\'(t)}{sqrt{1+(h(t))^2}} dt+--+-- The functions sin, cos, tan, etc. are defined using standard inverse or+-- functional relations. The logarithm function assumes that \(h\) has+-- constant term \(1\). All other functions assume that \(h\) has constant+-- term \(0\). All functions assume that the coefficient \(1/k\) or+-- \(1/k!\) exists for all indices \(k\). When computing to order+-- \(O(x^n)\), the modulus \(p\) must therefore be a prime satisfying+-- \(p \ge n\). Further, we always require that \(p > 2\) in order to be+-- able to multiply by \(1/2\) for internal purposes. If the input does not+-- satisfy all these conditions, results are undefined. Except where+-- otherwise noted, functions are implemented with optimal (up to+-- constants) complexity \(O(M(n))\), where \(M(n)\) is the cost of+-- polynomial multiplication.+--+-- | /_nmod_poly_log_series/ /g/ /h/ /hlen/ /n/ /mod/ +-- +-- Set \(g = \log(h) + O(x^n)\). Assumes \(n > 0\) and @hlen > 0@. Aliasing+-- of \(g\) and \(h\) is allowed.+foreign import ccall "nmod_poly.h _nmod_poly_log_series"+ _nmod_poly_log_series :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_log_series/ /g/ /h/ /n/ +-- +-- Set \(g = \log(h) + O(x^n)\). The case \(h = 1+cx^r\) is automatically+-- detected and handled efficiently.+foreign import ccall "nmod_poly.h nmod_poly_log_series"+ nmod_poly_log_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_exp_series/ /f/ /h/ /hlen/ /n/ /mod/ +-- +-- Set \(f = \exp(h) + O(x^n)\) where @h@ is a polynomial. Assume+-- \(n > 0\). Aliasing of \(g\) and \(h\) is not allowed.+-- +-- Uses Newton iteration (an improved version of the algorithm in+-- < [HanZim2004]>). For small \(n\), falls back to the basecase algorithm.+foreign import ccall "nmod_poly.h _nmod_poly_exp_series"+ _nmod_poly_exp_series :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /_nmod_poly_exp_expinv_series/ /f/ /g/ /h/ /n/ /mod/ +-- +-- Set \(f = \exp(h) + O(x^n)\) and \(g = \exp(-h) + O(x^n)\), more+-- efficiently for large \(n\) than performing a separate inversion to+-- obtain \(g\). Assumes \(n > 0\) and that \(h\) is zero-padded as+-- necessary to length \(n\). Aliasing is not allowed.+-- +-- Uses Newton iteration (the version given in < [HanZim2004]>). For small+-- \(n\), falls back to the basecase algorithm.+foreign import ccall "nmod_poly.h _nmod_poly_exp_expinv_series"+ _nmod_poly_exp_expinv_series :: Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_exp_series/ /g/ /h/ /n/ +-- +-- Set \(g = \exp(h) + O(x^n)\). The case \(h = cx^r\) is automatically+-- detected and handled efficiently. Otherwise this function automatically+-- uses the basecase algorithm for small \(n\) and Newton iteration+-- otherwise.+foreign import ccall "nmod_poly.h nmod_poly_exp_series"+ nmod_poly_exp_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_atan_series/ /g/ /h/ /n/ /mod/ +-- +-- Set \(g = \operatorname{atan}(h) + O(x^n)\). Assumes \(n > 0\). Aliasing+-- of \(g\) and \(h\) is allowed.+foreign import ccall "nmod_poly.h _nmod_poly_atan_series"+ _nmod_poly_atan_series :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_atan_series/ /g/ /h/ /n/ +-- +-- Set \(g = \operatorname{atan}(h) + O(x^n)\).+foreign import ccall "nmod_poly.h nmod_poly_atan_series"+ nmod_poly_atan_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_atanh_series/ /g/ /h/ /n/ /mod/ +-- +-- Set \(g = \operatorname{atanh}(h) + O(x^n)\). Assumes \(n > 0\).+-- Aliasing of \(g\) and \(h\) is allowed.+foreign import ccall "nmod_poly.h _nmod_poly_atanh_series"+ _nmod_poly_atanh_series :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_atanh_series/ /g/ /h/ /n/ +-- +-- Set \(g = \operatorname{atanh}(h) + O(x^n)\).+foreign import ccall "nmod_poly.h nmod_poly_atanh_series"+ nmod_poly_atanh_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_asin_series/ /g/ /h/ /hlen/ /n/ /mod/ +-- +-- Set \(g = \operatorname{asin}(h) + O(x^n)\). Assumes \(n > 0\). Aliasing+-- of \(g\) and \(h\) is allowed.+foreign import ccall "nmod_poly.h _nmod_poly_asin_series"+ _nmod_poly_asin_series :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_asin_series/ /g/ /h/ /n/ +-- +-- Set \(g = \operatorname{asin}(h) + O(x^n)\).+foreign import ccall "nmod_poly.h nmod_poly_asin_series"+ nmod_poly_asin_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_asinh_series/ /g/ /h/ /hlen/ /n/ /mod/ +-- +-- Set \(g = \operatorname{asinh}(h) + O(x^n)\). Assumes \(n > 0\).+-- Aliasing of \(g\) and \(h\) is allowed.+foreign import ccall "nmod_poly.h _nmod_poly_asinh_series"+ _nmod_poly_asinh_series :: Ptr CMp -> Ptr CMp -> CLong -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_asinh_series/ /g/ /h/ /n/ +-- +-- Set \(g = \operatorname{asinh}(h) + O(x^n)\).+foreign import ccall "nmod_poly.h nmod_poly_asinh_series"+ nmod_poly_asinh_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_sin_series/ /g/ /h/ /n/ /mod/ +-- +-- Set \(g = \operatorname{sin}(h) + O(x^n)\). Assumes \(n > 0\) and that+-- \(h\) is zero-padded as necessary to length \(n\). Aliasing of \(g\) and+-- \(h\) is allowed. The value is computed using the identity+-- \(\sin(x) = 2 \tan(x/2)) / (1 + \tan^2(x/2)).\)+foreign import ccall "nmod_poly.h _nmod_poly_sin_series"+ _nmod_poly_sin_series :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_sin_series/ /g/ /h/ /n/ +-- +-- Set \(g = \operatorname{sin}(h) + O(x^n)\).+foreign import ccall "nmod_poly.h nmod_poly_sin_series"+ nmod_poly_sin_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_cos_series/ /g/ /h/ /n/ /mod/ +-- +-- Set \(g = \operatorname{cos}(h) + O(x^n)\). Assumes \(n > 0\) and that+-- \(h\) is zero-padded as necessary to length \(n\). Aliasing of \(g\) and+-- \(h\) is allowed. The value is computed using the identity+-- \(\cos(x) = (1-\tan^2(x/2)) / (1 + \tan^2(x/2)).\)+foreign import ccall "nmod_poly.h _nmod_poly_cos_series"+ _nmod_poly_cos_series :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_cos_series/ /g/ /h/ /n/ +-- +-- Set \(g = \operatorname{cos}(h) + O(x^n)\).+foreign import ccall "nmod_poly.h nmod_poly_cos_series"+ nmod_poly_cos_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_tan_series/ /g/ /h/ /n/ /mod/ +-- +-- Set \(g = \operatorname{tan}(h) + O(x^n)\). Assumes \(n > 0\) and that+-- \(h\) is zero-padded as necessary to length \(n\). Aliasing of \(g\) and+-- \(h\) is not allowed. Uses Newton iteration to invert the atan function.+foreign import ccall "nmod_poly.h _nmod_poly_tan_series"+ _nmod_poly_tan_series :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_tan_series/ /g/ /h/ /n/ +-- +-- Set \(g = \operatorname{tan}(h) + O(x^n)\).+foreign import ccall "nmod_poly.h nmod_poly_tan_series"+ nmod_poly_tan_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_sinh_series/ /g/ /h/ /n/ /mod/ +-- +-- Set \(g = \operatorname{sinh}(h) + O(x^n)\). Assumes \(n > 0\) and that+-- \(h\) is zero-padded as necessary to length \(n\). Aliasing of \(g\) and+-- \(h\) is not allowed. Uses the identity \(\sinh(x) = (e^x - e^{-x})/2\).+foreign import ccall "nmod_poly.h _nmod_poly_sinh_series"+ _nmod_poly_sinh_series :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_sinh_series/ /g/ /h/ /n/ +-- +-- Set \(g = \operatorname{sinh}(h) + O(x^n)\).+foreign import ccall "nmod_poly.h nmod_poly_sinh_series"+ nmod_poly_sinh_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_cosh_series/ /g/ /h/ /n/ /mod/ +-- +-- Set \(g = \operatorname{cos}(h) + O(x^n)\). Assumes \(n > 0\) and that+-- \(h\) is zero-padded as necessary to length \(n\). Aliasing of \(g\) and+-- \(h\) is not allowed. Uses the identity \(\cosh(x) = (e^x + e^{-x})/2\).+foreign import ccall "nmod_poly.h _nmod_poly_cosh_series"+ _nmod_poly_cosh_series :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_cosh_series/ /g/ /h/ /n/ +-- +-- Set \(g = \operatorname{cosh}(h) + O(x^n)\).+foreign import ccall "nmod_poly.h nmod_poly_cosh_series"+ nmod_poly_cosh_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- | /_nmod_poly_tanh_series/ /g/ /h/ /n/ /mod/ +-- +-- Set \(g = \operatorname{tanh}(h) + O(x^n)\). Assumes \(n > 0\) and that+-- \(h\) is zero-padded as necessary to length \(n\). Uses the identity+-- \(\tanh(x) = (e^{2x}-1)/(e^{2x}+1)\).+foreign import ccall "nmod_poly.h _nmod_poly_tanh_series"+ _nmod_poly_tanh_series :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_tanh_series/ /g/ /h/ /n/ +-- +-- Set \(g = \operatorname{tanh}(h) + O(x^n)\).+foreign import ccall "nmod_poly.h nmod_poly_tanh_series"+ nmod_poly_tanh_series :: Ptr CNModPoly -> Ptr CNModPoly -> CLong -> IO ()++-- Products --------------------------------------------------------------------++-- | /_nmod_poly_product_roots_nmod_vec/ /poly/ /xs/ /n/ /mod/ +-- +-- Sets @(poly, n + 1)@ to the monic polynomial which is the product of+-- \((x - x_0)(x - x_1) \cdots (x - x_{n-1})\), the roots \(x_i\) being+-- given by @xs@.+-- +-- Aliasing of the input and output is not allowed.+foreign import ccall "nmod_poly.h _nmod_poly_product_roots_nmod_vec"+ _nmod_poly_product_roots_nmod_vec :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /nmod_poly_product_roots_nmod_vec/ /poly/ /xs/ /n/ +-- +-- Sets @poly@ to the monic polynomial which is the product of+-- \((x - x_0)(x - x_1) \cdots (x - x_{n-1})\), the roots \(x_i\) being+-- given by @xs@.+foreign import ccall "nmod_poly.h nmod_poly_product_roots_nmod_vec"+ nmod_poly_product_roots_nmod_vec :: Ptr CNModPoly -> Ptr CMp -> CLong -> IO ()++-- | /nmod_poly_find_distinct_nonzero_roots/ /roots/ /A/ +-- +-- If @A@ has \(\deg(A)\) distinct nonzero roots in \(\mathbb{F}_p\), write+-- these roots out to @roots[0]@ to @roots[deg(A) - 1]@ and return @1@.+-- Otherwise, return @0@. It is assumed that @A@ is nonzero and that the+-- modulus of @A@ is prime. This function uses Rabin\'s probabilistic+-- method via gcd\'s with \((x + \delta)^{\frac{p-1}{2}} - 1\).+foreign import ccall "nmod_poly.h nmod_poly_find_distinct_nonzero_roots"+ nmod_poly_find_distinct_nonzero_roots :: Ptr CMpLimb -> Ptr CNModPoly -> IO CInt++-- Subproduct trees ------------------------------------------------------------++-- | /_nmod_poly_tree_alloc/ /len/ +-- +-- Allocates space for a subproduct tree of the given length, having linear+-- factors at the lowest level.+-- +-- Entry \(i\) in the tree is a pointer to a single array of limbs, capable+-- of storing \(\lfloor n / 2^i \rfloor\) subproducts of degree \(2^i\)+-- adjacently, plus a trailing entry if \(n / 2^i\) is not an integer.+-- +-- For example, a tree of length 7 built from monic linear factors has the+-- following structure, where spaces have been inserted for illustrative+-- purposes:+-- +-- > X1 X1 X1 X1 X1 X1 X1+-- > XX1 XX1 XX1 X1+-- > XXXX1 XX1 X1+-- > XXXXXXX1+foreign import ccall "nmod_poly.h _nmod_poly_tree_alloc"+ _nmod_poly_tree_alloc :: CLong -> IO (Ptr (Ptr CMp))++-- | /_nmod_poly_tree_free/ /tree/ /len/ +-- +-- Free the allocated space for the subproduct.+foreign import ccall "nmod_poly.h _nmod_poly_tree_free"+ _nmod_poly_tree_free :: Ptr (Ptr CMp) -> CLong -> IO ()++-- | /_nmod_poly_tree_build/ /tree/ /roots/ /len/ /mod/ +-- +-- Builds a subproduct tree in the preallocated space from the @len@ monic+-- linear factors \((x-r_i)\). The top level product is not computed.+foreign import ccall "nmod_poly.h _nmod_poly_tree_build"+ _nmod_poly_tree_build :: Ptr (Ptr CMp) -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- Inflation and deflation -----------------------------------------------------++-- | /nmod_poly_inflate/ /result/ /input/ /inflation/ +-- +-- Sets @result@ to the inflated polynomial \(p(x^n)\) where \(p\) is given+-- by @input@ and \(n\) is given by @deflation@.+foreign import ccall "nmod_poly.h nmod_poly_inflate"+ nmod_poly_inflate :: Ptr CNModPoly -> Ptr CNModPoly -> CULong -> IO ()++-- | /nmod_poly_deflate/ /result/ /input/ /deflation/ +-- +-- Sets @result@ to the deflated polynomial \(p(x^{1/n})\) where \(p\) is+-- given by @input@ and \(n\) is given by @deflation@. Requires \(n > 0\).+foreign import ccall "nmod_poly.h nmod_poly_deflate"+ nmod_poly_deflate :: Ptr CNModPoly -> Ptr CNModPoly -> CULong -> IO ()++-- | /nmod_poly_deflation/ /input/ +-- +-- Returns the largest integer by which @input@ can be deflated. As special+-- cases, returns 0 if @input@ is the zero polynomial and 1 of @input@ is a+-- constant polynomial.+foreign import ccall "nmod_poly.h nmod_poly_deflation"+ nmod_poly_deflation :: Ptr CNModPoly -> IO CULong++-- Chinese Remaindering --------------------------------------------------------+++++-- | /nmod_poly_multi_crt_init/ /CRT/ +-- +-- Initialize @CRT@ for Chinese remaindering.+foreign import ccall "nmod_poly.h nmod_poly_multi_crt_init"+ nmod_poly_multi_crt_init :: Ptr CNModPolyMultiCRT -> IO ()++-- | /nmod_poly_multi_crt_precompute/ /CRT/ /moduli/ /len/ +-- +-- Configure @CRT@ for repeated Chinese remaindering of @moduli@. The+-- number of moduli, @len@, should be positive. A return of @0@ indicates+-- that the compilation failed and future calls to+-- @nmod_poly_multi_crt_precomp@ will leave the output undefined. A return+-- of @1@ indicates that the compilation was successful, which occurs if+-- and only if either (1) @len == 1@ and @modulus + 0@ is nonzero, or (2)+-- all of the moduli have positive degree and are pairwise relatively+-- prime.+foreign import ccall "nmod_poly.h nmod_poly_multi_crt_precompute"+ nmod_poly_multi_crt_precompute :: Ptr CNModPolyMultiCRT -> Ptr (Ptr CNModPoly) -> CLong -> IO CInt++-- | /nmod_poly_multi_crt_precomp/ /output/ /CRT/ /values/ +-- +-- Set @output@ to the polynomial of lowest possible degree that is+-- congruent to @values + i@ modulo the @moduli + i@ in+-- @nmod_poly_multi_crt_precompute@. The inputs+-- @values + 0, ..., values + len - 1@ where @len@ was used in+-- @nmod_poly_multi_crt_precompute@ are expected to be valid and have+-- modulus matching the modulus of the moduli used in+-- @nmod_poly_multi_crt_precompute@.+foreign import ccall "nmod_poly.h nmod_poly_multi_crt_precomp"+ nmod_poly_multi_crt_precomp :: Ptr CNModPoly -> Ptr CNModPolyMultiCRT -> Ptr (Ptr CNModPoly) -> IO ()++-- | /nmod_poly_multi_crt/ /output/ /moduli/ /values/ /len/ +-- +-- Perform the same operation as @nmod_poly_multi_crt_precomp@ while+-- internally constructing and destroying the precomputed data. All of the+-- remarks in @nmod_poly_multi_crt_precompute@ apply.+foreign import ccall "nmod_poly.h nmod_poly_multi_crt"+ nmod_poly_multi_crt :: Ptr CNModPoly -> Ptr (Ptr CNModPoly) -> Ptr (Ptr CNModPoly) -> CLong -> IO CInt++-- | /nmod_poly_multi_crt_clear/ /CRT/ +-- +-- Free all space used by @CRT@.+foreign import ccall "nmod_poly.h nmod_poly_multi_crt_clear"+ nmod_poly_multi_crt_clear :: Ptr CNModPolyMultiCRT -> IO ()++-- | /_nmod_poly_multi_crt_local_size/ /CRT/ +-- +-- Return the required length of the output for @_nmod_poly_multi_crt_run@.+foreign import ccall "nmod_poly.h _nmod_poly_multi_crt_local_size"+ _nmod_poly_multi_crt_local_size :: Ptr CNModPolyMultiCRT -> IO CLong++-- | /_nmod_poly_multi_crt_run/ /outputs/ /CRT/ /inputs/ +-- +-- Perform the same operation as @nmod_poly_multi_crt_precomp@ using+-- supplied temporary space. The actual output is placed in @outputs + 0@,+-- and @outputs@ should contain space for all temporaries and should be at+-- least as long as @_nmod_poly_multi_crt_local_size(CRT)@. Of course the+-- moduli of these temporaries should match the modulus of the inputs.+foreign import ccall "nmod_poly.h _nmod_poly_multi_crt_run"+ _nmod_poly_multi_crt_run :: Ptr (Ptr CNModPoly) -> Ptr CNModPolyMultiCRT -> Ptr (Ptr CNModPoly) -> IO ()++-- Berlekamp-Massey Algorithm --------------------------------------------------++-- | /nmod_berlekamp_massey_init/ /B/ /p/ +-- +-- Initialize @B@ in characteristic @p@ with an empty stream.+foreign import ccall "nmod_poly.h nmod_berlekamp_massey_init"+ nmod_berlekamp_massey_init :: Ptr CNModBerlekampMassey -> CMpLimb -> IO ()++-- | /nmod_berlekamp_massey_clear/ /B/ +-- +-- Free any space used by @B@.+foreign import ccall "nmod_poly.h nmod_berlekamp_massey_clear"+ nmod_berlekamp_massey_clear :: Ptr CNModBerlekampMassey -> IO ()++foreign import ccall "nmod_poly.h &nmod_berlekamp_massey_clear"+ p_nmod_berlekamp_massey_clear :: FunPtr (Ptr CNModBerlekampMassey -> IO ())++-- | /nmod_berlekamp_massey_start_over/ /B/ +-- +-- Empty the stream of points in @B@.+foreign import ccall "nmod_poly.h nmod_berlekamp_massey_start_over"+ nmod_berlekamp_massey_start_over :: Ptr CNModBerlekampMassey -> IO ()++-- | /nmod_berlekamp_massey_set_prime/ /B/ /p/ +-- +-- Set the characteristic of the field and empty the stream of points in+-- @B@.+foreign import ccall "nmod_poly.h nmod_berlekamp_massey_set_prime"+ nmod_berlekamp_massey_set_prime :: Ptr CNModBerlekampMassey -> CMpLimb -> IO ()++-- | /nmod_berlekamp_massey_add_points/ /B/ /a/ /count/ +-- +-- Add point(s) to the stream processed by @B@. The addition of any number+-- of points will not update the \(V\) and \(R\) polynomial.+foreign import ccall "nmod_poly.h nmod_berlekamp_massey_add_points"+ nmod_berlekamp_massey_add_points :: Ptr CNModBerlekampMassey -> Ptr CMpLimb -> CLong -> IO ()++-- | /nmod_berlekamp_massey_reduce/ /B/ +-- +-- Ensure that the polynomials \(V\) and \(R\) are up to date. The return+-- value is @1@ if this function changed \(V\) and @0@ otherwise. For+-- example, if this function is called twice in a row without adding any+-- points in between, the return of the second call should be @0@. As+-- another example, suppose the object is emptied, the points+-- \(1, 1, 2, 3\) are added, then reduce is called. This reduce should+-- return @1@ with \(\deg(R) < \deg(V) = 2\) because the Fibonacci sequence+-- has been recognized. The further addition of the two points \(5, 8\) and+-- a reduce will result in a return value of @0@.+foreign import ccall "nmod_poly.h nmod_berlekamp_massey_reduce"+ nmod_berlekamp_massey_reduce :: Ptr CNModBerlekampMassey -> IO CInt++-- | /nmod_berlekamp_massey_point_count/ /B/ +-- +-- Return the number of points stored in @B@.+foreign import ccall "nmod_poly.h nmod_berlekamp_massey_point_count"+ nmod_berlekamp_massey_point_count :: Ptr CNModBerlekampMassey -> IO CLong++-- | /nmod_berlekamp_massey_points/ /B/ +-- +-- Return a pointer to the array of points stored in @B@. This may be+-- @NULL@ if @nmod_berlekamp_massey_point_count@ returns @0@.+foreign import ccall "nmod_poly.h nmod_berlekamp_massey_points"+ nmod_berlekamp_massey_points :: Ptr CNModBerlekampMassey -> IO (Ptr CMpLimb)++-- | /nmod_berlekamp_massey_V_poly/ /B/ +-- +-- Return the polynomial \(V\) in @B@.+foreign import ccall "nmod_poly.h nmod_berlekamp_massey_V_poly"+ nmod_berlekamp_massey_V_poly :: Ptr CNModBerlekampMassey -> IO (Ptr (Ptr CNModPoly))++-- | /nmod_berlekamp_massey_R_poly/ /B/ +-- +-- Return the polynomial \(R\) in @B@.+foreign import ccall "nmod_poly.h nmod_berlekamp_massey_R_poly"+ nmod_berlekamp_massey_R_poly :: Ptr CNModBerlekampMassey -> IO (Ptr (Ptr CNModPoly))+
+ src/Data/Number/Flint/NMod/Poly/Factor.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.NMod.Poly.Factor (+ module Data.Number.Flint.NMod.Poly.Factor.FFI+ ) where++import Data.Number.Flint.NMod.Poly.Factor.FFI
+ src/Data/Number/Flint/NMod/Poly/Factor/FFI.hsc view
@@ -0,0 +1,374 @@+{-|+module : Data.Number.Flint.NMod.Poly.Factor.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NMod.Poly.Factor.FFI (+ -- * Factorisation of univariate polynomials over integers mod n (word-size n)+ -- * Types+ NModPolyFactor (..)+ , CNModPolyFactor (..)+ , newNModPolyFactor+ , withNModPolyFactor+ , withNewNModPolyFactor+ -- * Memory management+ , nmod_poly_factor_init+ , nmod_poly_factor_clear+ , nmod_poly_factor_realloc+ , nmod_poly_factor_fit_length+ , nmod_poly_factor_set+ -- * Output+ , nmod_poly_factor_print+ , nmod_poly_factor_print_pretty+ , nmod_poly_factor_fprint+ , nmod_poly_factor_fprint_pretty+ , nmod_poly_factor_get_str+ , nmod_poly_factor_get_str_pretty+ -- * Basic manipulations+ , nmod_poly_factor_insert+ , nmod_poly_factor_concat+ , nmod_poly_factor_pow+ , nmod_poly_remove+ , nmod_poly_is_irreducible+ , nmod_poly_is_irreducible_ddf+ , nmod_poly_is_irreducible_rabin+ , _nmod_poly_is_squarefree+ , nmod_poly_is_squarefree+ -- * Factorizations+ , nmod_poly_factor_squarefree+ , nmod_poly_factor_equal_deg_prob+ , nmod_poly_factor_equal_deg+ , nmod_poly_factor_distinct_deg+ , nmod_poly_factor_distinct_deg_threaded+ , nmod_poly_factor_cantor_zassenhaus+ , nmod_poly_factor_berlekamp+ , nmod_poly_factor_kaltofen_shoup+ , nmod_poly_factor_with_berlekamp+ , nmod_poly_factor_with_cantor_zassenhaus+ , nmod_poly_factor_with_kaltofen_shoup+ , nmod_poly_factor+ , _nmod_poly_interval_poly_worker+) where++-- Factorisation of univariate polynomials over integers mod n (word-size n)++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.NMod+import Data.Number.Flint.NMod.Types+import Data.Number.Flint.ThreadPool++#include <flint/nmod_poly_factor.h>++-- Types -----------------------------------------------------------------------++-- | Create new `NModPolyFactor`+newNModPolyFactor = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> nmod_poly_factor_init x+ addForeignPtrFinalizer p_nmod_poly_factor_clear x+ return $ NModPolyFactor x++-- | Use `NModPolyFactor`+{-# INLINE withNModPolyFactor #-}+withNModPolyFactor (NModPolyFactor x) f = do+ withForeignPtr x $ \px -> f px >>= return . (NModPolyFactor x,)++-- | Use new `NModPolyFactor`+{-# INLINE withNewNModPolyFactor #-}+withNewNModPolyFactor f = do+ x <- newNModPolyFactor+ withNModPolyFactor x $ \x -> f x++-- Factorisation ---------------------------------------------------------------++-- | /nmod_poly_factor_init/ /fac/ +-- +-- Initialises @fac@ for use. An @nmod_poly_factor_t@ represents a+-- polynomial in factorised form as a product of polynomials with+-- associated exponents.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_init"+ nmod_poly_factor_init :: Ptr CNModPolyFactor -> IO ()++-- | /nmod_poly_factor_clear/ /fac/ +-- +-- Frees all memory associated with @fac@.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_clear"+ nmod_poly_factor_clear :: Ptr CNModPolyFactor -> IO ()++foreign import ccall "nmod_poly_factor.h &nmod_poly_factor_clear"+ p_nmod_poly_factor_clear :: FunPtr (Ptr CNModPolyFactor -> IO ())++-- | /nmod_poly_factor_realloc/ /fac/ /alloc/ +-- +-- Reallocates the factor structure to provide space for precisely @alloc@+-- factors.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_realloc"+ nmod_poly_factor_realloc :: Ptr CNModPolyFactor -> CLong -> IO ()++-- | /nmod_poly_factor_fit_length/ /fac/ /len/ +-- +-- Ensures that the factor structure has space for at least @len@ factors.+-- This function takes care of the case of repeated calls by always at+-- least doubling the number of factors the structure can hold.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_fit_length"+ nmod_poly_factor_fit_length :: Ptr CNModPolyFactor -> CLong -> IO ()++-- | /nmod_poly_factor_set/ /res/ /fac/ +-- +-- Sets @res@ to the same factorisation as @fac@.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_set"+ nmod_poly_factor_set :: Ptr CNModPolyFactor -> Ptr CNModPolyFactor -> IO ()++-- Input and output ------------------------------------------------------------++-- | /nmod_poly_factor_get_str/ /fac/+-- +-- Returns string representation of the entries of @fac@.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_get_str"+ nmod_poly_factor_get_str :: Ptr CNModPolyFactor -> IO CString++-- | /nmod_poly_factor_get_str_pretty/ /fac/ /x/+-- +-- Returns string representation of the entries of @fac@ as polynomials.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_get_str_pretty"+ nmod_poly_factor_get_str_pretty :: Ptr CNModPolyFactor -> CString -> IO CString++-- | /nmod_poly_factor_fprint/ /fac/ +-- +-- Prints the entries of @fac@ to stream.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_fprint"+ nmod_poly_factor_fprint :: Ptr CFile -> Ptr CNModPolyFactor -> IO ()++-- | /nmod_poly_factor_fprint_pretty/ /fac/ /x/+-- +-- Prints the entries of @fac@ to stream a polynomials.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_fprint_pretty"+ nmod_poly_factor_fprint_pretty :: Ptr CFile -> Ptr CNModPolyFactor -> CString -> IO ()++-- | /nmod_poly_factor_print/ /fac/ +-- +-- Prints the entries of @fac@ to standard output.+nmod_poly_factor_print :: Ptr CNModPolyFactor -> IO ()+nmod_poly_factor_print fac = do+ printCStr nmod_poly_factor_get_str fac+ return ()++-- | /nmod_poly_factor_print_pretty/ /fac/ /x/+-- +-- Prints the entries of @fac@ to standard output as polynomials.+nmod_poly_factor_print_pretty :: Ptr CNModPolyFactor -> CString -> IO ()+nmod_poly_factor_print_pretty fac x = do+ printCStr (\fac -> nmod_poly_factor_get_str_pretty fac x) fac+ return ()+ +--------------------------------------------------------------------------------++-- | /nmod_poly_factor_insert/ /fac/ /poly/ /exp/ +-- +-- Inserts the factor @poly@ with multiplicity @exp@ into the factorisation+-- @fac@.+-- +-- If @fac@ already contains @poly@, then @exp@ simply gets added to the+-- exponent of the existing entry.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_insert"+ nmod_poly_factor_insert :: Ptr CNModPolyFactor -> Ptr CNModPoly -> CLong -> IO ()++-- | /nmod_poly_factor_concat/ /res/ /fac/ +-- +-- Concatenates two factorisations.+-- +-- This is equivalent to calling @nmod_poly_factor_insert@ repeatedly with+-- the individual factors of @fac@.+-- +-- Does not support aliasing between @res@ and @fac@.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_concat"+ nmod_poly_factor_concat :: Ptr CNModPolyFactor -> Ptr CNModPolyFactor -> IO ()++-- | /nmod_poly_factor_pow/ /fac/ /exp/ +-- +-- Raises @fac@ to the power @exp@.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_pow"+ nmod_poly_factor_pow :: Ptr CNModPolyFactor -> CLong -> IO ()++-- | /nmod_poly_remove/ /f/ /p/ +-- +-- Removes the highest possible power of @p@ from @f@ and returns the+-- exponent.+foreign import ccall "nmod_poly_factor.h nmod_poly_remove"+ nmod_poly_remove :: Ptr CNModPoly -> Ptr CNModPoly -> IO CULong++-- | /nmod_poly_is_irreducible/ /f/ +-- +-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+foreign import ccall "nmod_poly_factor.h nmod_poly_is_irreducible"+ nmod_poly_is_irreducible :: Ptr CNModPoly -> IO CInt++-- | /nmod_poly_is_irreducible_ddf/ /f/ +-- +-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+-- Uses fast distinct-degree factorisation.+foreign import ccall "nmod_poly_factor.h nmod_poly_is_irreducible_ddf"+ nmod_poly_is_irreducible_ddf :: Ptr CNModPoly -> IO CInt++-- | /nmod_poly_is_irreducible_rabin/ /f/ +-- +-- Returns 1 if the polynomial @f@ is irreducible, otherwise returns 0.+-- Uses Rabin irreducibility test.+foreign import ccall "nmod_poly_factor.h nmod_poly_is_irreducible_rabin"+ nmod_poly_is_irreducible_rabin :: Ptr CNModPoly -> IO CInt++-- | /_nmod_poly_is_squarefree/ /f/ /len/ /mod/ +-- +-- Returns 1 if @(f, len)@ is squarefree, and 0 otherwise. As a special+-- case, the zero polynomial is not considered squarefree. There are no+-- restrictions on the length.+foreign import ccall "nmod_poly_factor.h _nmod_poly_is_squarefree"+ _nmod_poly_is_squarefree :: Ptr CMp -> CLong -> Ptr CNMod -> IO CInt++-- | /nmod_poly_is_squarefree/ /f/ +-- +-- Returns 1 if @f@ is squarefree, and 0 otherwise. As a special case, the+-- zero polynomial is not considered squarefree.+foreign import ccall "nmod_poly_factor.h nmod_poly_is_squarefree"+ nmod_poly_is_squarefree :: Ptr CNModPoly -> IO CInt++-- | /nmod_poly_factor_squarefree/ /res/ /f/ +-- +-- Sets @res@ to a square-free factorization of @f@.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_squarefree"+ nmod_poly_factor_squarefree :: Ptr CNModPolyFactor -> Ptr CNModPoly -> IO ()++-- | /nmod_poly_factor_equal_deg_prob/ /factor/ /state/ /pol/ /d/ +-- +-- Probabilistic equal degree factorisation of @pol@ into irreducible+-- factors of degree @d@. If it passes, a factor is placed in factor and 1+-- is returned, otherwise 0 is returned and the value of factor is+-- undetermined.+-- +-- Requires that @pol@ be monic, non-constant and squarefree.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_equal_deg_prob"+ nmod_poly_factor_equal_deg_prob :: Ptr CNModPoly -> Ptr CFRandState -> Ptr CNModPoly -> CLong -> IO CInt++-- | /nmod_poly_factor_equal_deg/ /factors/ /pol/ /d/ +-- +-- Assuming @pol@ is a product of irreducible factors all of degree @d@,+-- finds all those factors and places them in factors. Requires that @pol@+-- be monic, non-constant and squarefree.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_equal_deg"+ nmod_poly_factor_equal_deg :: Ptr CNModPolyFactor -> Ptr CNModPoly -> CLong -> IO ()++-- | /nmod_poly_factor_distinct_deg/ /res/ /poly/ /degs/ +-- +-- Factorises a monic non-constant squarefree polynomial @poly@ of degree n+-- into factors \(f[d]\) such that for \(1 \leq d \leq n\) \(f[d]\) is the+-- product of the monic irreducible factors of @poly@ of degree \(d\).+-- Factors \(f[d]\) are stored in @res@, and the degree \(d\) of the+-- irreducible factors is stored in @degs@ in the same order as the+-- factors.+-- +-- Requires that @degs@ has enough space for @(n\/2)+1 * sizeof(slong)@.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_distinct_deg"+ nmod_poly_factor_distinct_deg :: Ptr CNModPolyFactor -> Ptr CNModPoly -> Ptr (Ptr CLong) -> IO ()++-- | /nmod_poly_factor_distinct_deg_threaded/ /res/ /poly/ /degs/ +-- +-- Multithreaded version of @nmod_poly_factor_distinct_deg@.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_distinct_deg_threaded"+ nmod_poly_factor_distinct_deg_threaded :: Ptr CNModPolyFactor -> Ptr CNModPoly -> Ptr (Ptr CLong) -> IO ()++-- | /nmod_poly_factor_cantor_zassenhaus/ /res/ /f/ +-- +-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the Cantor-Zassenhaus algorithm.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_cantor_zassenhaus"+ nmod_poly_factor_cantor_zassenhaus :: Ptr CNModPolyFactor -> Ptr CNModPoly -> IO ()++-- | /nmod_poly_factor_berlekamp/ /res/ /f/ +-- +-- Factorises a non-constant, squarefree polynomial @f@ into monic+-- irreducible factors using the Berlekamp algorithm.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_berlekamp"+ nmod_poly_factor_berlekamp :: Ptr CNModPolyFactor -> Ptr CNModPoly -> IO ()++-- | /nmod_poly_factor_kaltofen_shoup/ /res/ /poly/ +-- +-- Factorises a non-constant polynomial @f@ into monic irreducible factors+-- using the fast version of Cantor-Zassenhaus algorithm proposed by+-- Kaltofen and Shoup (1998). More precisely this algorithm uses a “baby+-- step\/giant step” strategy for the distinct-degree factorization step.+-- If @flint_get_num_threads@ is greater than one+-- @nmod_poly_factor_distinct_deg_threaded@ is used.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_kaltofen_shoup"+ nmod_poly_factor_kaltofen_shoup :: Ptr CNModPolyFactor -> Ptr CNModPoly -> IO ()++-- | /nmod_poly_factor_with_berlekamp/ /res/ /f/ +-- +-- Factorises a general polynomial @f@ into monic irreducible factors and+-- returns the leading coefficient of @f@, or 0 if @f@ is the zero+-- polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Berlekamp on all the+-- individual square-free factors.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_with_berlekamp"+ nmod_poly_factor_with_berlekamp :: Ptr CNModPolyFactor -> Ptr CNModPoly -> IO CMpLimb++-- | /nmod_poly_factor_with_cantor_zassenhaus/ /res/ /f/ +-- +-- Factorises a general polynomial @f@ into monic irreducible factors and+-- returns the leading coefficient of @f@, or 0 if @f@ is the zero+-- polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Cantor-Zassenhaus on all the+-- individual square-free factors.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_with_cantor_zassenhaus"+ nmod_poly_factor_with_cantor_zassenhaus :: Ptr CNModPolyFactor -> Ptr CNModPoly -> IO CMpLimb++-- | /nmod_poly_factor_with_kaltofen_shoup/ /res/ /f/ +-- +-- Factorises a general polynomial @f@ into monic irreducible factors and+-- returns the leading coefficient of @f@, or 0 if @f@ is the zero+-- polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs Kaltofen-Shoup on all the+-- individual square-free factors.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor_with_kaltofen_shoup"+ nmod_poly_factor_with_kaltofen_shoup :: Ptr CNModPolyFactor -> Ptr CNModPoly -> IO CMpLimb++-- | /nmod_poly_factor/ /res/ /f/ +-- +-- Factorises a general polynomial @f@ into monic irreducible factors and+-- returns the leading coefficient of @f@, or 0 if @f@ is the zero+-- polynomial.+-- +-- This function first checks for small special cases, deflates @f@ if it+-- is of the form \(p(x^m)\) for some \(m > 1\), then performs a+-- square-free factorisation, and finally runs either Cantor-Zassenhaus or+-- Berlekamp on all the individual square-free factors. Currently+-- Cantor-Zassenhaus is used by default unless the modulus is 2, in which+-- case Berlekamp is used.+foreign import ccall "nmod_poly_factor.h nmod_poly_factor"+ nmod_poly_factor :: Ptr CNModPolyFactor -> Ptr CNModPoly -> IO CMpLimb++-- | /_nmod_poly_interval_poly_worker/ /arg_ptr/ +-- +-- Worker function to compute interval polynomials in distinct degree+-- factorisation. Input\/output is stored in+-- @nmod_poly_interval_poly_arg_t@.+foreign import ccall "nmod_poly_factor.h _nmod_poly_interval_poly_worker"+ _nmod_poly_interval_poly_worker :: Ptr () -> IO ()+
+ src/Data/Number/Flint/NMod/Poly/Instances.hs view
@@ -0,0 +1,120 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.NMod.Poly.Instances (+ NModPoly (..)+ , module GHC.Exts+) where++import Test.QuickCheck++import GHC.Exts++import System.IO.Unsafe+import Control.Monad++import Foreign.Ptr+import Foreign.C.String+import Foreign.Storable+import Foreign.Marshal.Alloc (free)+import Foreign.Marshal.Array (advancePtr)++import Data.Number.Flint.NMod.Poly+import Data.Number.Flint.NMod.Poly.Factor++import Data.Number.Flint.UFD++instance Show NModPoly where+ show p = snd $ unsafePerformIO $ do+ withNModPoly p $ \p -> do+ withCString "x" $ \x -> do+ cs <- nmod_poly_get_str_pretty p x+ s <- peekCString cs+ free cs+ return s++instance Num NModPoly where+ (*) = lift2 nmod_poly_mul+ (+) = lift2 nmod_poly_add+ (-) = lift2 nmod_poly_sub+ abs = undefined+ signum = undefined+ fromInteger = undefined+ +instance Semigroup NModPoly where+ (<>) = lift2 nmod_poly_compose++instance Eq NModPoly where+ (==) x y = snd $ snd $ unsafePerformIO $ do+ withNModPoly x $ \x ->+ withNModPoly y $ \y -> do+ f <- nmod_poly_equal x y+ return $ f == 1++instance Ord NModPoly where+ compare = undefined+ +instance Real NModPoly where+ toRational = undefined++instance Enum NModPoly where+ toEnum = undefined+ fromEnum = undefined+ +instance Integral NModPoly where+ toInteger = undefined+ div x y = unsafePerformIO $ do+ (_, n) <- withNModPoly x nmod_poly_modulus+ (_, m) <- withNModPoly y nmod_poly_modulus+ when (n /= m) $ error "modulus does not agree."+ p <- newNModPoly n+ q <- newNModPoly n+ withNModPoly x $ \x ->+ withNModPoly y $ \y ->+ withNModPoly q $ \q ->+ nmod_poly_div q x y+ return q+ quotRem x y = unsafePerformIO $ do+ (_, n) <- withNModPoly x nmod_poly_modulus+ (_, m) <- withNModPoly y nmod_poly_modulus+ when (n /= m) $ error "modulus does not agree."+ p <- newNModPoly n + q <- newNModPoly n+ withNModPoly x $ \x ->+ withNModPoly y $ \y ->+ withNModPoly p $ \p ->+ withNModPoly q $ \q ->+ nmod_poly_divrem p q x y+ return (p, q)++instance UFD NModPoly where+ factor x = snd $ snd $ unsafePerformIO $ do+ withNModPoly x $ \x -> do+ m <- nmod_poly_modulus x+ f <- newNModPolyFactor+ withNModPolyFactor f $ \f -> do+ nmod_poly_factor f x+ (CNModPolyFactor d e n alloc) <- peek f+ forM [0..fromIntegral n-1] $ \j -> do+ m <- peek (e `advancePtr` j)+ r <- newNModPoly (fromIntegral m)+ withNModPoly r $ \r -> nmod_poly_set r (d `advancePtr` j)+ return (r, fromIntegral m)++lift2 f x y = unsafePerformIO $ do+ (_, n) <- withNModPoly x nmod_poly_modulus+ (_, m) <- withNModPoly y nmod_poly_modulus+ when (n /= m) $ error "modulus does not agree."+ result <- newNModPoly n+ withNModPoly result $ \result -> do+ withNModPoly x $ \x -> do+ withNModPoly y $ \y -> do+ f result x y+ return result++lift1 f x = unsafePerformIO $ do+ (_, n) <- withNModPoly x nmod_poly_modulus+ result <- newNModPoly n+ withNModPoly result $ \result ->+ withNModPoly x $ \x ->+ f result x+ return result+
+ src/Data/Number/Flint/NMod/Poly/Mat.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.NMod.Poly.Mat (+ module Data.Number.Flint.NMod.Poly.Mat.FFI+ ) where++import Data.Number.Flint.NMod.Poly.Mat.FFI
+ src/Data/Number/Flint/NMod/Poly/Mat/FFI.hsc view
@@ -0,0 +1,589 @@+{-|+module : Data.Number.Flint.NMod.Poly.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NMod.Poly.Mat.FFI (+ -- * Matrices of univariate polynomials over integers mod n (word-size n)+ NModPolyMat (..)+ , CNModPolyMat (..)+ , newNModPolyMat+ , withNModPolyMat+ -- * Memory management+ , nmod_poly_mat_init+ , nmod_poly_mat_init_set+ , nmod_poly_mat_clear+ -- * Basic properties+ , nmod_poly_mat_nrows+ , nmod_poly_mat_ncols+ , nmod_poly_mat_modulus+ -- * Basic assignment and manipulation+ , nmod_poly_mat_entry+ , nmod_poly_mat_set+ , nmod_poly_mat_swap+ , nmod_poly_mat_swap_entrywise+ -- * Input and output+ , nmod_poly_mat_print+ -- * Random matrix generation+ , nmod_poly_mat_randtest+ , nmod_poly_mat_randtest_sparse+ -- * Special matrices+ , nmod_poly_mat_zero+ , nmod_poly_mat_one+ -- * Basic comparison and properties+ , nmod_poly_mat_equal+ , nmod_poly_mat_is_zero+ , nmod_poly_mat_is_one+ , nmod_poly_mat_is_empty+ , nmod_poly_mat_is_square+ -- * Norms+ , nmod_poly_mat_max_length+ -- * Evaluation+ , nmod_poly_mat_evaluate_nmod+ -- * Arithmetic+ , nmod_poly_mat_scalar_mul_nmod_poly+ , nmod_poly_mat_scalar_mul_nmod+ , nmod_poly_mat_add+ , nmod_poly_mat_sub+ , nmod_poly_mat_neg+ , nmod_poly_mat_mul+ , nmod_poly_mat_mul_classical+ , nmod_poly_mat_mul_KS+ , nmod_poly_mat_mul_interpolate+ , nmod_poly_mat_sqr+ , nmod_poly_mat_sqr_classical+ , nmod_poly_mat_sqr_KS+ , nmod_poly_mat_sqr_interpolate+ , nmod_poly_mat_pow+ -- * Row reduction+ , nmod_poly_mat_find_pivot_any+ , nmod_poly_mat_find_pivot_partial+ , nmod_poly_mat_fflu+ , nmod_poly_mat_rref+ -- * Trace+ , nmod_poly_mat_trace+ -- * Determinant and rank+ , nmod_poly_mat_det+ , nmod_poly_mat_det_fflu+ , nmod_poly_mat_det_interpolate+ , nmod_poly_mat_rank+ -- * Inverse+ , nmod_poly_mat_inv+ -- * Nullspace+ , nmod_poly_mat_nullspace+ -- * Solving+ , nmod_poly_mat_solve+ , nmod_poly_mat_solve_fflu+ , nmod_poly_mat_solve_fflu_precomp+) where ++-- Matrices of univariate polynomials over integers mod n (word-size n) --------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array ( advancePtr)++import Data.Number.Flint.Flint+import Data.Number.Flint.ThreadPool++import Data.Number.Flint.Fmpz+import Data.Number.Flint.NMod+import Data.Number.Flint.NMod.Vec+import Data.Number.Flint.NMod.Types++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/nmod_vec.h>+#include <flint/nmod_mat.h>+#include <flint/nmod_poly.h>+#include <flint/nmod_poly_mat.h>++-- nmod_mat_t -----------------------------------------------------------------++newNModPolyMat rows cols n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> nmod_poly_mat_init x rows cols n+ addForeignPtrFinalizer p_nmod_poly_mat_clear x+ return $ NModPolyMat x++{-# INLINE withNModPolyMat #-}+withNModPolyMat (NModPolyMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (NModPolyMat x,)++-- Memory management -----------------------------------------------------------++-- | /nmod_poly_mat_init/ /mat/ /rows/ /cols/ /n/ +--+-- Initialises a matrix with the given number of rows and columns for use.+-- The modulus is set to \(n\).+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_init"+ nmod_poly_mat_init :: Ptr CNModPolyMat -> CLong -> CLong -> CMpLimb -> IO ()++-- | /nmod_poly_mat_init_set/ /mat/ /src/ +--+-- Initialises a matrix @mat@ of the same dimensions and modulus as @src@,+-- and sets it to a copy of @src@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_init_set"+ nmod_poly_mat_init_set :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_clear/ /mat/ +--+-- Frees all memory associated with the matrix. The matrix must be+-- reinitialised if it is to be used again.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_clear"+ nmod_poly_mat_clear :: Ptr CNModPolyMat -> IO ()++foreign import ccall "nmod_poly_mat.h &nmod_poly_mat_clear"+ p_nmod_poly_mat_clear :: FunPtr (Ptr CNModPolyMat -> IO ())++-- Basic properties ------------------------------------------------------------++-- | /nmod_poly_mat_nrows/ /mat/ +--+-- Returns the number of rows in @mat@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_nrows"+ nmod_poly_mat_nrows :: Ptr CNModPolyMat -> IO CLong++-- | /nmod_poly_mat_ncols/ /mat/ +--+-- Returns the number of columns in @mat@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_ncols"+ nmod_poly_mat_ncols :: Ptr CNModPolyMat -> IO CLong++-- | /nmod_poly_mat_modulus/ /mat/ +--+-- Returns the modulus of @mat@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_modulus"+ nmod_poly_mat_modulus :: Ptr CNModPolyMat -> IO CMpLimb++-- Basic assignment and manipulation -------------------------------------------++-- | /nmod_poly_mat_entry/ /mat/ /i/ /j/ +--+-- Gives a reference to the entry at row @i@ and column @j@. The reference+-- can be passed as an input or output variable to any @nmod_poly@ function+-- for direct manipulation of the matrix element. No bounds checking is+-- performed.+nmod_poly_mat_entry :: Ptr CNModPolyMat -> CLong -> CLong -> IO (Ptr CNModPoly)+nmod_poly_mat_entry mat i j = do+ CNModPolyMat entries r c rows mod <- peek mat+ return $ entries `advancePtr` (fromIntegral (i*c + j))+++-- | /nmod_poly_mat_set/ /mat1/ /mat2/ +--+-- Sets @mat1@ to a copy of @mat2@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_set"+ nmod_poly_mat_set :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_swap/ /mat1/ /mat2/ +--+-- Swaps @mat1@ and @mat2@ efficiently.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_swap"+ nmod_poly_mat_swap :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_swap_entrywise/ /mat1/ /mat2/ +--+-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_swap_entrywise"+ nmod_poly_mat_swap_entrywise :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- Input and output ------------------------------------------------------------++foreign import ccall "nmod_poly_mat.h nmod_poly_mat_get_str"+ nmod_poly_mat_get_str :: Ptr CNModPolyMat -> CString -> IO CString++foreign import ccall "nmod_poly_mat.h nmod_poly_mat_fprint"+ nmod_poly_mat_fprint :: Ptr CFile -> Ptr CNModPolyMat -> CString -> IO ()++-- | /nmod_poly_mat_print/ /mat/ /x/ +--+-- Prints the matrix @mat@ to standard output, using the variable @x@.+nmod_poly_mat_print :: Ptr CNModPolyMat -> CString -> IO ()+nmod_poly_mat_print mat x = do+ printCStr (\mat -> nmod_poly_mat_get_str mat x) mat+ return ()++-- Random matrix generation ----------------------------------------------------++-- | /nmod_poly_mat_randtest/ /mat/ /state/ /len/ +--+-- This is equivalent to applying @nmod_poly_randtest@ to all entries in+-- the matrix.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_randtest"+ nmod_poly_mat_randtest :: Ptr CNModPolyMat -> Ptr CFRandState -> CLong -> IO ()++-- | /nmod_poly_mat_randtest_sparse/ /A/ /state/ /len/ /density/ +--+-- Creates a random matrix with the amount of nonzero entries given+-- approximately by the @density@ variable, which should be a fraction+-- between 0 (most sparse) and 1 (most dense).+-- +-- The nonzero entries will have random lengths between 1 and @len@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_randtest_sparse"+ nmod_poly_mat_randtest_sparse :: Ptr CNModPolyMat -> Ptr CFRandState -> CLong -> CFloat -> IO ()++-- Special matrices ------------------------------------------------------------++-- | /nmod_poly_mat_zero/ /mat/ +--+-- Sets @mat@ to the zero matrix.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_zero"+ nmod_poly_mat_zero :: Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_one/ /mat/ +--+-- Sets @mat@ to the unit or identity matrix of given shape, having the+-- element 1 on the main diagonal and zeros elsewhere. If @mat@ is+-- nonsquare, it is set to the truncation of a unit matrix.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_one"+ nmod_poly_mat_one :: Ptr CNModPolyMat -> IO ()++-- Basic comparison and properties ---------------------------------------------++-- | /nmod_poly_mat_equal/ /mat1/ /mat2/ +--+-- Returns nonzero if @mat1@ and @mat2@ have the same shape and all their+-- entries agree, and returns zero otherwise.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_equal"+ nmod_poly_mat_equal :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO CInt++-- | /nmod_poly_mat_is_zero/ /mat/ +--+-- Returns nonzero if all entries in @mat@ are zero, and returns zero+-- otherwise.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_is_zero"+ nmod_poly_mat_is_zero :: Ptr CNModPolyMat -> IO CInt++-- | /nmod_poly_mat_is_one/ /mat/ +--+-- Returns nonzero if all entry of @mat@ on the main diagonal are the+-- constant polynomial 1 and all remaining entries are zero, and returns+-- zero otherwise. The matrix need not be square.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_is_one"+ nmod_poly_mat_is_one :: Ptr CNModPolyMat -> IO CInt++-- | /nmod_poly_mat_is_empty/ /mat/ +--+-- Returns a non-zero value if the number of rows or the number of columns+-- in @mat@ is zero, and otherwise returns zero.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_is_empty"+ nmod_poly_mat_is_empty :: Ptr CNModPolyMat -> IO CInt++-- | /nmod_poly_mat_is_square/ /mat/ +--+-- Returns a non-zero value if the number of rows is equal to the number of+-- columns in @mat@, and otherwise returns zero.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_is_square"+ nmod_poly_mat_is_square :: Ptr CNModPolyMat -> IO CInt++-- Norms -----------------------------------------------------------------------++-- | /nmod_poly_mat_max_length/ /A/ +--+-- Returns the maximum polynomial length among all the entries in @A@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_max_length"+ nmod_poly_mat_max_length :: Ptr CNModPolyMat -> IO CLong++-- Evaluation ------------------------------------------------------------------++-- | /nmod_poly_mat_evaluate_nmod/ /B/ /A/ /x/ +--+-- Sets the @nmod_mat_t@ @B@ to @A@ evaluated entrywise at the point @x@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_evaluate_nmod"+ nmod_poly_mat_evaluate_nmod :: Ptr CNModMat -> Ptr CNModPolyMat -> CMpLimb -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- | /nmod_poly_mat_scalar_mul_nmod_poly/ /B/ /A/ /c/ +--+-- Sets @B@ to @A@ multiplied entrywise by the polynomial @c@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_scalar_mul_nmod_poly"+ nmod_poly_mat_scalar_mul_nmod_poly :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> Ptr CNModPoly -> IO ()++-- | /nmod_poly_mat_scalar_mul_nmod/ /B/ /A/ /c/ +--+-- Sets @B@ to @A@ multiplied entrywise by the coefficient @c@, which is+-- assumed to be reduced modulo the modulus.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_scalar_mul_nmod"+ nmod_poly_mat_scalar_mul_nmod :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> CMpLimb -> IO ()++-- | /nmod_poly_mat_add/ /C/ /A/ /B/ +--+-- Sets @C@ to the sum of @A@ and @B@. All matrices must have the same+-- shape. Aliasing is allowed.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_add"+ nmod_poly_mat_add :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_sub/ /C/ /A/ /B/ +--+-- Sets @C@ to the sum of @A@ and @B@. All matrices must have the same+-- shape. Aliasing is allowed.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_sub"+ nmod_poly_mat_sub :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_neg/ /B/ /A/ +--+-- Sets @B@ to the negation of @A@. The matrices must have the same shape.+-- Aliasing is allowed.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_neg"+ nmod_poly_mat_neg :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_mul/ /C/ /A/ /B/ +--+-- Sets @C@ to the matrix product of @A@ and @B@. The matrices must have+-- compatible dimensions for matrix multiplication. Aliasing is allowed.+-- This function automatically chooses between classical, KS and+-- evaluation-interpolation multiplication.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_mul"+ nmod_poly_mat_mul :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_mul_classical/ /C/ /A/ /B/ +--+-- Sets @C@ to the matrix product of @A@ and @B@, computed using the+-- classical algorithm. The matrices must have compatible dimensions for+-- matrix multiplication. Aliasing is allowed.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_mul_classical"+ nmod_poly_mat_mul_classical :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_mul_KS/ /C/ /A/ /B/ +--+-- Sets @C@ to the matrix product of @A@ and @B@, computed using Kronecker+-- segmentation. The matrices must have compatible dimensions for matrix+-- multiplication. Aliasing is allowed.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_mul_KS"+ nmod_poly_mat_mul_KS :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_mul_interpolate/ /C/ /A/ /B/ +--+-- Sets @C@ to the matrix product of @A@ and @B@, computed through+-- evaluation and interpolation. The matrices must have compatible+-- dimensions for matrix multiplication. For interpolation to be+-- well-defined, we require that the modulus is a prime at least as large+-- as \(m + n - 1\) where \(m\) and \(n\) are the maximum lengths of+-- polynomials in the input matrices. Aliasing is allowed.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_mul_interpolate"+ nmod_poly_mat_mul_interpolate :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_sqr/ /B/ /A/ +--+-- Sets @B@ to the square of @A@, which must be a square matrix. Aliasing+-- is allowed. This function automatically chooses between classical and KS+-- squaring.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_sqr"+ nmod_poly_mat_sqr :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_sqr_classical/ /B/ /A/ +--+-- Sets @B@ to the square of @A@, which must be a square matrix. Aliasing+-- is allowed. This function uses direct formulas for very small matrices,+-- and otherwise classical matrix multiplication.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_sqr_classical"+ nmod_poly_mat_sqr_classical :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_sqr_KS/ /B/ /A/ +--+-- Sets @B@ to the square of @A@, which must be a square matrix. Aliasing+-- is allowed. This function uses Kronecker segmentation.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_sqr_KS"+ nmod_poly_mat_sqr_KS :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_sqr_interpolate/ /B/ /A/ +--+-- Sets @B@ to the square of @A@, which must be a square matrix, computed+-- through evaluation and interpolation. For interpolation to be+-- well-defined, we require that the modulus is a prime at least as large+-- as \(2n - 1\) where \(n\) is the maximum length of polynomials in the+-- input matrix. Aliasing is allowed.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_sqr_interpolate"+ nmod_poly_mat_sqr_interpolate :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_pow/ /B/ /A/ /exp/ +--+-- Sets @B@ to @A@ raised to the power @exp@, where @A@ is a square matrix.+-- Uses exponentiation by squaring. Aliasing is allowed.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_pow"+ nmod_poly_mat_pow :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> CULong -> IO ()++-- Row reduction ---------------------------------------------------------------++-- | /nmod_poly_mat_find_pivot_any/ /mat/ /start_row/ /end_row/ /c/ +--+-- Attempts to find a pivot entry for row reduction. Returns a row index+-- \(r\) between @start_row@ (inclusive) and @stop_row@ (exclusive) such+-- that column \(c\) in @mat@ has a nonzero entry on row \(r\), or returns+-- -1 if no such entry exists.+-- +-- This implementation simply chooses the first nonzero entry from it+-- encounters. This is likely to be a nearly optimal choice if all entries+-- in the matrix have roughly the same size, but can lead to unnecessary+-- coefficient growth if the entries vary in size.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_find_pivot_any"+ nmod_poly_mat_find_pivot_any :: Ptr CNModPolyMat -> CLong -> CLong -> CLong -> IO CLong++-- | /nmod_poly_mat_find_pivot_partial/ /mat/ /start_row/ /end_row/ /c/ +--+-- Attempts to find a pivot entry for row reduction. Returns a row index+-- \(r\) between @start_row@ (inclusive) and @stop_row@ (exclusive) such+-- that column \(c\) in @mat@ has a nonzero entry on row \(r\), or returns+-- -1 if no such entry exists.+-- +-- This implementation searches all the rows in the column and chooses the+-- nonzero entry of smallest degree. This heuristic typically reduces+-- coefficient growth when the matrix entries vary in size.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_find_pivot_partial"+ nmod_poly_mat_find_pivot_partial :: Ptr CNModPolyMat -> CLong -> CLong -> CLong -> IO CLong++-- | /nmod_poly_mat_fflu/ /B/ /den/ /perm/ /A/ /rank_check/ +--+-- Uses fraction-free Gaussian elimination to set (@B@, @den@) to a+-- fraction-free LU decomposition of @A@ and returns the rank of @A@.+-- Aliasing of @A@ and @B@ is allowed.+-- +-- Pivot elements are chosen with @nmod_poly_mat_find_pivot_partial@. If+-- @perm@ is non-@NULL@, the permutation of rows in the matrix will also be+-- applied to @perm@.+-- +-- If @rank_check@ is set, the function aborts and returns 0 if the matrix+-- is detected not to have full rank without completing the elimination.+-- +-- The denominator @den@ is set to \(\pm \operatorname{det}(A)\), where the+-- sign is decided by the parity of the permutation. Note that the+-- determinant is not generally the minimal denominator.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_fflu"+ nmod_poly_mat_fflu :: Ptr CNModPolyMat -> Ptr CNModPoly -> Ptr CLong -> Ptr CNModPolyMat -> CInt -> IO CLong++-- | /nmod_poly_mat_rref/ /B/ /den/ /A/ +--+-- Sets (@B@, @den@) to the reduced row echelon form of @A@ and returns the+-- rank of @A@. Aliasing of @A@ and @B@ is allowed.+-- +-- The denominator @den@ is set to \(\pm \operatorname{det}(A)\). Note that+-- the determinant is not generally the minimal denominator.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_rref"+ nmod_poly_mat_rref :: Ptr CNModPolyMat -> Ptr CNModPoly -> Ptr CNModPolyMat -> IO CLong++-- Trace -----------------------------------------------------------------------++-- | /nmod_poly_mat_trace/ /trace/ /mat/ +--+-- Computes the trace of the matrix, i.e. the sum of the entries on the+-- main diagonal. The matrix is required to be square.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_trace"+ nmod_poly_mat_trace :: Ptr CNModPoly -> Ptr CNModPolyMat -> IO ()++-- Determinant and rank --------------------------------------------------------++-- | /nmod_poly_mat_det/ /det/ /A/ +--+-- Sets @det@ to the determinant of the square matrix @A@. Uses a direct+-- formula, fraction-free LU decomposition, or interpolation, depending on+-- the size of the matrix.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_det"+ nmod_poly_mat_det :: Ptr CNModPoly -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_det_fflu/ /det/ /A/ +--+-- Sets @det@ to the determinant of the square matrix @A@. The determinant+-- is computed by performing a fraction-free LU decomposition on a copy of+-- @A@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_det_fflu"+ nmod_poly_mat_det_fflu :: Ptr CNModPoly -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_det_interpolate/ /det/ /A/ +--+-- Sets @det@ to the determinant of the square matrix @A@. The determinant+-- is computed by determining a bound \(n\) for its length, evaluating the+-- matrix at \(n\) distinct points, computing the determinant of each+-- coefficient matrix, and forming the interpolating polynomial.+-- +-- If the coefficient ring does not contain \(n\) distinct points (that is,+-- if working over \(\mathbf{Z}/p\mathbf{Z}\) where \(p < n\)), this+-- function automatically falls back to @nmod_poly_mat_det_fflu@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_det_interpolate"+ nmod_poly_mat_det_interpolate :: Ptr CNModPoly -> Ptr CNModPolyMat -> IO ()++-- | /nmod_poly_mat_rank/ /A/ +--+-- Returns the rank of @A@. Performs fraction-free LU decomposition on a+-- copy of @A@.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_rank"+ nmod_poly_mat_rank :: Ptr CNModPolyMat -> IO CLong++-- Inverse ---------------------------------------------------------------------++-- | /nmod_poly_mat_inv/ /Ainv/ /den/ /A/ +--+-- Sets (@Ainv@, @den@) to the inverse matrix of @A@. Returns 1 if @A@ is+-- nonsingular and 0 if @A@ is singular. Aliasing of @Ainv@ and @A@ is+-- allowed.+-- +-- More precisely, @det@ will be set to the determinant of @A@ and @Ainv@+-- will be set to the adjugate matrix of @A@. Note that the determinant is+-- not necessarily the minimal denominator.+-- +-- Uses fraction-free LU decomposition, followed by solving for the+-- identity matrix.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_inv"+ nmod_poly_mat_inv :: Ptr CNModPolyMat -> Ptr CNModPoly -> Ptr CNModPolyMat -> IO CInt++-- Nullspace -------------------------------------------------------------------++-- | /nmod_poly_mat_nullspace/ /res/ /mat/ +--+-- Computes the right rational nullspace of the matrix @mat@ and returns+-- the nullity.+-- +-- More precisely, assume that @mat@ has rank \(r\) and nullity \(n\). Then+-- this function sets the first \(n\) columns of @res@ to linearly+-- independent vectors spanning the nullspace of @mat@. As a result, we+-- always have rank(@res@) \(= n\), and @mat@ \(\times\) @res@ is the zero+-- matrix.+-- +-- The computed basis vectors will not generally be in a reduced form. In+-- general, the polynomials in each column vector in the result will have a+-- nontrivial common GCD.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_nullspace"+ nmod_poly_mat_nullspace :: Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO CLong++-- Solving ---------------------------------------------------------------------++-- | /nmod_poly_mat_solve/ /X/ /den/ /A/ /B/ +--+-- Solves the equation \(AX = B\) for nonsingular \(A\). More precisely,+-- computes (@X@, @den@) such that \(AX = B \times \operatorname{den}\).+-- Returns 1 if \(A\) is nonsingular and 0 if \(A\) is singular. The+-- computed denominator will not generally be minimal.+-- +-- Uses fraction-free LU decomposition followed by fraction-free forward+-- and back substitution.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_solve"+ nmod_poly_mat_solve :: Ptr CNModPolyMat -> Ptr CNModPoly -> Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO CInt++-- | /nmod_poly_mat_solve_fflu/ /X/ /den/ /A/ /B/ +--+-- Solves the equation \(AX = B\) for nonsingular \(A\). More precisely,+-- computes (@X@, @den@) such that \(AX = B \times \operatorname{den}\).+-- Returns 1 if \(A\) is nonsingular and 0 if \(A\) is singular. The+-- computed denominator will not generally be minimal.+-- +-- Uses fraction-free LU decomposition followed by fraction-free forward+-- and back substitution.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_solve_fflu"+ nmod_poly_mat_solve_fflu :: Ptr CNModPolyMat -> Ptr CNModPoly -> Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO CInt++-- | /nmod_poly_mat_solve_fflu_precomp/ /X/ /perm/ /FFLU/ /B/ +--+-- Performs fraction-free forward and back substitution given a precomputed+-- fraction-free LU decomposition and corresponding permutation.+foreign import ccall "nmod_poly_mat.h nmod_poly_mat_solve_fflu_precomp"+ nmod_poly_mat_solve_fflu_precomp :: Ptr CNModPolyMat -> Ptr CLong -> Ptr CNModPolyMat -> Ptr CNModPolyMat -> IO ()+
+ src/Data/Number/Flint/NMod/Types.hs view
@@ -0,0 +1,7 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}++module Data.Number.Flint.NMod.Types (+ module Data.Number.Flint.NMod.Types.FFI+ ) where++import Data.Number.Flint.NMod.Types.FFI
+ src/Data/Number/Flint/NMod/Types/FFI.hsc view
@@ -0,0 +1,86 @@+{-|+module : Data.Number.Flint.NMod.Types.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NMod.Types.FFI where++import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr+import Foreign.Storable++import Data.Number.Flint.Flint+import Data.Number.Flint.Flint.Internal+import Data.Number.Flint.NMod++#include <flint/nmod_types.h>++-- nmod_poly_t -----------------------------------------------------------------++data NModPoly = NModPoly {-# UNPACK #-} !(ForeignPtr CNModPoly)+type CNModPoly = CFlint NModPoly++instance Storable CNModPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_poly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_poly_t}+ peek = undefined+ poke = undefined++-- nmod_poly_factor_t ----------------------------------------------------------++data NModPolyFactor = NModPolyFactor {-# UNPACK #-}+ !(ForeignPtr CNModPolyFactor)+data CNModPolyFactor = CNModPolyFactor (Ptr CNModPoly) (Ptr CLong) CLong CLong++instance Storable CNModPolyFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_poly_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_poly_factor_t}+ peek ptr = do+ p <- #{peek nmod_poly_factor_struct, p } ptr+ exp <- #{peek nmod_poly_factor_struct, exp } ptr+ num <- #{peek nmod_poly_factor_struct, num } ptr+ alloc <- #{peek nmod_poly_factor_struct, alloc} ptr+ return $ CNModPolyFactor p exp num alloc+ poke = undefined++-- nmod_mat_t ------------------------------------------------------------------++data NModMat = NModMat {-# UNPACK #-} !(ForeignPtr CNModMat)+data CNModMat = CNModMat (Ptr CMpLimb) CLong CLong (Ptr (Ptr CMpLimb)) (Ptr CNMod)++instance Storable CNModMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_mat_t}+ peek ptr = CNModMat+ <$> #{peek nmod_mat_struct, entries} ptr+ <*> #{peek nmod_mat_struct, r } ptr+ <*> #{peek nmod_mat_struct, c } ptr+ <*> #{peek nmod_mat_struct, rows } ptr+ <*> #{peek nmod_mat_struct, mod } ptr+ poke = undefined++-- nmod_poly_mat_t -------------------------------------------------------------++data NModPolyMat = NModPolyMat {-# UNPACK #-} !(ForeignPtr CNModPolyMat)+data CNModPolyMat = CNModPolyMat (Ptr CNModPoly) CLong CLong (Ptr (Ptr CNModPoly)) (Ptr CNMod)++instance Storable CNModPolyMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size nmod_poly_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment nmod_poly_mat_t}+ peek ptr = CNModPolyMat+ <$> #{peek nmod_poly_mat_struct, entries} ptr+ <*> #{peek nmod_poly_mat_struct, r } ptr+ <*> #{peek nmod_poly_mat_struct, c } ptr+ <*> #{peek nmod_poly_mat_struct, rows } ptr+ <*> #{peek nmod_poly_mat_struct, modulus} ptr+ poke = error "CNModPolyMat.poke: Not defined."
+ src/Data/Number/Flint/NMod/Vec.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.NMod.Vec (+ module Data.Number.Flint.NMod.Vec.FFI+ ) where++import Data.Number.Flint.NMod.Vec.FFI
+ src/Data/Number/Flint/NMod/Vec/FFI.hsc view
@@ -0,0 +1,193 @@+{-|+module : Data.Number.Flint.NMod.Vec.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.NMod.Vec.FFI (+ -- * Vectors over integers mod n (word-size n)+ -- * Memory management+ _nmod_vec_init+ , _nmod_vec_clear+ -- * Random functions+ , _nmod_vec_randtest+ -- * Basic manipulation and comparison+ , _nmod_vec_set+ , _nmod_vec_zero+ , _nmod_vec_swap+ , _nmod_vec_reduce+ , _nmod_vec_max_bits+ , _nmod_vec_equal+ -- * Arithmetic operations+ , _nmod_vec_add+ , _nmod_vec_sub+ , _nmod_vec_neg+ , _nmod_vec_scalar_mul_nmod+ , _nmod_vec_scalar_mul_nmod_shoup+ , _nmod_vec_scalar_addmul_nmod+ -- * Dot products+ , _nmod_vec_dot_bound_limbs+ , _nmod_vec_dot+ , _nmod_vec_dot_rev+ , _nmod_vec_dot_ptr+) where++-- Vectors over integers mod n (word-size n) -----------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq+import Data.Number.Flint.NMod++#include <flint/flint.h>+#include <flint/nmod_vec.h>++-- Memory management -----------------------------------------------------------++-- | /_nmod_vec_init/ /len/ +-- +-- Returns a vector of the given length. The entries are not necessarily+-- zero.+foreign import ccall "nmod_vec.h _nmod_vec_init"+ _nmod_vec_init :: CLong -> IO (Ptr CMp)++-- | /_nmod_vec_clear/ /vec/ +-- +-- Frees the memory used by the given vector.+foreign import ccall "nmod_vec.h _nmod_vec_clear"+ _nmod_vec_clear :: Ptr CMp -> IO ()++-- Random functions ------------------------------------------------------------++-- | /_nmod_vec_randtest/ /vec/ /state/ /len/ /mod/ +-- +-- Sets @vec@ to a random vector of the given length with entries reduced+-- modulo @mod.n@.+foreign import ccall "nmod_vec.h _nmod_vec_randtest"+ _nmod_vec_randtest :: Ptr CMp -> Ptr CFRandState -> CLong -> Ptr CNMod -> IO ()++-- Basic manipulation and comparison -------------------------------------------++-- | /_nmod_vec_set/ /res/ /vec/ /len/ +-- +-- Copies @len@ entries from the vector @vec@ to @res@.+foreign import ccall "nmod_vec.h _nmod_vec_set"+ _nmod_vec_set :: Ptr CMp -> Ptr CMp -> CLong -> IO ()++-- | /_nmod_vec_zero/ /vec/ /len/ +-- +-- Zeros the given vector of the given length.+foreign import ccall "nmod_vec.h _nmod_vec_zero"+ _nmod_vec_zero :: Ptr CMp -> CLong -> IO ()++-- | /_nmod_vec_swap/ /a/ /b/ /length/ +-- +-- Swaps the vectors @a@ and @b@ of length \(n\) by actually swapping the+-- entries.+foreign import ccall "nmod_vec.h _nmod_vec_swap"+ _nmod_vec_swap :: Ptr CMp -> Ptr CMp -> CLong -> IO ()++-- | /_nmod_vec_reduce/ /res/ /vec/ /len/ /mod/ +-- +-- Reduces the entries of @(vec, len)@ modulo @mod.n@ and set @res@ to the+-- result.+foreign import ccall "nmod_vec.h _nmod_vec_reduce"+ _nmod_vec_reduce :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /_nmod_vec_max_bits/ /vec/ /len/ +-- +-- Returns the maximum number of bits of any entry in the vector.+foreign import ccall "nmod_vec.h _nmod_vec_max_bits"+ _nmod_vec_max_bits :: Ptr CMp -> CLong -> IO CFBitCnt++-- | /_nmod_vec_equal/ /vec/ /vec2/ /len/ +-- +-- Returns~\`1\` if @(vec, len)@ is equal to @(vec2, len)@, otherwise+-- returns~\`0\`.+foreign import ccall "nmod_vec.h _nmod_vec_equal"+ _nmod_vec_equal :: Ptr CMp -> Ptr CMp -> CLong -> IO CInt++-- Arithmetic operations -------------------------------------------------------++-- | /_nmod_vec_add/ /res/ /vec1/ /vec2/ /len/ /mod/ +-- +-- Sets @(res, len)@ to the sum of @(vec1, len)@ and @(vec2, len)@.+foreign import ccall "nmod_vec.h _nmod_vec_add"+ _nmod_vec_add :: Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /_nmod_vec_sub/ /res/ /vec1/ /vec2/ /len/ /mod/ +-- +-- Sets @(res, len)@ to the difference of @(vec1, len)@ and @(vec2, len)@.+foreign import ccall "nmod_vec.h _nmod_vec_sub"+ _nmod_vec_sub :: Ptr CMp -> Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /_nmod_vec_neg/ /res/ /vec/ /len/ /mod/ +-- +-- Sets @(res, len)@ to the negation of @(vec, len)@.+foreign import ccall "nmod_vec.h _nmod_vec_neg"+ _nmod_vec_neg :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> IO ()++-- | /_nmod_vec_scalar_mul_nmod/ /res/ /vec/ /len/ /c/ /mod/ +-- +-- Sets @(res, len)@ to @(vec, len)@ multiplied by \(c\). The element \(c\)+-- and all elements of \(vec\) are assumed to be less than \(mod.n\).+foreign import ccall "nmod_vec.h _nmod_vec_scalar_mul_nmod"+ _nmod_vec_scalar_mul_nmod :: Ptr CMp -> Ptr CMp -> CLong -> CMpLimb -> Ptr CNMod -> IO ()++-- | /_nmod_vec_scalar_mul_nmod_shoup/ /res/ /vec/ /len/ /c/ /mod/ +-- +-- Sets @(res, len)@ to @(vec, len)@ multiplied by \(c\) using+-- @n_mulmod_shoup@. \(mod.n\) should be less than+-- \(2^{\mathtt{FLINT\_BITS} - 1}\). \(c\) and all elements of \(vec\)+-- should be less than \(mod.n\).+foreign import ccall "nmod_vec.h _nmod_vec_scalar_mul_nmod_shoup"+ _nmod_vec_scalar_mul_nmod_shoup :: Ptr CMp -> Ptr CMp -> CLong -> CMpLimb -> Ptr CNMod -> IO ()++-- | /_nmod_vec_scalar_addmul_nmod/ /res/ /vec/ /len/ /c/ /mod/ +-- +-- Adds @(vec, len)@ times \(c\) to the vector @(res, len)@. The element+-- \(c\) and all elements of \(vec\) are assumed to be less than \(mod.n\).+foreign import ccall "nmod_vec.h _nmod_vec_scalar_addmul_nmod"+ _nmod_vec_scalar_addmul_nmod :: Ptr CMp -> Ptr CMp -> CLong -> CMpLimb -> Ptr CNMod -> IO ()++-- Dot products ----------------------------------------------------------------++-- | /_nmod_vec_dot_bound_limbs/ /len/ /mod/ +-- +-- Returns the number of limbs (0, 1, 2 or 3) needed to represent the+-- unreduced dot product of two vectors of length @len@ having entries+-- modulo @mod.n@, assuming that @len@ is nonnegative and that @mod.n@ is+-- nonzero. The computed bound is tight. In other words, this function+-- returns the precise limb size of @len@ times @(mod.n - 1) ^ 2@.+foreign import ccall "nmod_vec.h _nmod_vec_dot_bound_limbs"+ _nmod_vec_dot_bound_limbs :: CLong -> Ptr CNMod -> IO CInt++-- | /_nmod_vec_dot/ /vec1/ /vec2/ /len/ /mod/ /nlimbs/ +-- +-- Returns the dot product of (@vec1@, @len@) and (@vec2@, @len@). The+-- @nlimbs@ parameter should be 0, 1, 2 or 3, specifying the number of+-- limbs needed to represent the unreduced result.+foreign import ccall "nmod_vec.h _nmod_vec_dot"+ _nmod_vec_dot :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> CInt -> IO CMpLimb++-- | /_nmod_vec_dot_rev/ /vec1/ /vec2/ /len/ /mod/ /nlimbs/ +-- +-- The same as @_nmod_vec_dot@, but reverses @vec2@.+foreign import ccall "nmod_vec.h _nmod_vec_dot_rev"+ _nmod_vec_dot_rev :: Ptr CMp -> Ptr CMp -> CLong -> Ptr CNMod -> CInt -> IO CMpLimb++-- | /_nmod_vec_dot_ptr/ /vec1/ /vec2/ /offset/ /len/ /mod/ /nlimbs/ +-- +-- Returns the dot product of (@vec1@, @len@) and the values at+-- @vec2[i][offset]@. The @nlimbs@ parameter should be 0, 1, 2 or 3,+-- specifying the number of limbs needed to represent the unreduced result.+foreign import ccall "nmod_vec.h _nmod_vec_dot_ptr"+ _nmod_vec_dot_ptr :: Ptr CMp -> Ptr (Ptr CMp) -> CLong -> CLong -> Ptr CNMod -> CInt -> IO CMpLimb+
+ src/Data/Number/Flint/Padic.hs view
@@ -0,0 +1,60 @@+{-|+module : Data.Number.Flint.Padic+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++= p-adic numbers++A @Padic@ represents a p-adic number.+This module implements operations p-adic numbers.++== Basic usage ++Calculate a solution of \(x^2-2=0\) over \(\mathbb Q_7\) using default+precision (20 digits).++@+import Data.Number.Flint++main = do+ withNewPadicCtx 7 1 20 padic_series $ \\ctx -> + withNewPadic $ \\x -> do+ padic_set_ui x 2 ctx+ padic_sqrt x x ctx + padic_print x ctx+ putStr "\\n"+@++Running main yields:++>>> main +3 + 1*7^1 + 2*7^2 + 6*7^3 + 1*7^4 + 2*7^5 + 1*7^6 + 2*7^7 + 4*7^8 + 6*7^9 + 6*7^10 + 2*7^11 + 1*7^12 + 1*7^13 + 2*7^15 + 1*7^16 + 1*7^17 + 4*7^18 + 6*7^19++== Introduction++The @Padic@ data type represents elements of \(\mathbb{Q}_p\) to+precision \(N\), stored in the form \(x = p^v u\) +with \(u, v \in \mathbb{Z}\). Arithmetic operations can be carried out with+respect to a context containing the prime number \(p\) and various+pieces of pre-computed data.++Independent of the context, we consider a \(p\)-adic number x = u p^v to+be in canonical form whenever either p nmid u or \(u = v = 0\), and we+say it is reduced if, in addition, for non-zero \(u\), \(u \in (0, p^{N-v})\).++We briefly describe the interface:++The functions in this module expect arguments of type @Padic@, and+each variable carries its own precision. The functions have an interface+that is similar to the MPFR functions. In particular, they have the same+semantics, specified as follows: Compute the requested operation exactly+and then reduce the result to the precision of the output variable.+-}++module Data.Number.Flint.Padic (+ module Data.Number.Flint.Padic.FFI,+) where++import Data.Number.Flint.Padic.FFI+
+ src/Data/Number/Flint/Padic/FFI.hsc view
@@ -0,0 +1,936 @@+{-|+module : Data.Number.Flint.Padic.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Padic.FFI (+ -- * Data structures+ -- A \(p\)-adic number of type @CPadic@ comprises a unit \(u\), a+ -- valuation \(v\), and a precision \(N\). + -- ** p-adic numbers+ -- | A p-adic number of type Padic comprises \(a\) unit \(u\), a valuation+ -- \(v\), and a precision \(N\). Create with `newPadic`.+ Padic (..)+ , CPadic (..)+ , newPadic+ , withPadic+ , withNewPadic+ -- ** p-adic context+ --+ -- | A context object for p p-adic arithmetic contains data+ -- pertinent to p-adic computations, but which we choose not to store+ -- with each element individually. Currently, this includes the prime+ -- number \(p\) , its double inverse in case of word-sized primes,+ -- precomputed powers of \(p\) in the range given by min and max, and the+ -- printing mode. Create with `newPadicCtx`.+ , PadicCtx (..)+ , CPadicCtx (..)+ , newPadicCtx+ , withPadicCtx+ , withNewPadicCtx+ -- + , padic_unit+ , padic_get_val+ , padic_get_prec+ --+ , padic_ctx_init+ , padic_ctx_clear+ , _padic_ctx_pow_ui+ , padic_ctx_print+ -- * Memory management+ , padic_init+ , padic_init2+ , padic_clear+ , _padic_canonicalise+ , _padic_reduce+ , padic_reduce+ , PadicPrintMode (..)+ , padic_terse+ , padic_series+ , padic_val_unit+ -- * Randomisation+ , padic_randtest+ , padic_randtest_not_zero+ , padic_randtest_int+ -- * Assignments and conversions+ , padic_set+ , padic_set_si+ , padic_set_ui+ , padic_set_fmpz+ , padic_set_fmpq+ , padic_set_mpz+ , padic_set_mpq+ , padic_get_fmpz+ , padic_get_fmpq+ , padic_get_mpz+ , padic_get_mpq+ , padic_swap+ , padic_zero+ , padic_one+ -- * Comparison+ , padic_is_zero+ , padic_is_one+ , padic_equal+ -- * Arithmetic operations+ , _padic_lifts_exps+ , _padic_lifts_pows+ , padic_add+ , padic_sub+ , padic_neg+ , padic_mul+ , padic_shift+ , padic_div+ , _padic_inv_precompute+ , _padic_inv_clear+ , _padic_inv_precomp+ , _padic_inv+ , padic_inv+ , padic_sqrt+ , padic_pow_si+ -- * Exponential+ , _padic_exp_bound+ , _padic_exp_rectangular+ , padic_exp+ , padic_exp_rectangular+ , padic_exp_balanced+ -- * Logarithm+ , _padic_log_bound+ , _padic_log+ , padic_log+ , padic_log_rectangular+ , padic_log_satoh+ , padic_log_balanced+ -- * Special functions+ , _padic_teichmuller+ , padic_teichmuller+ , padic_val_fac_ui_2+ , padic_val_fac_ui+ , padic_val_fac+ -- * Input and output+ , padic_get_str+ , _padic_fprint+ , _padic_print+ , padic_print+ , padic_debug+) where ++-- p-adic numbers --------------------------------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, castPtr, nullPtr )+import Foreign.Storable+import Foreign.Marshal ( free, peekArray )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq++#include <flint/flint.h>+#include <flint/padic.h>++-- padic_t ---------------------------------------------------------------------++data Padic = Padic {-# UNPACK #-} !(ForeignPtr CPadic)+data CPadic = CPadic (Ptr CFmpz) CLong CLong++instance Storable CPadic where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size padic_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment padic_t}+ peek ptr = CPadic+ <$> (return $ castPtr ptr)+ <*> #{peek padic_struct, v} ptr+ <*> #{peek padic_struct, N} ptr+ poke ptr (CPadic u v n) = do+ #{poke padic_struct, u} ptr u+ #{poke padic_struct, v} ptr v+ #{poke padic_struct, N} ptr n+ +-- | Create a new p-adic.+newPadic = do+ p <- mallocForeignPtr+ withForeignPtr p padic_init+ addForeignPtrFinalizer p_padic_clear p+ return $ Padic p++-- | Use p-adic.+{-# INLINE withPadic #-}+withPadic (Padic p) f = do+ withForeignPtr p $ \fp -> (Padic p,) <$> f fp++-- | Apply `f` to new p-adic.+{-# INLINE withNewPadic #-}+withNewPadic f = do+ x <- newPadic+ withPadic x f++-- padic_inv_t -----------------------------------------------------------------++data PadicInv = PadicInv {-# UNPACK #-} !(ForeignPtr CPadicInv)+type CPadicInv = CFlint PadicInv++instance Storable CPadicInv where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size padic_inv_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment padic_inv_t}+ peek = error "CPadicInv.peek: Not defined"+ poke = error "CPadicInv.poke: Not defined"++newPadicInv x n = do+ p <- mallocForeignPtr+ withForeignPtr p $ \p ->+ withFmpz x $ \x -> _padic_inv_precompute p x n+ addForeignPtrFinalizer p_padic_inv_clear p+ return $ PadicInv p+ +{-# INLINE withPadicInv #-}+withPadicInv (PadicInv p) f =+ withForeignPtr p $ \ fp -> (PadicInv p,) <$> f fp++-- padic_ctx_t -----------------------------------------------------------------++data PadicCtx = PadicCtx {-# UNPACK #-} !(ForeignPtr CPadicCtx)+data CPadicCtx =+ CPadicCtx (Ptr CFmpz) CDouble (Ptr CFmpz) CLong CLong PadicPrintMode++instance Storable CPadicCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size padic_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment padic_ctx_t}+ peek ptr = CPadicCtx+ <$> (return $ castPtr ptr)+ <*> #{peek padic_ctx_struct, pinv } ptr+ <*> #{peek padic_ctx_struct, pow } ptr+ <*> #{peek padic_ctx_struct, min } ptr+ <*> #{peek padic_ctx_struct, max } ptr+ <*> #{peek padic_ctx_struct, mode } ptr+ poke = undefined++-- | Create p-adic context with prime \(p\), precomputed powers \(p^{min}\)+-- to \(p^{max}\) and `PadicPrintMode` @mode@.+newPadicCtx p min max mode = do+ ctx <- mallocForeignPtr+ withForeignPtr ctx $ \ctx ->+ withFmpz p $ \p -> + padic_ctx_init ctx p min max mode+ addForeignPtrFinalizer p_padic_ctx_clear ctx+ return $ PadicCtx ctx++-- | Use p-adic context.+{-# INLINE withPadicCtx #-}+withPadicCtx (PadicCtx p) f = do+ withForeignPtr p $ \fp -> (PadicCtx p,) <$> f fp++-- | Use new p-adic ctx+withNewPadicCtx p min max mode f = do+ ctx <- newPadicCtx p min max mode+ withPadicCtx ctx $ \ctx -> do f ctx+ +-- | /padic_unit/ /op/ +-- +-- Returns the unit part of the \(p\)-adic number as a FLINT integer, which+-- can be used as an operand for the @fmpz@ functions.+padic_unit :: Ptr CPadic -> IO (Ptr CFmpz)+padic_unit x = return $ castPtr x+ +-- | /padic_get_val/ /op/ +-- +-- Returns the valuation part of the \(p\)-adic number.+padic_get_val :: Ptr CPadic -> IO CLong+padic_get_val x = do+ CPadic u v n <- peek x+ return v+ +-- | /padic_get_prec/ /op/ +-- +-- Returns the precision of the \(p\)-adic number.+padic_get_prec :: Ptr CPadic -> IO CLong+padic_get_prec x = do+ CPadic u v n <- peek x+ return n++-- Context ---------------------------------------------------------------------++-- A context object for \(p\)-adic arithmetic contains data pertinent to+-- p-adic computations, but which we choose not to store with each element+-- individually. Currently, this includes the prime number \(p\), its+-- @double@ inverse in case of word-sized primes, precomputed powers of+-- \(p\) in the range given by @min@ and @max@, and the printing mode.+--+-- | /padic_ctx_init/ /ctx/ /p/ /min/ /max/ /mode/ +-- +-- Initialises the context @ctx@ with the given data.+-- +-- Assumes that \(p\) is a prime. This is not verified but the subsequent+-- behaviour is undefined if \(p\) is a composite number.+-- +-- Assumes that @min@ and @max@ are non-negative and that @min@ is at most+-- @max@, raising an @abort@ signal otherwise.+-- +-- Assumes that the printing mode is one of @PADIC_TERSE@, @PADIC_SERIES@,+-- or @PADIC_VAL_UNIT@. Using the example \(x = 7^{-1} 12\) in+-- \(\mathbf{Q}_7\), these behave as follows:+-- +-- In @padic_terseE@ mode, a \(p\)-adic number is printed in the same way as+-- a rational number, e.g. @12\/7@.+-- +-- In @padic_series@ mode, a \(p\)-adic number is printed digit by digit,+-- e.g. @5*7^-1 + 1@.+-- +-- In @padic_val_unit@ mode, a \(p\)-adic number is printed showing the+-- valuation and unit parts separately, e.g. @12*7^-1@.+foreign import ccall "padic.h padic_ctx_init"+ padic_ctx_init :: Ptr CPadicCtx+ -> Ptr CFmpz -> CLong -> CLong -> PadicPrintMode -> IO ()++-- | /padic_ctx_clear/ /ctx/ +-- +-- Clears all memory that has been allocated as part of the context.+foreign import ccall "padic.h padic_ctx_clear"+ padic_ctx_clear :: Ptr CPadicCtx -> IO ()++foreign import ccall "padic.h &padic_ctx_clear"+ p_padic_ctx_clear :: FunPtr (Ptr CPadicCtx -> IO ())++-- | /_padic_ctx_pow_ui/ /rop/ /e/ /ctx/ +-- +-- Sets @rop@ to \(p^e\) as efficiently as possible, where @rop@ is+-- expected to be an uninitialised @fmpz_t@.+-- +-- If the return value is non-zero, it is the responsibility of the caller+-- to clear the returned integer.+foreign import ccall "padic.h _padic_ctx_pow_ui"+ _padic_ctx_pow_ui :: Ptr CFmpz -> CULong -> Ptr CPadicCtx -> IO CInt+ +padic_ctx_print ctx = do+ CPadicCtx p pinv pow min max mode <- peek ctx+ putStr "p = "+ fmpz_print p+ putStrLn $ " (1/pinv = " ++ show (1/pinv)+ ++ ", min = " ++ show min+ ++ ", max = " ++ show max+ ++ ", mode = " ++ show mode+ ++ ")"+ +-- Print modes -----------------------------------------------------------------++newtype PadicPrintMode = PadicPrintMode {_PadicPrintMode :: CInt} deriving Eq++instance Storable PadicPrintMode where+ {-# INLINE sizeOf #-}+ sizeOf _ = sizeOf (undefined :: CInt)+ {-# INLINE alignment #-}+ alignment _ = alignment (undefined :: CInt)+ peek ptr = do+ v <- peek (castPtr ptr) :: IO CInt+ return $ PadicPrintMode v+ poke = undefined++instance Show PadicPrintMode where+ show mode+ | mode == padic_terse = "PADIC_TERSE"+ | mode == padic_series = "PADIC_SERIES"+ | mode == padic_val_unit = "PADIC_VAL_UNIT"+ | otherwise = "unknown print mode"+ +padic_terse = PadicPrintMode #const PADIC_TERSE+padic_series = PadicPrintMode #const PADIC_SERIES+padic_val_unit = PadicPrintMode #const PADIC_VAL_UNIT++-- Memory management -----------------------------------------------------------++-- | /padic_init/ /rop/ +-- +-- Initialises the \(p\)-adic number with the precision set to+-- @PADIC_DEFAULT_PREC@, which is defined as \(20\).+foreign import ccall "padic.h padic_init"+ padic_init :: Ptr CPadic -> IO ()++-- | /padic_init2/ /rop/ /N/ +-- +-- Initialises the \(p\)-adic number @rop@ with precision \(N\).+foreign import ccall "padic.h padic_init2"+ padic_init2 :: Ptr CPadic -> CLong -> IO ()++-- | /padic_clear/ /rop/ +-- +-- Clears all memory used by the \(p\)-adic number @rop@.+foreign import ccall "padic.h padic_clear"+ padic_clear :: Ptr CPadic -> IO ()++foreign import ccall "padic.h &padic_clear"+ p_padic_clear :: FunPtr (Ptr CPadic -> IO ())++-- | /_padic_canonicalise/ /rop/ /ctx/ +-- +-- Brings the \(p\)-adic number @rop@ into canonical form.+-- +-- That is to say, ensures that either \(u = v = 0\) or \(p \nmid u\).+-- There is no reduction modulo a power of \(p\).+foreign import ccall "padic.h _padic_canonicalise"+ _padic_canonicalise :: Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /_padic_reduce/ /rop/ /ctx/ +-- +-- Given a \(p\)-adic number @rop@ in canonical form, reduces it modulo+-- \(p^N\).+foreign import ccall "padic.h _padic_reduce"+ _padic_reduce :: Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_reduce/ /rop/ /ctx/ +-- +-- Ensures that the \(p\)-adic number @rop@ is reduced.+foreign import ccall "padic.h padic_reduce"+ padic_reduce :: Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- Randomisation ---------------------------------------------------------------++-- | /padic_randtest/ /rop/ /state/ /ctx/ +-- +-- Sets @rop@ to a random \(p\)-adic number modulo \(p^N\) with valuation+-- in the range \([- \lceil N/10\rceil, N)\),+-- \([N - \lceil -N/10\rceil, N)\), or \([-10, 0)\) as \(N\) is positive,+-- negative or zero, whenever @rop@ is non-zero.+foreign import ccall "padic.h padic_randtest"+ padic_randtest :: Ptr CPadic -> Ptr CFRandState -> Ptr CPadicCtx -> IO ()++-- | /padic_randtest_not_zero/ /rop/ /state/ /ctx/ +-- +-- Sets @rop@ to a random non-zero \(p\)-adic number modulo \(p^N\), where+-- the range of the valuation is as for the function @padic_randtest@.+foreign import ccall "padic.h padic_randtest_not_zero"+ padic_randtest_not_zero :: Ptr CPadic -> Ptr CFRandState -> Ptr CPadicCtx -> IO ()++-- | /padic_randtest_int/ /rop/ /state/ /ctx/ +-- +-- Sets @rop@ to a random \(p\)-adic integer modulo \(p^N\).+-- +-- Note that whenever \(N \leq 0\), @rop@ is set to zero.+foreign import ccall "padic.h padic_randtest_int"+ padic_randtest_int :: Ptr CPadic -> Ptr CFRandState -> Ptr CPadicCtx -> IO ()++-- Assignments and conversions -------------------------------------------------++-- All assignment functions set the value of @rop@ from @op@, reduced to+-- the precision of @rop@.+--+-- | /padic_set/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the \(p\)-adic number @op@.+foreign import ccall "padic.h padic_set"+ padic_set :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_set_si/ /rop/ /op/ /ctx/ +-- +-- Sets the \(p\)-adic number @rop@ to the @slong@ integer @op@.+foreign import ccall "padic.h padic_set_si"+ padic_set_si :: Ptr CPadic -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_set_ui/ /rop/ /op/ /ctx/ +-- +-- Sets the \(p\)-adic number @rop@ to the @ulong@ integer @op@.+foreign import ccall "padic.h padic_set_ui"+ padic_set_ui :: Ptr CPadic -> CULong -> Ptr CPadicCtx -> IO ()++-- | /padic_set_fmpz/ /rop/ /op/ /ctx/ +-- +-- Sets the \(p\)-adic number @rop@ to the integer @op@.+foreign import ccall "padic.h padic_set_fmpz"+ padic_set_fmpz :: Ptr CPadic -> Ptr CFmpz -> Ptr CPadicCtx -> IO ()++-- | /padic_set_fmpq/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the rational @op@.+foreign import ccall "padic.h padic_set_fmpq"+ padic_set_fmpq :: Ptr CPadic -> Ptr CFmpq -> Ptr CPadicCtx -> IO ()++-- | /padic_set_mpz/ /rop/ /op/ /ctx/ +-- +-- Sets the \(p\)-adic number @rop@ to the MPIR integer @op@.+foreign import ccall "padic.h padic_set_mpz"+ padic_set_mpz :: Ptr CPadic -> Ptr CMpz -> Ptr CPadicCtx -> IO ()++-- | /padic_set_mpq/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the MPIR rational @op@.+foreign import ccall "padic.h padic_set_mpq"+ padic_set_mpq :: Ptr CPadic -> Ptr CMpq -> Ptr CPadicCtx -> IO ()++-- | /padic_get_fmpz/ /rop/ /op/ /ctx/ +-- +-- Sets the integer @rop@ to the exact \(p\)-adic integer @op@.+-- +-- If @op@ is not a \(p\)-adic integer, raises an @abort@ signal.+foreign import ccall "padic.h padic_get_fmpz"+ padic_get_fmpz :: Ptr CFmpz -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_get_fmpq/ /rop/ /op/ /ctx/ +-- +-- Sets the rational @rop@ to the \(p\)-adic number @op@.+foreign import ccall "padic.h padic_get_fmpq"+ padic_get_fmpq :: Ptr CFmpq -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_get_mpz/ /rop/ /op/ /ctx/ +-- +-- Sets the MPIR integer @rop@ to the \(p\)-adic integer @op@.+-- +-- If @op@ is not a \(p\)-adic integer, raises an @abort@ signal.+foreign import ccall "padic.h padic_get_mpz"+ padic_get_mpz :: Ptr CMpz -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_get_mpq/ /rop/ /op/ /ctx/ +-- +-- Sets the MPIR rational @rop@ to the value of @op@.+foreign import ccall "padic.h padic_get_mpq"+ padic_get_mpq :: Ptr CMpq -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_swap/ /op1/ /op2/ +-- +-- Swaps the two \(p\)-adic numbers @op1@ and @op2@.+-- +-- Note that this includes swapping the precisions. In particular, this+-- operation is not equivalent to swapping @op1@ and @op2@ using+-- @padic_set@ and an auxiliary variable whenever the precisions of the two+-- elements are different.+foreign import ccall "padic.h padic_swap"+ padic_swap :: Ptr CPadic -> Ptr CPadic -> IO ()++-- | /padic_zero/ /rop/ +-- +-- Sets the \(p\)-adic number @rop@ to zero.+foreign import ccall "padic.h padic_zero"+ padic_zero :: Ptr CPadic -> IO ()++-- | /padic_one/ /rop/ +-- +-- Sets the \(p\)-adic number @rop@ to one, reduced modulo the precision of+-- @rop@.+foreign import ccall "padic.h padic_one"+ padic_one :: Ptr CPadic -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /padic_is_zero/ /op/ +-- +-- Returns whether @op@ is equal to zero.+foreign import ccall "padic.h padic_is_zero"+ padic_is_zero :: Ptr CPadic -> IO CInt++-- | /padic_is_one/ /op/ +-- +-- Returns whether @op@ is equal to one, that is, whether \(u = 1\) and+-- \(v = 0\).+foreign import ccall "padic.h padic_is_one"+ padic_is_one :: Ptr CPadic -> IO CInt++-- | /padic_equal/ /op1/ /op2/ +-- +-- Returns whether @op1@ and @op2@ are equal, that is, whether+-- \(u_1 = u_2\) and \(v_1 = v_2\).+foreign import ccall "padic.h padic_equal"+ padic_equal :: Ptr CPadic -> Ptr CPadic -> IO CInt++-- Arithmetic operations -------------------------------------------------------++-- | /_padic_lifts_exps/ /n/ /N/ +-- +-- Given a positive integer \(N\) define the sequence+-- \(a_0 = N, a_1 = \lceil a_0/2\rceil, \dotsc, a_{n-1} = \lceil a_{n-2}/2\rceil = 1\).+-- Then \(n = \lceil\log_2 N\rceil + 1\).+-- +-- This function sets \(n\) and allocates and returns the array \(a\).+foreign import ccall "padic.h _padic_lifts_exps"+ _padic_lifts_exps :: Ptr CLong -> CLong -> IO (Ptr CLong)++-- | /_padic_lifts_pows/ /pow/ /a/ /n/ /p/ +-- +-- Given an array \(a\) as computed above, this function computes the+-- corresponding powers of \(p\), that is, @pow[i]@ is equal to+-- \(p^{a_i}\).+foreign import ccall "padic.h _padic_lifts_pows"+ _padic_lifts_pows :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> IO ()++-- | /padic_add/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the sum of @op1@ and @op2@.+foreign import ccall "padic.h padic_add"+ padic_add :: Ptr CPadic -> Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_sub/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the difference of @op1@ and @op2@.+foreign import ccall "padic.h padic_sub"+ padic_sub :: Ptr CPadic -> Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_neg/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the additive inverse of @op@.+foreign import ccall "padic.h padic_neg"+ padic_neg :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_mul/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the product of @op1@ and @op2@.+foreign import ccall "padic.h padic_mul"+ padic_mul :: Ptr CPadic -> Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_shift/ /rop/ /op/ /v/ /ctx/ +-- +-- Sets @rop@ to the product of @op@ and \(p^v\).+foreign import ccall "padic.h padic_shift"+ padic_shift :: Ptr CPadic -> Ptr CPadic -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_div/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the quotient of @op1@ and @op2@.+foreign import ccall "padic.h padic_div"+ padic_div :: Ptr CPadic -> Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /_padic_inv_precompute/ /S/ /p/ /N/ +-- +-- Pre-computes some data and allocates temporary space for \(p\)-adic+-- inversion using Hensel lifting.+foreign import ccall "padic.h _padic_inv_precompute"+ _padic_inv_precompute :: Ptr CPadicInv -> Ptr CFmpz -> CLong -> IO ()++-- | /_padic_inv_clear/ /S/ +-- +-- Frees the memory used by \(S\).+foreign import ccall "padic.h _padic_inv_clear"+ _padic_inv_clear :: Ptr CPadicInv -> IO ()++foreign import ccall "padic.h &_padic_inv_clear"+ p_padic_inv_clear :: FunPtr (Ptr CPadicInv -> IO ())++-- | /_padic_inv_precomp/ /rop/ /op/ /S/ +-- +-- Sets @rop@ to the inverse of @op@ modulo \(p^N\), assuming that @op@ is+-- a unit and \(N \geq 1\).+-- +-- In the current implementation, allows aliasing, but this might change in+-- future versions.+-- +-- Uses some data \(S\) precomputed by calling the function+-- @_padic_inv_precompute@. Note that this object is not declared @const@+-- and in fact it carries a field providing temporary work space. This+-- allows repeated calls of this function to avoid repeated memory+-- allocations, as used e.g. by the function @padic_log@.+foreign import ccall "padic.h _padic_inv_precomp"+ _padic_inv_precomp :: Ptr CFmpz -> Ptr CFmpz -> Ptr CPadicInv -> IO ()++-- | /_padic_inv/ /rop/ /op/ /p/ /N/ +-- +-- Sets @rop@ to the inverse of @op@ modulo \(p^N\), assuming that @op@ is+-- a unit and \(N \geq 1\).+-- +-- In the current implementation, allows aliasing, but this might change in+-- future versions.+foreign import ccall "padic.h _padic_inv"+ _padic_inv :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /padic_inv/ /rop/ /op/ /ctx/ +-- +-- Computes the inverse of @op@ modulo \(p^N\).+-- +-- Suppose that @op@ is given as \(x = u p^v\). Raises an @abort@ signal if+-- \(v < -N\). Otherwise, computes the inverse of \(u\) modulo \(p^{N+v}\).+-- +-- This function employs Hensel lifting of an inverse modulo \(p\).+foreign import ccall "padic.h padic_inv"+ padic_inv :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_sqrt/ /rop/ /op/ /ctx/ +-- +-- Returns whether @op@ is a \(p\)-adic square. If this is the case, sets+-- @rop@ to one of the square roots; otherwise, the value of @rop@ is+-- undefined.+-- +-- We have the following theorem:+-- +-- Let \(u \in \mathbf{Z}^{\times}\). Then \(u\) is a square if and only if+-- \(u \bmod p\) is a square in \(\mathbf{Z} / p \mathbf{Z}\), for+-- \(p > 2\), or if \(u \bmod 8\) is a square in+-- \(\mathbf{Z} / 8 \mathbf{Z}\), for \(p = 2\).+foreign import ccall "padic.h padic_sqrt"+ padic_sqrt :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO CInt++-- | /padic_pow_si/ /rop/ /op/ /e/ /ctx/ +-- +-- Sets @rop@ to @op@ raised to the power \(e\), which is defined as one+-- whenever \(e = 0\).+-- +-- Assumes that some computations involving \(e\) and the valuation of @op@+-- do not overflow in the @slong@ range.+-- +-- Note that if the input \(x = p^v u\) is defined modulo \(p^N\) then+-- \(x^e = p^{ev} u^e\) is defined modulo \(p^{N + (e - 1) v}\), which is a+-- precision loss in case \(v < 0\).+foreign import ccall "padic.h padic_pow_si"+ padic_pow_si :: Ptr CPadic -> Ptr CPadic -> CLong -> Ptr CPadicCtx -> IO ()++-- Exponential -----------------------------------------------------------------++-- | /_padic_exp_bound/ /v/ /N/ /p/ +-- +-- Returns an integer \(i\) such that for all \(j \geq i\) we have+-- \(\operatorname{ord}_p(x^j / j!) \geq N\), where+-- \(\operatorname{ord}_p(x) = v\).+-- +-- When \(p\) is a word-sized prime, returns+-- \(\left\lceil \frac{(p-1)N - 1}{(p-1)v - 1}\right\rceil\). Otherwise,+-- returns \(\lceil N/v\rceil\).+-- +-- Assumes that \(v < N\). Moreover, \(v\) has to be at least \(2\) or+-- \(1\), depending on whether \(p\) is \(2\) or odd.+foreign import ccall "padic.h _padic_exp_bound"+ _padic_exp_bound :: CLong -> CLong -> Ptr CFmpz -> IO CLong++-- | /_padic_exp_rectangular/ /rop/ /u/ /v/ /p/ /N/ +-- +-- Sets @rop@ to the \(p\)-exponential function evaluated at \(x = p^v u\),+-- reduced modulo \(p^N\).+-- +-- Assumes that \(x \neq 0\), that \(\operatorname{ord}_p(x) < N\) and that+-- \(\exp(x)\) converges, that is, that \(\operatorname{ord}_p(x)\) is at+-- least \(2\) or \(1\) depending on whether the prime \(p\) is \(2\) or+-- odd.+-- +-- Supports aliasing between @rop@ and \(u\).+foreign import ccall "padic.h _padic_exp_rectangular"+ _padic_exp_rectangular :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /padic_exp/ /y/ /x/ /ctx/ +-- +-- Returns whether the \(p\)-adic exponential function converges at the+-- \(p\)-adic number \(x\), and if so sets \(y\) to its value.+-- +-- The \(p\)-adic exponential function is defined by the usual series+-- +-- \[`\]+-- \[\exp_p(x) = \sum_{i = 0}^{\infty} \frac{x^i}{i!}\]+-- +-- but this only converges only when+-- \(\operatorname{ord}_p(x) > 1 / (p - 1)\). For elements+-- \(x \in \mathbf{Q}_p\), this means that+-- \(\operatorname{ord}_p(x) \geq 1\) when \(p \geq 3\) and+-- \(\operatorname{ord}_2(x) \geq 2\) when \(p = 2\).+foreign import ccall "padic.h padic_exp"+ padic_exp :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO CInt++-- | /padic_exp_rectangular/ /y/ /x/ /ctx/ +-- +-- Returns whether the \(p\)-adic exponential function converges at the+-- \(p\)-adic number \(x\), and if so sets \(y\) to its value.+-- +-- Uses a rectangular splitting algorithm to evaluate the series expression+-- of \(\exp(x) \bmod{p^N}\).+foreign import ccall "padic.h padic_exp_rectangular"+ padic_exp_rectangular :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO CInt++-- | /padic_exp_balanced/ /y/ /x/ /ctx/ +-- +-- Returns whether the \(p\)-adic exponential function converges at the+-- \(p\)-adic number \(x\), and if so sets \(y\) to its value.+-- +-- Uses a balanced approach, balancing the size of chunks of \(x\) with the+-- valuation and hence the rate of convergence, which results in a+-- quasi-linear algorithm in \(N\), for fixed \(p\).+foreign import ccall "padic.h padic_exp_balanced"+ padic_exp_balanced :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO CInt++-- Logarithm -------------------------------------------------------------------++-- | /_padic_log_bound/ /v/ /N/ /p/ +-- +-- Returns \(b\) such that for all \(i \geq b\) we have+-- +-- \[`\]+-- \[i v - \operatorname{ord}_p(i) \geq N\]+-- +-- where \(v \geq 1\).+-- +-- Assumes that \(1 \leq v < N\) or \(2 \leq v < N\) when \(p\) is odd or+-- \(p = 2\), respectively, and also that \(N < 2^{f-2}\) where \(f\) is+-- @FLINT_BITS@.+foreign import ccall "padic.h _padic_log_bound"+ _padic_log_bound :: CLong -> CLong -> Ptr CFmpz -> IO CLong++-- | /_padic_log/ /z/ /y/ /v/ /p/ /N/ +-- +-- Computes+-- +-- \[`\]+-- \[z = - \sum_{i = 1}^{\infty} \frac{y^i}{i} \pmod{p^N},\]+-- +-- reduced modulo \(p^N\).+-- +-- Note that this can be used to compute the \(p\)-adic logarithm via the+-- equation+-- +-- \[`\]+-- \[\begin{aligned}+-- \log(x) & = \sum_{i=1}^{\infty} (-1)^{i-1} \frac{(x-1)^i}{i} \\+-- & = - \sum_{i=1}^{\infty} \frac{(1-x)^i}{i}.+-- \end{aligned}\]+-- +-- Assumes that \(y = 1 - x\) is non-zero and that+-- \(v = \operatorname{ord}_p(y)\) is at least \(1\) when \(p\) is odd and+-- at least \(2\) when \(p = 2\) so that the series converges.+-- +-- Assumes that \(v < N\), and hence in particular \(N \geq 2\).+-- +-- Does not support aliasing between \(y\) and \(z\).+foreign import ccall "padic.h _padic_log"+ _padic_log :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /padic_log/ /rop/ /op/ /ctx/ +-- +-- Returns whether the \(p\)-adic logarithm function converges at the+-- \(p\)-adic number @op@, and if so sets @rop@ to its value.+-- +-- The \(p\)-adic logarithm function is defined by the usual series+-- +-- \[`\]+-- \[\log_p(x) = \sum_{i=1}^{\infty} (-1)^{i-1} \frac{(x-1)^i}{i}\]+-- +-- but this only converges when \(\operatorname{ord}_p(x - 1)\) is at least+-- \(2\) or \(1\) when \(p = 2\) or \(p > 2\), respectively.+foreign import ccall "padic.h padic_log"+ padic_log :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO CInt++-- | /padic_log_rectangular/ /rop/ /op/ /ctx/ +-- +-- Returns whether the \(p\)-adic logarithm function converges at the+-- \(p\)-adic number @op@, and if so sets @rop@ to its value.+-- +-- Uses a rectangular splitting algorithm to evaluate the series expression+-- of \(\log(x) \bmod{p^N}\).+foreign import ccall "padic.h padic_log_rectangular"+ padic_log_rectangular :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO CInt++-- | /padic_log_satoh/ /rop/ /op/ /ctx/ +-- +-- Returns whether the \(p\)-adic logarithm function converges at the+-- \(p\)-adic number @op@, and if so sets @rop@ to its value.+-- +-- Uses an algorithm based on a result of Satoh, Skjernaa and Taguchi that+-- \(\operatorname{ord}_p\bigl(a^{p^k} - 1\bigr) > k\), which implies that+-- +-- \[`\]+-- \[\log(a) \equiv p^{-k} \Bigl( \log\bigl(a^{p^k}\bigr) \pmod{p^{N+k}} +-- \Bigr) \pmod{p^N}.\]+foreign import ccall "padic.h padic_log_satoh"+ padic_log_satoh :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO CInt++-- | /padic_log_balanced/ /rop/ /op/ /ctx/ +-- +-- Returns whether the \(p\)-adic logarithm function converges at the+-- \(p\)-adic number @op@, and if so sets @rop@ to its value.+foreign import ccall "padic.h padic_log_balanced"+ padic_log_balanced :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO CInt++-- Special functions -----------------------------------------------------------++-- | /_padic_teichmuller/ /rop/ /op/ /p/ /N/ +-- +-- Computes the Teichm\"uller lift of the \(p\)-adic unit @op@, assuming+-- that \(N \geq 1\).+-- +-- Supports aliasing between @rop@ and @op@.+foreign import ccall "padic.h _padic_teichmuller"+ _padic_teichmuller :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> CLong -> IO ()++-- | /padic_teichmuller/ /rop/ /op/ /ctx/ +-- +-- Computes the Teichm\"uller lift of the \(p\)-adic unit @op@.+-- +-- If @op@ is a \(p\)-adic integer divisible by \(p\), sets @rop@ to zero,+-- which satisfies \(t^p - t = 0\), although it is clearly not a+-- \((p-1)\)-st root of unity.+-- +-- If @op@ has negative valuation, raises an @abort@ signal.+foreign import ccall "padic.h padic_teichmuller"+ padic_teichmuller :: Ptr CPadic -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_val_fac_ui_2/ /n/ +-- +-- Computes the \(2\)-adic valuation of \(n!\).+-- +-- Note that since \(n\) fits into an @ulong@, so does+-- \(\operatorname{ord}_2(n!)\) since+-- \(\operatorname{ord}_2(n!) \leq (n - 1) / (p - 1) = n - 1\).+foreign import ccall "padic.h padic_val_fac_ui_2"+ padic_val_fac_ui_2 :: CULong -> IO CULong++-- | /padic_val_fac_ui/ /n/ /p/ +-- +-- Computes the \(p\)-adic valuation of \(n!\).+-- +-- Note that since \(n\) fits into an @ulong@, so does+-- \(\operatorname{ord}_p(n!)\) since+-- \(\operatorname{ord}_p(n!) \leq (n - 1) / (p - 1)\).+foreign import ccall "padic.h padic_val_fac_ui"+ padic_val_fac_ui :: CULong -> Ptr CFmpz -> IO CULong++-- | /padic_val_fac/ /rop/ /op/ /p/ +-- +-- Sets @rop@ to the \(p\)-adic valuation of the factorial of @op@,+-- assuming that @op@ is non-negative.+foreign import ccall "padic.h padic_val_fac"+ padic_val_fac :: Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()++-- Input and output ------------------------------------------------------------++-- | /padic_get_str/ /str/ /op/ /ctx/ +-- +-- Returns the string representation of the \(p\)-adic number @op@+-- according to the printing mode set in the context.+-- +-- If @str@ is @NULL@ then a new block of memory is allocated and a pointer+-- to this is returned. Otherwise, it is assumed that the string @str@ is+-- large enough to hold the representation and it is also the return value.+foreign import ccall "padic.h padic_get_str"+ padic_get_str :: CString -> Ptr CPadic -> Ptr CPadicCtx -> IO CString++-- | /_padic_fprint/ /file/ /u/ /v/ /ctx/ +-- +-- Prints the string representation of the \(p\)-adic number @op@ to the+-- stream @file@.+-- +-- In the current implementation, always returns \(1\).+foreign import ccall "padic.h _padic_fprint"+ _padic_fprint :: Ptr CFile -> Ptr CFmpz -> CLong -> Ptr CPadicCtx -> IO CInt++-- | /_padic_print/ /u/ /v/ /ctx/ +-- +-- Prints the string representation of the \(p\)-adic number @op@ to the+-- stream @stdout@.+-- +-- In the current implementation, always returns \(1\).+foreign import ccall "padic.h _padic_print"+ _padic_print :: Ptr CFmpz -> CLong -> Ptr CPadicCtx -> IO CInt++-- | /padic_print/ /op/ /ctx/ +-- +-- Prints the string representation of the \(p\)-adic number @op@ to the+-- stream @stdout@.+-- +-- In the current implementation, always returns \(1\).+padic_print :: Ptr CPadic -> Ptr CPadicCtx -> IO CInt+padic_print x ctx = printCStr (flip (padic_get_str nullPtr) ctx) x++-- | /padic_debug/ /op/ +-- +-- Prints debug information about @op@ to the stream @stdout@, in the+-- format @\"(u v N)\"@.+foreign import ccall "padic.h padic_debug"+ padic_debug :: Ptr CPadic -> IO ()+
+ src/Data/Number/Flint/Padic/Mat.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Padic.Mat (+ module Data.Number.Flint.Padic.Mat.FFI+) where++import Data.Number.Flint.Padic.Mat.FFI
+ src/Data/Number/Flint/Padic/Mat/FFI.hsc view
@@ -0,0 +1,477 @@+{-|+module : Data.Number.Flint.Padic.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Padic.Mat.FFI (+ -- * Matrices over p-adic numbers+ PadicMat (..)+ , CPadicMat (..)+ -- * Constructors+ , newPadicMat+ , withPadicMat+ -- * Macros+ , padic_mat+ , padic_mat_entry+ -- , padic_mat_val+ -- , padic_mat_prec+ , padic_mat_get_val+ , padic_mat_get_prec+ , padic_mat_nrows+ , padic_mat_ncols+ -- * Memory management+ , padic_mat_init+ , padic_mat_init2+ , padic_mat_clear+ , _padic_mat_canonicalise+ , _padic_mat_reduce+ , padic_mat_reduce+ , padic_mat_is_empty+ , padic_mat_is_square+ , padic_mat_is_canonical+ -- * Basic assignment+ , padic_mat_set+ , padic_mat_swap+ , padic_mat_swap_entrywise+ , padic_mat_zero+ , padic_mat_one+ -- * Conversions+ , padic_mat_set_fmpq_mat+ , padic_mat_get_fmpq_mat+ -- * Entries+ , padic_mat_get_entry_padic+ , padic_mat_set_entry_padic+ -- * Comparison+ , padic_mat_equal+ , padic_mat_is_zero+ -- * Input and output+ , padic_mat_get_str+ , padic_mat_get_str_pretty+ , padic_mat_fprint+ , padic_mat_fprint_pretty+ , padic_mat_print+ , padic_mat_print_pretty+ -- * Random matrix generation+ , padic_mat_randtest+ -- * Transpose+ , padic_mat_transpose+ -- * Addition and subtraction+ , _padic_mat_add+ , padic_mat_add+ , _padic_mat_sub+ , padic_mat_sub+ , _padic_mat_neg+ , padic_mat_neg+ -- * Scalar operations+ , _padic_mat_scalar_mul_padic+ , padic_mat_scalar_mul_padic+ , _padic_mat_scalar_mul_fmpz+ , padic_mat_scalar_mul_fmpz+ , padic_mat_scalar_div_fmpz+ -- * Multiplication+ , padic_mat_mul+) where ++-- matrices over p-adic numbers ------------------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Mat+import Data.Number.Flint.Fmpq.Mat+import Data.Number.Flint.Padic++#include <flint/flint.h>+#include <flint/padic.h>+#include <flint/padic_mat.h>++-- padic_mat_t -----------------------------------------------------------------++data PadicMat = PadicMat {-# UNPACK #-} !(ForeignPtr CPadicMat)+data CPadicMat = CPadicMat (Ptr CFmpzMat) CLong CLong++instance Storable CPadicMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size padic_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment padic_mat_t}+ peek ptr = return CPadicMat+ `ap` #{peek padic_mat_struct, mat} ptr+ `ap` #{peek padic_mat_struct, val} ptr+ `ap` #{peek padic_mat_struct, N } ptr+ poke = undefined++newPadicMat rows cols prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> padic_mat_init x rows cols prec+ addForeignPtrFinalizer p_padic_mat_clear x+ return $ PadicMat x++{-# INLINE withPadicMat #-}+withPadicMat (PadicMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (PadicMat x,)++-- Module documentation --------------------------------------------------------++-- We represent a matrix over \(\mathbf{Q}_p\) as a product \(p^v M\),+-- where \(p\) is a prime number, \(v \in \mathbf{Z}\) and \(M\) a matrix+-- over \(\mathbf{Z}\). We say this matrix is in /canonical form/ if either+-- \(M\) is zero, in which case we choose \(v = 0\), too, or if \(M\)+-- contains at least one p-adic unit. We say this matrix is /reduced/+-- modulo \(p^N\) if it is canonical form and if all coefficients of \(M\)+-- lie in the range \([0, p^{N-v})\).+--++-- | /padic_mat/ /A/ +-- +-- Returns a pointer to the unit part of the matrix, which is a matrix over+-- \(\mathbf{Z}\).+-- +-- The return value can be used as an argument to the functions in the+-- @fmpz_mat@ module.+padic_mat :: Ptr CPadicMat -> IO (Ptr CFmpzMat)+padic_mat ptr = return $ castPtr ptr+ +-- | /padic_mat_entry/ /A/ /i/ /j/ +-- +-- Returns a pointer to unit part of the entry in position \((i, j)\). Note+-- that this is not necessarily a unit.+-- +-- The return value can be used as an argument to the functions in the+-- @fmpz@ module.+padic_mat_entry :: Ptr CPadicMat -> CLong -> CLong -> IO (Ptr CFmpz)+padic_mat_entry a i j = do+ CPadicMat mat _ _ <- peek a+ fmpz_mat_entry mat i j+ +-- | /padic_mat_get_val/ /A/ +-- +-- Returns the valuation of the matrix.+foreign import ccall "padic_mat.h padic_mat_get_val"+ padic_mat_get_val :: Ptr CPadicMat -> IO CLong++-- | /padic_mat_get_prec/ /A/ +-- +-- Returns the \(p\)-adic precision of the matrix.+foreign import ccall "padic_mat.h padic_mat_get_prec"+ padic_mat_get_prec :: Ptr CPadicMat -> IO CLong++-- | /padic_mat_nrows/ /A/ +-- +-- Returns the number of rows of the matrix \(A\).+foreign import ccall "padic_mat.h padic_mat_nrows"+ padic_mat_nrows :: Ptr CPadicMat -> IO CLong++-- | /padic_mat_ncols/ /A/ +-- +-- Returns the number of columns of the matrix \(A\).+foreign import ccall "padic_mat.h padic_mat_ncols"+ padic_mat_ncols :: Ptr CPadicMat -> IO CLong++-- Memory management -----------------------------------------------------------++-- | /padic_mat_init/ /A/ /r/ /c/ +-- +-- Initialises the matrix \(A\) as a zero matrix with the specified numbers+-- of rows and columns and precision @PADIC_DEFAULT_PREC@.+foreign import ccall "padic_mat.h padic_mat_init"+ padic_mat_init :: Ptr CPadicMat -> CLong -> CLong -> CLong -> IO ()++-- | /padic_mat_init2/ /A/ /r/ /c/ /prec/ +-- +-- Initialises the matrix \(A\) as a zero matrix with the specified numbers+-- of rows and columns and the given precision.+foreign import ccall "padic_mat.h padic_mat_init2"+ padic_mat_init2 :: Ptr CPadicMat -> CLong -> CLong -> CLong -> IO ()++-- | /padic_mat_clear/ /A/ +-- +-- Clears the matrix \(A\).+foreign import ccall "padic_mat.h padic_mat_clear"+ padic_mat_clear :: Ptr CPadicMat -> IO ()++foreign import ccall "padic_mat.h &padic_mat_clear"+ p_padic_mat_clear :: FunPtr (Ptr CPadicMat -> IO ())++-- | /_padic_mat_canonicalise/ /A/ /ctx/ +-- +-- Ensures that the matrix \(A\) is in canonical form.+foreign import ccall "padic_mat.h _padic_mat_canonicalise"+ _padic_mat_canonicalise :: Ptr CPadicMat -> Ptr CPadicCtx -> IO ()++-- | /_padic_mat_reduce/ /A/ /ctx/ +-- +-- Ensures that the matrix \(A\) is reduced modulo \(p^N\), assuming that+-- it is in canonical form already.+foreign import ccall "padic_mat.h _padic_mat_reduce"+ _padic_mat_reduce :: Ptr CPadicMat -> Ptr CPadicCtx -> IO ()++-- | /padic_mat_reduce/ /A/ /ctx/ +-- +-- Ensures that the matrix \(A\) is reduced modulo \(p^N\), without+-- assuming that it is necessarily in canonical form.+foreign import ccall "padic_mat.h padic_mat_reduce"+ padic_mat_reduce :: Ptr CPadicMat -> Ptr CPadicCtx -> IO ()++-- | /padic_mat_is_empty/ /A/ +-- +-- Returns whether the matrix \(A\) is empty, that is, whether it has zero+-- rows or zero columns.+foreign import ccall "padic_mat.h padic_mat_is_empty"+ padic_mat_is_empty :: Ptr CPadicMat -> IO CInt++-- | /padic_mat_is_square/ /A/ +-- +-- Returns whether the matrix \(A\) is square.+foreign import ccall "padic_mat.h padic_mat_is_square"+ padic_mat_is_square :: Ptr CPadicMat -> IO CInt++-- | /padic_mat_is_canonical/ /A/ /p/ +-- +-- Returns whether the matrix \(A\) is in canonical form.+foreign import ccall "padic_mat.h padic_mat_is_canonical"+ padic_mat_is_canonical :: Ptr CPadicMat -> Ptr CFmpz -> IO CInt++-- Basic assignment ------------------------------------------------------------++-- | /padic_mat_set/ /B/ /A/ +-- +-- Sets \(B\) to a copy of \(A\), respecting the precision of \(B\).+foreign import ccall "padic_mat.h padic_mat_set"+ padic_mat_set :: Ptr CPadicMat -> Ptr CPadicMat -> IO ()++-- | /padic_mat_swap/ /A/ /B/ +-- +-- Swaps the two matrices \(A\) and \(B\). This is done efficiently by+-- swapping pointers.+foreign import ccall "padic_mat.h padic_mat_swap"+ padic_mat_swap :: Ptr CPadicMat -> Ptr CPadicMat -> IO ()++-- | /padic_mat_swap_entrywise/ /mat1/ /mat2/ +-- +-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "padic_mat.h padic_mat_swap_entrywise"+ padic_mat_swap_entrywise :: Ptr CPadicMat -> Ptr CPadicMat -> IO ()++-- | /padic_mat_zero/ /A/ +-- +-- Sets the matrix \(A\) to zero.+foreign import ccall "padic_mat.h padic_mat_zero"+ padic_mat_zero :: Ptr CPadicMat -> IO ()++-- | /padic_mat_one/ /A/ +-- +-- Sets the matrix \(A\) to the identity matrix. If the precision is+-- negative then the matrix will be the zero matrix.+foreign import ccall "padic_mat.h padic_mat_one"+ padic_mat_one :: Ptr CPadicMat -> IO ()++-- Conversions -----------------------------------------------------------------++-- | /padic_mat_set_fmpq_mat/ /B/ /A/ /ctx/ +-- +-- Sets the \(p\)-adic matrix \(B\) to the rational matrix \(A\), reduced+-- according to the given context.+foreign import ccall "padic_mat.h padic_mat_set_fmpq_mat"+ padic_mat_set_fmpq_mat :: Ptr CPadicMat -> Ptr CFmpqMat -> Ptr CPadicCtx -> IO ()++-- | /padic_mat_get_fmpq_mat/ /B/ /A/ /ctx/ +-- +-- Sets the rational matrix \(B\) to the \(p\)-adic matrices \(A\); no+-- reduction takes place.+foreign import ccall "padic_mat.h padic_mat_get_fmpq_mat"+ padic_mat_get_fmpq_mat :: Ptr CFmpqMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()++-- Entries ---------------------------------------------------------------------++-- Because of the choice of the data structure, representing the matrix as+-- \(p^v M\), setting an entry of the matrix might lead to changes in all+-- entries in the matrix \(M\). Also, a specific entry is not readily+-- available as a \(p\)-adic number. Thus, there are separate functions+-- available for getting and setting entries.+--+-- | /padic_mat_get_entry_padic/ /rop/ /op/ /i/ /j/ /ctx/ +-- +-- Sets @rop@ to the entry in position \((i, j)\) in the matrix @op@.+foreign import ccall "padic_mat.h padic_mat_get_entry_padic"+ padic_mat_get_entry_padic :: Ptr CPadic -> Ptr CPadicMat -> CLong -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_mat_set_entry_padic/ /rop/ /i/ /j/ /op/ /ctx/ +-- +-- Sets the entry in position \((i, j)\) in the matrix to @rop@.+foreign import ccall "padic_mat.h padic_mat_set_entry_padic"+ padic_mat_set_entry_padic :: Ptr CPadicMat -> CLong -> CLong -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /padic_mat_equal/ /A/ /B/ +-- +-- Returns whether the two matrices \(A\) and \(B\) are equal.+foreign import ccall "padic_mat.h padic_mat_equal"+ padic_mat_equal :: Ptr CPadicMat -> Ptr CPadicMat -> IO CInt++-- | /padic_mat_is_zero/ /A/ +-- +-- Returns whether the matrix \(A\) is zero.+foreign import ccall "padic_mat.h padic_mat_is_zero"+ padic_mat_is_zero :: Ptr CPadicMat -> IO CInt++-- Input and output ------------------------------------------------------------++foreign import ccall "padic_mat.h padic_mat_get_str"+ padic_mat_get_str:: Ptr CPadicMat -> Ptr CPadicCtx -> IO CString+ +foreign import ccall "padic_mat.h padic_mat_get_str_pretty"+ padic_mat_get_str_pretty:: Ptr CPadicMat -> Ptr CPadicCtx -> IO CString+ +-- | /padic_mat_fprint/ /file/ /A/ /ctx/ +-- +-- Prints a simple representation of the matrix \(A\) to the output stream+-- @file@. The format is the number of rows, a space, the number of+-- columns, two spaces, followed by a list of all the entries, one row+-- after the other.+-- +-- In the current implementation, always returns \(1\).+foreign import ccall "padic_mat.h padic_mat_fprint"+ padic_mat_fprint :: Ptr CFile -> Ptr CPadicMat -> Ptr CPadicCtx -> IO CInt++-- | /padic_mat_fprint_pretty/ /file/ /A/ /ctx/ +-- +-- Prints a /pretty/ representation of the matrix \(A\) to the output+-- stream @file@.+-- +-- In the current implementation, always returns \(1\).+foreign import ccall "padic_mat.h padic_mat_fprint_pretty"+ padic_mat_fprint_pretty :: Ptr CFile -> Ptr CPadicMat -> Ptr CPadicCtx -> IO CInt++-- | /padic_mat_print/ /file/ /A/ /ctx/ +-- +-- Prints a simple representation of the matrix \(A\) to @stdout@. The+-- format is the number of rows, a space, the number of columns, two+-- spaces, followed by a list of all the entries, one row after the+-- other.+-- +-- In the current implementation, always returns \(1\).+padic_mat_print :: Ptr CPadicMat -> Ptr CPadicCtx -> IO CInt+padic_mat_print mat ctx = printCStr (flip padic_mat_get_str ctx) mat++-- | /padic_mat_print_pretty/ /file/ /A/ /ctx/ +-- +-- Prints a /pretty/ representation of the matrix \(A\) to @stdout@.+-- +-- In the current implementation, always returns \(1\).+padic_mat_print_pretty :: Ptr CPadicMat -> Ptr CPadicCtx -> IO CInt+padic_mat_print_pretty mat ctx = printCStr (flip padic_mat_get_str_pretty ctx) mat++-- Random matrix generation ----------------------------------------------------++-- | /padic_mat_randtest/ /A/ /state/ /ctx/ +-- +-- Sets \(A\) to a random matrix.+-- +-- The valuation will be in the range \([- \lceil N/10\rceil, N)\),+-- \([N - \lceil -N/10\rceil, N)\), or \([-10, 0)\) as \(N\) is positive,+-- negative or zero.+foreign import ccall "padic_mat.h padic_mat_randtest"+ padic_mat_randtest :: Ptr CPadicMat -> Ptr CFRandState -> Ptr CPadicCtx -> IO ()++-- Transpose -------------------------------------------------------------------++-- | /padic_mat_transpose/ /B/ /A/ +-- +-- Sets \(B\) to \(A^t\).+foreign import ccall "padic_mat.h padic_mat_transpose"+ padic_mat_transpose :: Ptr CPadicMat -> Ptr CPadicMat -> IO ()++-- Addition and subtraction ----------------------------------------------------++-- | /_padic_mat_add/ /C/ /A/ /B/ /ctx/ +-- +-- Sets \(C\) to the exact sum \(A + B\), ensuring that the result is in+-- canonical form.+foreign import ccall "padic_mat.h _padic_mat_add"+ _padic_mat_add :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()++-- | /padic_mat_add/ /C/ /A/ /B/ /ctx/ +-- +-- Sets \(C\) to the sum \(A + B\) modulo \(p^N\).+foreign import ccall "padic_mat.h padic_mat_add"+ padic_mat_add :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()++-- | /_padic_mat_sub/ /C/ /A/ /B/ /ctx/ +-- +-- Sets \(C\) to the exact difference \(A - B\), ensuring that the result+-- is in canonical form.+foreign import ccall "padic_mat.h _padic_mat_sub"+ _padic_mat_sub :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()++-- | /padic_mat_sub/ /C/ /A/ /B/ /ctx/ +-- +-- Sets \(C\) to \(A - B\), ensuring that the result is reduced.+foreign import ccall "padic_mat.h padic_mat_sub"+ padic_mat_sub :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()++-- | /_padic_mat_neg/ /B/ /A/ +-- +-- Sets \(B\) to \(-A\) in canonical form.+foreign import ccall "padic_mat.h _padic_mat_neg"+ _padic_mat_neg :: Ptr CPadicMat -> Ptr CPadicMat -> IO ()++-- | /padic_mat_neg/ /B/ /A/ /ctx/ +-- +-- Sets \(B\) to \(-A\), ensuring the result is reduced.+foreign import ccall "padic_mat.h padic_mat_neg"+ padic_mat_neg :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()++-- Scalar operations -----------------------------------------------------------++-- | /_padic_mat_scalar_mul_padic/ /B/ /A/ /c/ /ctx/ +-- +-- Sets \(B\) to \(c A\), ensuring that the result is in canonical form.+foreign import ccall "padic_mat.h _padic_mat_scalar_mul_padic"+ _padic_mat_scalar_mul_padic :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_mat_scalar_mul_padic/ /B/ /A/ /c/ /ctx/ +-- +-- Sets \(B\) to \(c A\), ensuring that the result is reduced.+foreign import ccall "padic_mat.h padic_mat_scalar_mul_padic"+ padic_mat_scalar_mul_padic :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /_padic_mat_scalar_mul_fmpz/ /B/ /A/ /c/ /ctx/ +-- +-- Sets \(B\) to \(c A\), ensuring that the result is in canonical form.+foreign import ccall "padic_mat.h _padic_mat_scalar_mul_fmpz"+ _padic_mat_scalar_mul_fmpz :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CFmpz -> Ptr CPadicCtx -> IO ()++-- | /padic_mat_scalar_mul_fmpz/ /B/ /A/ /c/ /ctx/ +-- +-- Sets \(B\) to \(c A\), ensuring that the result is reduced.+foreign import ccall "padic_mat.h padic_mat_scalar_mul_fmpz"+ padic_mat_scalar_mul_fmpz :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CFmpz -> Ptr CPadicCtx -> IO ()++-- | /padic_mat_scalar_div_fmpz/ /B/ /A/ /c/ /ctx/ +-- +-- Sets \(B\) to \(c^{-1} A\), assuming that \(c \neq 0\). Ensures that the+-- result \(B\) is reduced.+foreign import ccall "padic_mat.h padic_mat_scalar_div_fmpz"+ padic_mat_scalar_div_fmpz :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CFmpz -> Ptr CPadicCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /padic_mat_mul/ /C/ /A/ /B/ /ctx/ +-- +-- Sets \(C\) to the product \(A B\) of the two matrices \(A\) and \(B\),+-- ensuring that \(C\) is reduced.+foreign import ccall "padic_mat.h padic_mat_mul"+ padic_mat_mul :: Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicMat -> Ptr CPadicCtx -> IO ()+
+ src/Data/Number/Flint/Padic/Poly.hs view
@@ -0,0 +1,25 @@+{-|+module : Data.Number.Flint.Padic.Poly+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++= Polynomials over p-adics++ We represent a polynomial+ in \(\mathbb{Q}_p[x]\) as a product \(p^v f(x)\), where \(p\) is a+ prime number, \(v \in \mathbb{Z}\) and \(f(x) \in \mathbb{Z}[x]\). As a+ data structure, we call this polynomial /normalised/ if the+ polynomial \(f(x)\) is /normalised/, that is, if the top+ coefficient is non-zero. We say this polynomial is in + /canonical form/ if one of the coefficients of \(f(x)\) is a \(p\)-adic+ unit. If \(f(x)\) is the zero polynomial, we require that \(v =+ 0\). We say this polynomial is /reduced/ modulo \(p^N\) if it is+ canonical form and if all coefficients lie in the range \([0, p^N)\).+-}++module Data.Number.Flint.Padic.Poly (+ module Data.Number.Flint.Padic.Poly.FFI,+) where++import Data.Number.Flint.Padic.Poly.FFI
+ src/Data/Number/Flint/Padic/Poly/FFI.hsc view
@@ -0,0 +1,778 @@+{-|+module : Data.Number.Flint.Padic.Poly.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Padic.Poly.FFI (+ -- * Polynomials over p-adic numbers+ PadicPoly (..)+ , CPadicPoly (..)+ , newPadicPoly+ , withPadicPoly+ , withNewPadicPoly+ -- * Memory management+ , padic_poly_init+ , padic_poly_init2+ , padic_poly_realloc+ , padic_poly_fit_length+ , _padic_poly_set_length+ , padic_poly_clear+ , _padic_poly_normalise+ , _padic_poly_canonicalise+ , padic_poly_reduce+ , padic_poly_truncate+ -- * Polynomial parameters+ , padic_poly_degree+ , padic_poly_length+ , padic_poly_val+ -- , padic_poly_prec+ -- * Randomisation+ , padic_poly_randtest+ , padic_poly_randtest_not_zero+ , padic_poly_randtest_val+ -- * Assignment and basic manipulation+ , padic_poly_set_padic+ , padic_poly_set+ , padic_poly_set_si+ , padic_poly_set_ui+ , padic_poly_set_fmpz+ , padic_poly_set_fmpq+ , padic_poly_set_fmpz_poly+ , padic_poly_set_fmpq_poly+ , padic_poly_get_fmpz_poly+ , padic_poly_get_fmpq_poly+ , padic_poly_zero+ , padic_poly_one+ , padic_poly_swap+ -- * Getting and setting coefficients+ , padic_poly_get_coeff_padic+ , padic_poly_set_coeff_padic+ -- * Comparison+ , padic_poly_equal+ , padic_poly_is_zero+ , padic_poly_is_one+ -- * Addition and subtraction+ , _padic_poly_add+ , padic_poly_add+ , _padic_poly_sub+ , padic_poly_sub+ , padic_poly_neg+ -- * Scalar multiplication+ , _padic_poly_scalar_mul_padic+ , padic_poly_scalar_mul_padic+ -- * Multiplication+ , _padic_poly_mul+ , padic_poly_mul+ -- * Powering+ , _padic_poly_pow+ , padic_poly_pow+ -- * Series inversion+ , padic_poly_inv_series+ -- * Derivative+ , _padic_poly_derivative+ , padic_poly_derivative+ -- * Shifting+ , padic_poly_shift_left+ , padic_poly_shift_right+ -- * Evaluation+ , _padic_poly_evaluate_padic+ , padic_poly_evaluate_padic+ -- * Composition+ , _padic_poly_compose+ , padic_poly_compose+ , _padic_poly_compose_pow+ , padic_poly_compose_pow+ -- * Input and output+ , padic_poly_debug+ , _padic_poly_fprint+ , padic_poly_fprint+ , _padic_poly_print+ , padic_poly_print+ , _padic_poly_fprint_pretty+ , padic_poly_fprint_pretty+ , _padic_poly_print_pretty+ , padic_poly_print_pretty+ , padic_poly_get_str_pretty+ , padic_poly_get_str+ -- * Testing+ , _padic_poly_is_canonical+) where++-- polynomials over p-adic numbers ---------------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, nullPtr, plusPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Poly+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Fmpq.Poly+import Data.Number.Flint.Padic++#include <flint/flint.h>+#include <flint/padic.h>+#include <flint/padic_poly.h>++-- padic_poly_t ----------------------------------------------------------------++data PadicPoly = PadicPoly {-# UNPACK #-} !(ForeignPtr CPadicPoly)+data CPadicPoly = CPadicPoly (Ptr CFmpz) CLong CLong CLong CLong++instance Storable CPadicPoly where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size padic_poly_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment padic_poly_t}+ peek ptr = return CPadicPoly+ `ap` (return $ castPtr ptr)+ `ap` #{peek padic_poly_struct, alloc } ptr+ `ap` #{peek padic_poly_struct, length} ptr+ `ap` #{peek padic_poly_struct, val } ptr+ `ap` #{peek padic_poly_struct, N } ptr+ poke = undefined++newPadicPoly = do+ x <- mallocForeignPtr+ withForeignPtr x padic_poly_init+ addForeignPtrFinalizer p_padic_poly_clear x+ return $ PadicPoly x++{-# INLINE withPadicPoly #-}+withPadicPoly (PadicPoly x) f = do+ withForeignPtr x $ \px -> f px >>= return . (PadicPoly x,)++{-# INLINE withNewPadicPoly #-}+withNewPadicPoly f = do+ x <- newPadicPoly+ withPadicPoly x f+ +-- Memory management -----------------------------------------------------------++-- | /padic_poly_init/ /poly/ +-- +-- Initialises @poly@ for use, setting its length to zero. The precision of+-- the polynomial is set to @PADIC_DEFAULT_PREC@. A corresponding call to+-- @padic_poly_clear@ must be made after finishing with the @padic_poly_t@+-- to free the memory used by the polynomial.+foreign import ccall "padic_poly.h padic_poly_init"+ padic_poly_init :: Ptr CPadicPoly -> IO ()++-- | /padic_poly_init2/ /poly/ /alloc/ /prec/ +-- +-- Initialises @poly@ with space for at least @alloc@ coefficients and sets+-- the length to zero. The allocated coefficients are all set to zero. The+-- precision is set to @prec@.+foreign import ccall "padic_poly.h padic_poly_init2"+ padic_poly_init2 :: Ptr CPadicPoly -> CLong -> CLong -> IO ()++-- | /padic_poly_realloc/ /poly/ /alloc/ /p/ +-- +-- Reallocates the given polynomial to have space for @alloc@ coefficients.+-- If @alloc@ is zero the polynomial is cleared and then reinitialised. If+-- the current length is greater than @alloc@ the polynomial is first+-- truncated to length @alloc@.+foreign import ccall "padic_poly.h padic_poly_realloc"+ padic_poly_realloc :: Ptr CPadicPoly -> CLong -> Ptr CFmpz -> IO ()++-- | /padic_poly_fit_length/ /poly/ /len/ +-- +-- If @len@ is greater than the number of coefficients currently allocated,+-- then the polynomial is reallocated to have space for at least @len@+-- coefficients. No data is lost when calling this function.+-- +-- The function efficiently deals with the case where @fit_length@ is+-- called many times in small increments by at least doubling the number of+-- allocated coefficients when length is larger than the number of+-- coefficients currently allocated.+foreign import ccall "padic_poly.h padic_poly_fit_length"+ padic_poly_fit_length :: Ptr CPadicPoly -> CLong -> IO ()++-- | /_padic_poly_set_length/ /poly/ /len/ +-- +-- Demotes the coefficients of @poly@ beyond @len@ and sets the length of+-- @poly@ to @len@.+-- +-- Note that if the current length is greater than @len@ the polynomial may+-- no slonger be in canonical form.+foreign import ccall "padic_poly.h _padic_poly_set_length"+ _padic_poly_set_length :: Ptr CPadicPoly -> CLong -> IO ()++-- | /padic_poly_clear/ /poly/ +-- +-- Clears the given polynomial, releasing any memory used. It must be+-- reinitialised in order to be used again.+foreign import ccall "padic_poly.h padic_poly_clear"+ padic_poly_clear :: Ptr CPadicPoly -> IO ()++foreign import ccall "padic_poly.h &padic_poly_clear"+ p_padic_poly_clear :: FunPtr (Ptr CPadicPoly -> IO ())++-- | /_padic_poly_normalise/ /poly/ +-- +-- Sets the length of @poly@ so that the top coefficient is non-zero. If+-- all coefficients are zero, the length is set to zero. This function is+-- mainly used internally, as all functions guarantee normalisation.+foreign import ccall "padic_poly.h _padic_poly_normalise"+ _padic_poly_normalise :: Ptr CPadicPoly -> IO ()++-- | /_padic_poly_canonicalise/ /poly/ /v/ /len/ /p/ +-- +-- Brings the polynomial @poly@ into canonical form, assuming that it is+-- normalised already. Does /not/ carry out any reduction.+foreign import ccall "padic_poly.h _padic_poly_canonicalise"+ _padic_poly_canonicalise :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> IO ()++-- | /padic_poly_reduce/ /poly/ /ctx/ +-- +-- Reduces the polynomial @poly@ modulo \(p^N\), assuming that it is in+-- canonical form already.+foreign import ccall "padic_poly.h padic_poly_reduce"+ padic_poly_reduce :: Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_truncate/ /poly/ /n/ /p/ +-- +-- Truncates the polynomial to length at most~\`n\`.+foreign import ccall "padic_poly.h padic_poly_truncate"+ padic_poly_truncate :: Ptr CPadicPoly -> CLong -> Ptr CFmpz -> IO ()++-- Polynomial parameters -------------------------------------------------------++-- | /padic_poly_degree/ /poly/ +-- +-- Returns the degree of the polynomial @poly@.+foreign import ccall "padic_poly.h padic_poly_degree"+ padic_poly_degree :: Ptr CPadicPoly -> IO CLong++-- | /padic_poly_length/ /poly/ +-- +-- Returns the length of the polynomial @poly@.+foreign import ccall "padic_poly.h padic_poly_length"+ padic_poly_length :: Ptr CPadicPoly -> IO CLong++-- | /padic_poly_val/ /poly/ +-- +-- Returns the valuation of the polynomial @poly@, which is defined to be+-- the minimum valuation of all its coefficients.+-- +-- The valuation of the zero polynomial is~\`0\`.+-- +-- Note that this is implemented as a macro and can be used as either a+-- @lvalue@ or a @rvalue@.+foreign import ccall "padic_poly.h padic_poly_val"+ padic_poly_val :: Ptr CPadicPoly -> IO CLong++-- | /padic_poly_prec/ /poly/ +-- +-- Returns the precision of the polynomial @poly@.+-- +-- Note that this is implemented as a macro and can be used as either a+-- @lvalue@ or a @rvalue@.+-- +-- Note that increasing the precision might require a call to+-- @padic_poly_reduce@.+-- foreign import ccall "padic_poly.h padic_poly_prec"+-- padic_poly_prec :: Ptr CPadicPoly -> IO CLong++-- Randomisation ---------------------------------------------------------------++-- | /padic_poly_randtest/ /f/ /state/ /len/ /ctx/ +-- +-- Sets \(f\) to a random polynomial of length at most @len@ with entries+-- reduced modulo \(p^N\).+foreign import ccall "padic_poly.h padic_poly_randtest"+ padic_poly_randtest :: Ptr CPadicPoly -> Ptr CFRandState -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_randtest_not_zero/ /f/ /state/ /len/ /ctx/ +-- +-- Sets \(f\) to a non-zero random polynomial of length at most @len@ with+-- entries reduced modulo \(p^N\).+foreign import ccall "padic_poly.h padic_poly_randtest_not_zero"+ padic_poly_randtest_not_zero :: Ptr CPadicPoly -> Ptr CFRandState -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_randtest_val/ /f/ /state/ /val/ /len/ /ctx/ +-- +-- Sets \(f\) to a random polynomial of length at most @len@ with at most+-- the prescribed valuation @val@ and entries reduced modulo \(p^N\).+-- +-- Specifically, we aim to set the valuation to be exactly equal to @val@,+-- but do not check for additional cancellation when creating the+-- coefficients.+foreign import ccall "padic_poly.h padic_poly_randtest_val"+ padic_poly_randtest_val :: Ptr CPadicPoly -> Ptr CFRandState -> CLong -> CLong -> Ptr CPadicCtx -> IO ()++-- Assignment and basic manipulation -------------------------------------------++-- | /padic_poly_set_padic/ /poly/ /x/ /ctx/ +-- +-- Sets the polynomial @poly@ to the \(p\)-adic number \(x\), reduced to+-- the precision of the polynomial.+foreign import ccall "padic_poly.h padic_poly_set_padic"+ padic_poly_set_padic :: Ptr CPadicPoly -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_set/ /poly1/ /poly2/ /ctx/ +-- +-- Sets the polynomial @poly1@ to the polynomial @poly2@, reduced to the+-- precision of @poly1@.+foreign import ccall "padic_poly.h padic_poly_set"+ padic_poly_set :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_set_si/ /poly/ /x/ /ctx/ +-- +-- Sets the polynomial @poly@ to the @signed slong@ integer \(x\) reduced+-- to the precision of the polynomial.+foreign import ccall "padic_poly.h padic_poly_set_si"+ padic_poly_set_si :: Ptr CPadicPoly -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_set_ui/ /poly/ /x/ /ctx/ +-- +-- Sets the polynomial @poly@ to the @unsigned slong@ integer \(x\) reduced+-- to the precision of the polynomial.+foreign import ccall "padic_poly.h padic_poly_set_ui"+ padic_poly_set_ui :: Ptr CPadicPoly -> CULong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_set_fmpz/ /poly/ /x/ /ctx/ +-- +-- Sets the polynomial @poly@ to the integer \(x\) reduced to the precision+-- of the polynomial.+foreign import ccall "padic_poly.h padic_poly_set_fmpz"+ padic_poly_set_fmpz :: Ptr CPadicPoly -> Ptr CFmpz -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_set_fmpq/ /poly/ /x/ /ctx/ +-- +-- Sets the polynomial @poly@ to the value of the rational \(x\), reduced+-- to the precision of the polynomial.+foreign import ccall "padic_poly.h padic_poly_set_fmpq"+ padic_poly_set_fmpq :: Ptr CPadicPoly -> Ptr CFmpq -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_set_fmpz_poly/ /rop/ /op/ /ctx/ +-- +-- Sets the polynomial @rop@ to the integer polynomial @op@ reduced to the+-- precision of the polynomial.+foreign import ccall "padic_poly.h padic_poly_set_fmpz_poly"+ padic_poly_set_fmpz_poly :: Ptr CPadicPoly -> Ptr CFmpzPoly -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_set_fmpq_poly/ /rop/ /op/ /ctx/ +-- +-- Sets the polynomial @rop@ to the value of the rational polynomial @op@,+-- reduced to the precision of the polynomial.+foreign import ccall "padic_poly.h padic_poly_set_fmpq_poly"+ padic_poly_set_fmpq_poly :: Ptr CPadicPoly -> Ptr CFmpqPoly -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_get_fmpz_poly/ /rop/ /op/ /ctx/ +-- +-- Sets the integer polynomial @rop@ to the value of the \(p\)-adic+-- polynomial @op@ and returns \(1\) if the polynomial is \(p\)-adically+-- integral. Otherwise, returns \(0\).+foreign import ccall "padic_poly.h padic_poly_get_fmpz_poly"+ padic_poly_get_fmpz_poly :: Ptr CFmpzPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt++-- | /padic_poly_get_fmpq_poly/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the rational polynomial corresponding to the \(p\)-adic+-- polynomial @op@.+foreign import ccall "padic_poly.h padic_poly_get_fmpq_poly"+ padic_poly_get_fmpq_poly :: Ptr CFmpqPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_zero/ /poly/ +-- +-- Sets @poly@ to the zero polynomial.+foreign import ccall "padic_poly.h padic_poly_zero"+ padic_poly_zero :: Ptr CPadicPoly -> IO ()++-- | /padic_poly_one/ /poly/ +-- +-- Sets @poly@ to the constant polynomial \(1\), reduced to the precision+-- of the polynomial.+foreign import ccall "padic_poly.h padic_poly_one"+ padic_poly_one :: Ptr CPadicPoly -> IO ()++-- | /padic_poly_swap/ /poly1/ /poly2/ +-- +-- Swaps the two polynomials @poly1@ and @poly2@, including their+-- precisions.+-- +-- This is done efficiently by swapping pointers.+foreign import ccall "padic_poly.h padic_poly_swap"+ padic_poly_swap :: Ptr CPadicPoly -> Ptr CPadicPoly -> IO ()++-- Getting and setting coefficients --------------------------------------------++-- | /padic_poly_get_coeff_padic/ /c/ /poly/ /n/ /ctx/ +-- +-- Sets \(c\) to the coefficient of \(x^n\) in the polynomial, reduced+-- modulo the precision of \(c\).+foreign import ccall "padic_poly.h padic_poly_get_coeff_padic"+ padic_poly_get_coeff_padic :: Ptr CPadic -> Ptr CPadicPoly -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_set_coeff_padic/ /f/ /n/ /c/ /ctx/ +-- +-- Sets the coefficient of \(x^n\) in the polynomial \(f\) to \(c\),+-- reduced to the precision of the polynomial \(f\).+-- +-- Note that this operation can take linear time in the length of the+-- polynomial.+foreign import ccall "padic_poly.h padic_poly_set_coeff_padic"+ padic_poly_set_coeff_padic :: Ptr CPadicPoly -> CLong -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /padic_poly_equal/ /poly1/ /poly2/ +-- +-- Returns whether the two polynomials @poly1@ and @poly2@ are equal.+foreign import ccall "padic_poly.h padic_poly_equal"+ padic_poly_equal :: Ptr CPadicPoly -> Ptr CPadicPoly -> IO CInt++-- | /padic_poly_is_zero/ /poly/ +-- +-- Returns whether the polynomial @poly@ is the zero polynomial.+foreign import ccall "padic_poly.h padic_poly_is_zero"+ padic_poly_is_zero :: Ptr CPadicPoly -> IO CInt++-- | /padic_poly_is_one/ /poly/ /ctx/ +-- +-- Returns whether the polynomial @poly@ is equal to the constant+-- polynomial~\`1\`, taking the precision of the polynomial into account.+foreign import ccall "padic_poly.h padic_poly_is_one"+ padic_poly_is_one :: Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /_padic_poly_add/ /rop/ /rval/ /N/ /op1/ /val1/ /len1/ /N1/ /op2/ /val2/ /len2/ /N2/ /ctx/ +-- +-- Sets @(rop, *val, FLINT_MAX(len1, len2)@ to the sum of+-- @(op1, val1, len1)@ and @(op2, val2, len2)@.+-- +-- Assumes that the input is reduced and guarantees that this is also the+-- case for the output.+-- +-- Assumes that \(\min\{v_1, v_2\} < N\).+-- +-- Supports aliasing between the output and input arguments.+foreign import ccall "padic_poly.h _padic_poly_add"+ _padic_poly_add :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_add/ /f/ /g/ /h/ /ctx/ +-- +-- Sets \(f\) to the sum \(g + h\).+foreign import ccall "padic_poly.h padic_poly_add"+ padic_poly_add :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()++-- | /_padic_poly_sub/ /rop/ /rval/ /op1/ /val1/ /len1/ /op2/ /val2/ /len2/ /ctx/ +-- +-- Sets @(rop, *val, FLINT_MAX(len1, len2)@ to the difference of+-- @(op1, val1, len1)@ and @(op2, val2, len2)@.+-- +-- Assumes that the input is reduced and guarantees that this is also the+-- case for the output.+-- +-- Assumes that \(\min\{v_1, v_2\} < N\).+-- +-- Support aliasing between the output and input arguments.+foreign import ccall "padic_poly.h _padic_poly_sub"+ _padic_poly_sub :: Ptr CFmpz -> Ptr CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_sub/ /f/ /g/ /h/ /ctx/ +-- +-- Sets \(f\) to the difference \(g - h\).+foreign import ccall "padic_poly.h padic_poly_sub"+ padic_poly_sub :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_neg/ /f/ /g/ /ctx/ +-- +-- Sets \(f\) to \(-g\).+foreign import ccall "padic_poly.h padic_poly_neg"+ padic_poly_neg :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()++-- Scalar multiplication -------------------------------------------------------++-- | /_padic_poly_scalar_mul_padic/ /rop/ /rval/ /op/ /val/ /len/ /c/ /ctx/ +-- +-- Sets @(rop, *rval, len)@ to @(op, val, len)@ multiplied by the scalar+-- \(c\).+-- +-- The result will only be correctly reduced if the polynomial is non-zero.+-- Otherwise, the array @(rop, len)@ will be set to zero but the valuation+-- @*rval@ might be wrong.+foreign import ccall "padic_poly.h _padic_poly_scalar_mul_padic"+ _padic_poly_scalar_mul_padic :: Ptr CFmpz -> Ptr CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_scalar_mul_padic/ /rop/ /op/ /c/ /ctx/ +-- +-- Sets the polynomial @rop@ to the product of the polynomial @op@ and the+-- \(p\)-adic number \(c\), reducing the result modulo \(p^N\).+foreign import ccall "padic_poly.h padic_poly_scalar_mul_padic"+ padic_poly_scalar_mul_padic :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- Multiplication --------------------------------------------------------------++-- | /_padic_poly_mul/ /rop/ /rval/ /N/ /op1/ /val1/ /len1/ /op2/ /val2/ /len2/ /ctx/ +-- +-- Sets @(rop, *rval, len1 + len2 - 1)@ to the product of+-- @(op1, val1, len1)@ and @(op2, val2, len2)@.+-- +-- Assumes that the resulting valuation @*rval@, which is the sum of the+-- valuations @val1@ and @val2@, is less than the precision~\`N\` of the+-- context.+-- +-- Assumes that @len1 >= len2 > 0@.+foreign import ccall "padic_poly.h _padic_poly_mul"+ _padic_poly_mul :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_mul/ /res/ /poly1/ /poly2/ /ctx/ +-- +-- Sets the polynomial @res@ to the product of the two polynomials @poly1@+-- and @poly2@, reduced modulo \(p^N\).+foreign import ccall "padic_poly.h padic_poly_mul"+ padic_poly_mul :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()++-- Powering --------------------------------------------------------------------++-- | /_padic_poly_pow/ /rop/ /rval/ /N/ /op/ /val/ /len/ /e/ /ctx/ +-- +-- Sets the polynomial @(rop, *rval, e (len - 1) + 1)@ to the polynomial+-- @(op, val, len)@ raised to the power~\`e\`.+-- +-- Assumes that \(e > 1\) and @len > 0@.+-- +-- Does not support aliasing between the input and output arguments.+foreign import ccall "padic_poly.h _padic_poly_pow"+ _padic_poly_pow :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> CULong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_pow/ /rop/ /op/ /e/ /ctx/ +-- +-- Sets the polynomial @rop@ to the polynomial @op@ raised to the+-- power~\`e\`, reduced to the precision in @rop@.+-- +-- In the special case \(e = 0\), sets @rop@ to the constant polynomial one+-- reduced to the precision of @rop@. Also note that when \(e = 1\), this+-- operation sets @rop@ to @op@ and then reduces @rop@.+-- +-- When the valuation of the input polynomial is negative, this results in+-- a loss of \(p\)-adic precision. Suppose that the input polynomial is+-- given to precision~\`N\` and has valuation~\`v \< 0\`. The result then+-- has valuation \(e v < 0\) but is only correct to precision+-- \(N + (e - 1) v\).+foreign import ccall "padic_poly.h padic_poly_pow"+ padic_poly_pow :: Ptr CPadicPoly -> Ptr CPadicPoly -> CULong -> Ptr CPadicCtx -> IO ()++-- Series inversion ------------------------------------------------------------++-- | /padic_poly_inv_series/ /g/ /f/ /n/ /ctx/ +-- +-- Computes the power series inverse \(g\) of \(f\) modulo \(X^n\), where+-- \(n \geq 1\).+-- +-- Given the polynomial \(f \in \mathbf{Q}[X] \subset \mathbf{Q}_p[X]\),+-- there exists a unique polynomial \(f^{-1} \in \mathbf{Q}[X]\) such that+-- \(f f^{-1} = 1\) modulo \(X^n\). This function sets \(g\) to \(f^{-1}\)+-- reduced modulo \(p^N\).+-- +-- Assumes that the constant coefficient of \(f\) is non-zero.+-- +-- Moreover, assumes that the valuation of the constant coefficient of+-- \(f\) is minimal among the coefficients of \(f\).+-- +-- Note that the result \(g\) is zero if and only if+-- \(- \operatorname{ord}_p(f) \geq N\).+foreign import ccall "padic_poly.h padic_poly_inv_series"+ padic_poly_inv_series :: Ptr CPadicPoly -> Ptr CPadicPoly -> CLong -> Ptr CPadicCtx -> IO ()++-- Derivative ------------------------------------------------------------------++-- | /_padic_poly_derivative/ /rop/ /rval/ /N/ /op/ /val/ /len/ /ctx/ +-- +-- Sets @(rop, rval)@ to the derivative of @(op, val)@ reduced modulo+-- \(p^N\).+-- +-- Supports aliasing of the input and the output parameters.+foreign import ccall "padic_poly.h _padic_poly_derivative"+ _padic_poly_derivative :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_derivative/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the derivative of @op@, reducing the result modulo the+-- precision of @rop@.+foreign import ccall "padic_poly.h padic_poly_derivative"+ padic_poly_derivative :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()++-- Shifting --------------------------------------------------------------------++-- | /padic_poly_shift_left/ /rop/ /op/ /n/ /ctx/ +-- +-- Notationally, sets the polynomial @rop@ to the polynomial @op@+-- multiplied by \(x^n\), where \(n \geq 0\), and reduces the result.+foreign import ccall "padic_poly.h padic_poly_shift_left"+ padic_poly_shift_left :: Ptr CPadicPoly -> Ptr CPadicPoly -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_shift_right/ /rop/ /op/ /n/ +-- +-- Notationally, sets the polynomial @rop@ to the polynomial @op@ after+-- floor division by \(x^n\), where \(n \geq 0\), ensuring the result is+-- reduced.+foreign import ccall "padic_poly.h padic_poly_shift_right"+ padic_poly_shift_right :: Ptr CPadicPoly -> Ptr CPadicPoly -> CLong -> IO ()++-- Evaluation ------------------------------------------------------------------++foreign import ccall "padic_poly.h _padic_poly_evaluate_padic"+ _padic_poly_evaluate_padic :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> CLong -> Ptr CPadicCtx -> IO ()++-- | /_padic_poly_evaluate_padic/ /u/ /v/ /N/ /poly/ /val/ /len/ /a/ /b/ /ctx/ +-- +-- Sets the \(p\)-adic number @y@ to @poly@ evaluated at \(a\), reduced in+-- the given context.+-- +-- Suppose that the polynomial can be written as \(F(X) = p^w f(X)\) with+-- \(\operatorname{ord}_p(f) = 1\), that \(\operatorname{ord}_p(a) = b\)+-- and that both are defined to precision~\`N\`. Then \(f\) is defined to+-- precision \(N-w\) and so \(f(a)\) is defined to precision \(N-w\) when+-- \(a\) is integral and \(N-w+(n-1)b\) when \(b < 0\), where+-- \(n = \deg(f)\). Thus, \(y = F(a)\) is defined to precision \(N\) when+-- \(a\) is integral and \(N+(n-1)b\) when \(b < 0\).++foreign import ccall "flint/padic_poly.h padic_poly_evaluate_padic"+ padic_poly_evaluate_padic :: Ptr CPadic -> Ptr CPadicPoly -> Ptr CPadic -> Ptr CPadicCtx -> IO ()++-- Composition -----------------------------------------------------------------++-- | /_padic_poly_compose/ /rop/ /rval/ /N/ /op1/ /val1/ /len1/ /op2/ /val2/ /len2/ /ctx/ +-- +-- Sets @(rop, *rval, (len1-1)*(len2-1)+1)@ to the composition of the two+-- input polynomials, reducing the result modulo \(p^N\).+-- +-- Assumes that @len1@ is non-zero.+-- +-- Does not support aliasing.+foreign import ccall "padic_poly.h _padic_poly_compose"+ _padic_poly_compose :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_compose/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the composition of @op1@ and @op2@, reducing the result in+-- the given context.+-- +-- To be clear about the order of composition, let \(f(X)\) and \(g(X)\)+-- denote the polynomials @op1@ and @op2@, respectively. Then @rop@ is set+-- to \(f(g(X))\).+foreign import ccall "padic_poly.h padic_poly_compose"+ padic_poly_compose :: Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO ()++-- | /_padic_poly_compose_pow/ /rop/ /rval/ /N/ /op/ /val/ /len/ /k/ /ctx/ +-- +-- Sets @(rop, *rval, (len - 1)*k + 1)@ to the composition of+-- @(op, val, len)@ and the monomial \(x^k\), where \(k \geq 1\).+-- +-- Assumes that @len@ is positive.+-- +-- Supports aliasing between the input and output polynomials.+foreign import ccall "padic_poly.h _padic_poly_compose_pow"+ _padic_poly_compose_pow :: Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> CLong -> CLong -> Ptr CPadicCtx -> IO ()++-- | /padic_poly_compose_pow/ /rop/ /op/ /k/ /ctx/ +-- +-- Sets @rop@ to the composition of @op@ and the monomial \(x^k\), where+-- \(k \geq 1\).+-- +-- Note that no reduction takes place.+foreign import ccall "padic_poly.h padic_poly_compose_pow"+ padic_poly_compose_pow :: Ptr CPadicPoly -> Ptr CPadicPoly -> CLong -> Ptr CPadicCtx -> IO ()++-- Input and output ------------------------------------------------------------++-- | /padic_poly_debug/ /poly/ +-- +-- Prints the data defining the \(p\)-adic polynomial @poly@ in a simple+-- format useful for debugging purposes.+-- +-- In the current implementation, always returns \(1\).+foreign import ccall "padic_poly.h padic_poly_debug"+ padic_poly_debug :: Ptr CPadicPoly -> IO CInt++-- | /_padic_poly_fprint/ /file/ /poly/ /val/ /len/ /ctx/ +-- +-- Prints a simple representation of the polynomial @poly@ to the stream+-- @file@.+-- +-- A non-zero polynomial is represented by the number of coefficients, two+-- spaces, followed by a list of the coefficients, which are printed in a+-- way depending on the print mode,+-- +-- In the @PADIC_TERSE@ mode, the coefficients are printed as rational+-- numbers.+-- +-- The @PADIC_SERIES@ mode is currently not supported and will raise an+-- abort signal.+-- +-- In the @PADIC_VAL_UNIT@ mode, the coefficients are printed in the form+-- \(p^v u\).+-- +-- The zero polynomial is represented by @\"0\"@.+-- +-- In the current implementation, always returns \(1\).+foreign import ccall "padic_poly.h _padic_poly_fprint"+ _padic_poly_fprint :: Ptr CFile -> Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO CInt++foreign import ccall "flint/padic_poly.h padic_poly_fprint"+ padic_poly_fprint :: Ptr CFile -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt++-- | /_padic_poly_print/ /poly/ /val/ /len/ /ctx/ +-- +-- Prints a simple representation of the polynomial @poly@ to @stdout@.+-- +-- In the current implementation, always returns \(1\).+foreign import ccall "padic_poly.h _padic_poly_print"+ _padic_poly_print :: Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO CInt++padic_poly_print :: Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt+padic_poly_print poly ctx = do+ cs <- padic_poly_get_str nullPtr poly ctx+ s <- peekCString cs+ free cs+ putStr s+ return (1 :: CInt)++foreign import ccall "padic_poly.h _padic_poly_fprint_pretty"+ _padic_poly_fprint_pretty :: Ptr CFile -> Ptr CFmpz -> CLong -> CLong -> CString -> Ptr CPadicCtx -> IO CInt++foreign import ccall "flint/padic_poly.h _padic_poly_print_pretty"+ _padic_poly_print_pretty :: Ptr CFmpz -> CLong -> CLong -> CString -> Ptr CPadicCtx -> IO CInt++foreign import ccall "flint/padic_poly.h padic_poly_fprint_pretty"+ padic_poly_fprint_pretty :: Ptr CFile -> Ptr CPadicPoly -> CString -> Ptr CPadicCtx -> IO CInt++padic_poly_print_pretty :: Ptr CPadicPoly -> CString -> Ptr CPadicCtx -> IO CInt+padic_poly_print_pretty poly var ctx = do+ cs <- padic_poly_get_str_pretty poly var ctx+ s <- peekCString cs+ free cs+ putStr s+ return (1 :: CInt)+++foreign import ccall "padic_poly_get_str"+ padic_poly_get_str :: CString -> Ptr CPadicPoly -> Ptr CPadicCtx -> IO CString+ +foreign import ccall "padic_poly_get_str_pretty"+ padic_poly_get_str_pretty :: Ptr CPadicPoly -> CString -> Ptr CPadicCtx -> IO CString++-- Testing ---------------------------------------------------------------------++foreign import ccall "padic_poly.h _padic_poly_is_canonical"+ _padic_poly_is_canonical :: Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO CInt++foreign import ccall "flint/padic_poly.h padic_poly_is_canonical"+ padic_poly_is_canonical :: Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt ++foreign import ccall "flint/padic_poly.h _padic_poly_is_reduced"+ _padic_poly_is_reduced :: Ptr CFmpz -> CLong -> CLong -> Ptr CPadicCtx -> IO CInt++foreign import ccall "flint/padic_poly.h padic_poly_is_reduced"+ padic_poly_is_reduced :: Ptr CPadicPoly -> Ptr CPadicCtx -> IO CInt
+ src/Data/Number/Flint/Partitions.hs view
@@ -0,0 +1,28 @@+{-|+module : Data.Number.Flint.Partitions+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++This module implements the asymptotically fast algorithm for evaluating+the integer partition function \(p(n)\) described in < [Joh2012]>. The+idea is to evaluate a truncation of the Hardy-Ramanujan-Rademacher+series using tight precision estimates, and symbolically factoring the+occurring exponential sums.++An implementation based on floating-point arithmetic can also be found+in FLINT. That version relies on some numerical subroutines that have+not been proved correct.++The implementation provided here uses ball arithmetic throughout to+guarantee a correct error bound for the numerical approximation +of \(p(n)\). Optionally, hardware double arithmetic can be used for+low-precision terms. This gives a significant speedup for +small (e.g.\(n < 10^6\) ).+-}+module Data.Number.Flint.Partitions (+ module Data.Number.Flint.Partitions.FFI+) where++import Data.Number.Flint.Partitions.FFI+
+ src/Data/Number/Flint/Partitions/FFI.hsc view
@@ -0,0 +1,102 @@+{-|+module : Data.Number.Flint.Partitions.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Partitions.FFI (+ -- * Computation of the partition function+ partitions_rademacher_bound+ , partitions_hrr_sum_arb+ , partitions_fmpz_fmpz+ , partitions_fmpz_ui+ -- , partitions_fmpz_ui_using_doubles+ , partitions_leading_fmpz+) where ++-- Computation of the partition function ---------------------------------------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types++import Data.Number.Flint.Fmpz++import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Acb.Types++--------------------------------------------------------------------------------++-- | /partitions_rademacher_bound/ /b/ /n/ /N/ +-- +-- Sets \(b\) to an upper bound for+-- +-- \[M(n,N) = \frac{44 \pi^2}{225 \sqrt 3} N^{-1/2}+-- + \frac{\pi \sqrt{2}}{75} \left( \frac{N}{n-1} \right)^{1/2}+-- \sinh\left(\frac{\pi}{N} \sqrt{\frac{2n}{3}}\right).\]+-- +-- This formula gives an upper bound for the truncation error in the+-- Hardy-Ramanujan-Rademacher formula when the series is taken up to the+-- term \(t(n,N)\) inclusive.+foreign import ccall "partitions.h partitions_rademacher_bound"+ partitions_rademacher_bound :: Ptr CArf -> Ptr CFmpz -> CULong -> IO ()++-- | /partitions_hrr_sum_arb/ /x/ /n/ /N0/ /N/ /use_doubles/ +-- +-- Evaluates the partial sum \(\sum_{k=N_0}^N t(n,k)\) of the+-- Hardy-Ramanujan-Rademacher series.+-- +-- If /use_doubles/ is nonzero, doubles and the system\'s standard library+-- math functions are used to evaluate the smallest terms. This+-- significantly speeds up evaluation for small \(n\) (e.g. \(n < 10^6\)),+-- and gives a small speed improvement for larger \(n\), but the result is+-- not guaranteed to be correct. In practice, the error is estimated very+-- conservatively, and unless the system\'s standard library is broken, use+-- of doubles can be considered safe. Setting /use_doubles/ to zero gives a+-- fully guaranteed bound.+foreign import ccall "partitions.h partitions_hrr_sum_arb"+ partitions_hrr_sum_arb :: Ptr CArb -> Ptr CFmpz -> CLong -> CLong -> CInt -> IO ()++-- | /partitions_fmpz_fmpz/ /p/ /n/ /use_doubles/ +-- +-- Computes the partition function \(p(n)\) using the+-- Hardy-Ramanujan-Rademacher formula. This function computes a numerical+-- ball containing \(p(n)\) and verifies that the ball contains a unique+-- integer.+-- +-- If /n/ is sufficiently large and a number of threads greater than 1 has+-- been selected with @flint_set_num_threads()@, the computation time will+-- be reduced by using two threads.+-- +-- See @partitions_hrr_sum_arb@ for an explanation of the /use_doubles/+-- option.+foreign import ccall "partitions.h partitions_fmpz_fmpz"+ partitions_fmpz_fmpz :: Ptr CFmpz -> Ptr CFmpz -> CInt -> IO ()++-- | /partitions_fmpz_ui/ /p/ /n/ +-- +-- Computes the partition function \(p(n)\) using the+-- Hardy-Ramanujan-Rademacher formula. This function computes a numerical+-- ball containing \(p(n)\) and verifies that the ball contains a unique+-- integer.+foreign import ccall "partitions.h partitions_fmpz_ui"+ partitions_fmpz_ui :: Ptr CFmpz -> CULong -> IO ()++-- -- | /partitions_fmpz_ui_using_doubles/ /p/ /n/ +-- -- +-- -- Computes the partition function \(p(n)\), enabling the use of doubles+-- -- internally. This significantly speeds up evaluation for small \(n\)+-- -- (e.g. \(n < 10^6\)), but the error bounds are not certified (see remarks+-- -- for @partitions_hrr_sum_arb@).+-- foreign import ccall "partitions.h partitions_fmpz_ui_using_doubles"+-- partitions_fmpz_ui_using_doubles :: Ptr CFmpz -> CULong -> IO ()++-- | /partitions_leading_fmpz/ /res/ /n/ /prec/ +-- +-- Sets /res/ to the leading term in the Hardy-Ramanujan series for+-- \(p(n)\) (without Rademacher\'s correction of this term, which is+-- vanishingly small when \(n\) is large), that is,+-- \(\sqrt{12} (1-1/t) e^t / (24n-1)\) where \(t = \pi \sqrt{24n-1} / 6\).+foreign import ccall "partitions.h partitions_leading_fmpz"+ partitions_leading_fmpz :: Ptr CArb -> Ptr CFmpz -> CLong -> IO ()+
+ src/Data/Number/Flint/QSieve.hs view
@@ -0,0 +1,13 @@+{-|+module : Data.Number.Flint.QSieve+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.QSieve (+ module Data.Number.Flint.QSieve.FFI+) where++import Data.Number.Flint.QSieve.FFI+
+ src/Data/Number/Flint/QSieve/FFI.hsc view
@@ -0,0 +1,356 @@+{-|+module : Data.Number.Flint.QSieve.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.QSieve.FFI (+ -- * Quadratic sieve+ Qs (..)+ , CQs()+ , newQs+ , withQs+ -- *+ , qsieve_knuth_schroeppel+ , qsieve_primes_init+ , qsieve_primes_increment+ , qsieve_init_A+ , qsieve_next_A+ --, qsieve_compute_pre_data+ , qsieve_init_poly_first+ , qsieve_init_poly_next+ , qsieve_compute_C+ , qsieve_do_sieving+ , qsieve_do_sieving2+ , qsieve_evaluate_candidate+ , qsieve_evaluate_sieve+ , qsieve_collect_relations+ , qsieve_write_to_file+ , qsieve_get_table_entry+ , qsieve_add_to_hashtable+ , qsieve_parse_relation+ , qsieve_merge_relation+ , qsieve_compare_relation+ , qsieve_remove_duplicates+ --, qsieve_insert_relation2+ , qsieve_process_relation+ , qsieve_factor+) where++-- Quadratic sieve -------------------------------------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Factor++#include <flint/flint.h>+#include <flint/fmpz.h>+#include <flint/qsieve.h>++-- qs_t ------------------------------------------------------------------------++data Qs = Qs {-# UNPACK #-} !(ForeignPtr CQs)+type CQs = CFlint Qs++instance Storable CQs where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size qs_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment qs_t}+ peek = undefined+ poke = undefined++newQs n = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x ->+ withFmpz n $ \n -> do+ qsieve_init x n+ addForeignPtrFinalizer p_qsieve_clear x+ return $ Qs x++{-# INLINE withQs #-}+withQs (Qs x) f = do+ withForeignPtr x $ \px -> f px >>= return . (Qs x,)++-- hash_t ----------------------------------------------------------------------++data Hash = Hash {-# UNPACK #-} !(ForeignPtr CHash)+data CHash = CHash CMpLimb CMpLimb CMpLimb++instance Storable CHash where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size hash_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment hash_t}+ peek ptr = CHash+ <$> #{peek hash_t, prime} ptr+ <*> #{peek hash_t, next } ptr+ <*> #{peek hash_t, count} ptr + poke ptr (CHash prime next count) = do+ #{poke hash_t, prime} ptr prime+ #{poke hash_t, next } ptr next+ #{poke hash_t, count} ptr count+ +-- relation_t ------------------------------------------------------------------++data Relation = Relation {-# UNPACK #-} !(ForeignPtr CRelation)+data CRelation = CRelation CMpLimb CLong CLong (Ptr CLong) (Ptr CFac) (Ptr CFmpz)++instance Storable CRelation where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size relation_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment relation_t}+ peek ptr = CRelation+ <$> #{peek relation_t, lp } ptr+ <*> #{peek relation_t, num_factors } ptr+ <*> #{peek relation_t, small_primes} ptr+ <*> #{peek relation_t, small } ptr+ <*> #{peek relation_t, factor } ptr+ <*> #{peek relation_t, Y } ptr+ poke ptr (CRelation lp num_factors small_primes small factor y) = do+ #{poke relation_t, lp } ptr lp + #{poke relation_t, num_factors } ptr num_factors+ #{poke relation_t, small_primes} ptr small_primes+ #{poke relation_t, small } ptr small+ #{poke relation_t, factor } ptr factor+ #{poke relation_t, Y } ptr y++-- fac_t -----------------------------------------------------------------------++data Fac = Fac {-# UNPACK #-} !(ForeignPtr CFac)+data CFac = CFac CLong CLong++instance Storable CFac where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size fac_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment fac_t}+ peek ptr = CFac+ <$> #{peek fac_t, ind} ptr+ <*> #{peek fac_t, exp} ptr+ poke ptr (CFac ind exp) = do+ #{poke fac_t, ind} ptr ind+ #{poke fac_t, ind} ptr exp++--------------------------------------------------------------------------------++foreign import ccall "flint/qsieve.h qsieve_init"+ qsieve_init :: Ptr CQs -> Ptr CFmpz -> IO ()+ +foreign import ccall "flint/qsieve.h qsieve_clear"+ qsieve_clear :: Ptr CQs -> IO ()++foreign import ccall "flint/qsieve.h &qsieve_clear"+ p_qsieve_clear :: FunPtr (Ptr CQs -> IO ())++--------------------------------------------------------------------------------++-- | /qsieve_knuth_schroeppel/ /qs_inf/ +--+-- Return the Knuth-Schroeppel multiplier for the \(n\), integer to be+-- factored based upon the Knuth-Schroeppel function.+foreign import ccall "qsieve.h qsieve_knuth_schroeppel"+ qsieve_knuth_schroeppel :: Ptr CQs -> IO CMpLimb++-- | /qsieve_primes_init/ /qs_inf/ +--+-- Compute the factor base prime along with there inverse for \(kn\), where+-- \(k\) is Knuth-Schroeppel multiplier and \(n\) is the integer to be+-- factored. It also computes the square root of \(kn\) modulo factor base+-- primes.+foreign import ccall "qsieve.h qsieve_primes_init"+ qsieve_primes_init :: Ptr CQs -> IO CMpLimb++-- | /qsieve_primes_increment/ /qs_inf/ /delta/ +--+-- It increase the number of factor base primes by amount \'delta\' and+-- calculate inverse of those primes along with the square root of \(kn\)+-- modulo those primes.+foreign import ccall "qsieve.h qsieve_primes_increment"+ qsieve_primes_increment :: Ptr CQs -> CMpLimb -> IO CMpLimb++-- | /qsieve_init_A0/ /qs_inf/ +--+-- First it chooses the possible range of factor of \(A _0\), based on the+-- number of bits in optimal value of \(A _0\). It tries to select range+-- such that we have plenty of primes to choose from as well as number of+-- factor in \(A _0\) are sufficient. For input of size less than 130 bit,+-- this selection method doesn\'t work therefore we randomly generate 2 or+-- 3-subset of all the factor base prime as the factor of \(A _0\).+-- Otherwise, if we have to select \(s\) factor for \(A _0\), we generate+-- \(s - 1\)-subset from odd indices of the possible range of factor and+-- then search last factor using binary search from the even indices of+-- possible range of factor such that value of \(A _0\) is close to it\'s+-- optimal value.+foreign import ccall "qsieve.h qsieve_init_A"+ qsieve_init_A :: Ptr CQs -> IO ()++-- | /qsieve_next_A0/ /qs_inf/ +--+-- Find next candidate for \(A _0\) as follows: generate next lexicographic+-- \(s - 1\)-subset from the odd indices of possible range of factor base+-- and choose the last factor from even indices using binary search so that+-- value \(A _0\) is close to it\'s optimal value.+foreign import ccall "qsieve.h qsieve_next_A"+ qsieve_next_A :: Ptr CQs -> IO ()++-- -- | /qsieve_compute_pre_data/ /qs_inf/ +-- --+-- -- Precompute all the data associated with factor\'s of \(A _0\), since+-- -- \(A _0\) is going to be fixed for several \(A\).+-- foreign import ccall "qsieve.h qsieve_compute_pre_data"+-- qsieve_compute_pre_data :: Ptr CQs -> IO ()++-- | /qsieve_init_poly_first/ /qs_inf/ +--+-- Initializes the value of \(A = q _0 * A _0\), where \(q _0\) is+-- non-factor base prime. precompute the data necessary for generating+-- different \(B\) value using grey code formula. Combine the data+-- calculated for the factor of \(A _0\) along with the parameter \(q _0\)+-- to obtain data as for factor of \(A\). It also calculates the sieve+-- offset for all the factor base prime, for first polynomial.+foreign import ccall "qsieve.h qsieve_init_poly_first"+ qsieve_init_poly_first :: Ptr CQs -> IO ()++-- | /qsieve_init_poly_next/ /qs_inf/ +--+-- Generate next polynomial or next \(B\) value for particular \(A\) and+-- also updates the sieve offsets for all the factor base prime, for this+-- \(B\) value.+foreign import ccall "qsieve.h qsieve_init_poly_next"+ qsieve_init_poly_next :: Ptr CQs -> IO ()++-- | /qsieve_compute_C/ /qs_inf/ +--+-- Given \(A\) and \(B\), calculate \(C = (B ^2 - A) / N\).+foreign import ccall "qsieve.h qsieve_compute_C"+ qsieve_compute_C :: Ptr CQs -> IO ()++-- | /qsieve_do_sieving/ /qs_inf/ /sieve/ +--+-- First initialize the sieve array to zero, then for each \(p \in\)+-- @factor base@, add \(\log_2(p)\) to the locations+-- \(\operatorname{soln1} _p + i * p\) and+-- \(\operatorname{soln2} _p + i * p\) for \(i = 0, 1, 2,\dots\), where+-- \(\operatorname{soln1} _p\) and \(\operatorname{soln2} _p\) are the+-- sieve offsets calculated for \(p\).+foreign import ccall "qsieve.h qsieve_do_sieving"+ qsieve_do_sieving :: Ptr CQs -> CString -> IO ()++-- | /qsieve_do_sieving2/ /qs_inf/ +--+-- Perform the same task as above but instead of sieving over whole array+-- at once divide the array in blocks and then sieve over each block for+-- all the primes in factor base.+foreign import ccall "qsieve.h qsieve_do_sieving2"+ qsieve_do_sieving2 :: Ptr CQs -> IO ()++-- | /qsieve_evaluate_candidate/ /qs_inf/ /i/ /sieve/ +--+-- For location \(i\) in sieve array value at which, is greater than sieve+-- threshold, check the value of \(Q(x)\) at position \(i\) for smoothness.+-- If value is found to be smooth then store it for later processing, else+-- check the residue for the partial if it is found to be partial then+-- store it for late processing.+foreign import ccall "qsieve.h qsieve_evaluate_candidate"+ qsieve_evaluate_candidate :: Ptr CQs -> CLong -> CString -> IO CLong++-- | /qsieve_evaluate_sieve/ /qs_inf/ /sieve/ +--+-- Scan the sieve array for location at, which accumulated value is greater+-- than sieve threshold.+foreign import ccall "qsieve.h qsieve_evaluate_sieve"+ qsieve_evaluate_sieve :: Ptr CQs -> CString -> IO CLong++-- | /qsieve_collect_relations/ /qs_inf/ /sieve/ +--+-- Call for initialization of polynomial, sieving, and scanning of sieve+-- for all the possible polynomials for particular hypercube i.e. \(A\).+foreign import ccall "qsieve.h qsieve_collect_relations"+ qsieve_collect_relations :: Ptr CQs -> CString -> IO CLong++-- | /qsieve_write_to_file/ /qs_inf/ /prime/ /Y/ +--+-- Write a relation to the file. Format is as follows, first write large+-- prime, in case of full relation it is 1, then write exponent of small+-- primes, then write number of factor followed by offset of factor in+-- factor base and their exponent and at last value of \(Q(x)\) for+-- particular relation. each relation is written in new line.+foreign import ccall "qsieve.h qsieve_write_to_file"+ qsieve_write_to_file :: Ptr CQs -> CMpLimb -> Ptr CFmpz -> IO ()++-- | /qsieve_get_table_entry/ /qs_inf/ /prime/ +--+-- Return the pointer to the location of \'prime\' is hash table if it+-- exist, else create and entry for it in hash table and return pointer to+-- that.+foreign import ccall "qsieve.h qsieve_get_table_entry"+ qsieve_get_table_entry :: Ptr CQs -> CMpLimb -> IO (Ptr (Ptr CHash))++-- | /qsieve_add_to_hashtable/ /qs_inf/ /prime/ +--+-- Add \'prime\' to the hast table.+foreign import ccall "qsieve.h qsieve_add_to_hashtable"+ qsieve_add_to_hashtable :: Ptr CQs -> CMpLimb -> IO ()++-- | /qsieve_parse_relation/ /qs_inf/ /str/ +--+-- Given a string representation of relation from the file, parse it to+-- obtain all the parameters of relation.+foreign import ccall "qsieve.h qsieve_parse_relation"+ qsieve_parse_relation :: Ptr CQs -> CString -> IO (Ptr CRelation)++-- | /qsieve_merge_relation/ /qs_inf/ /a/ /b/ +--+-- Given two partial relation having same large prime, merge them to obtain+-- a full relation.+foreign import ccall "qsieve.h qsieve_merge_relation"+ qsieve_merge_relation :: Ptr CQs -> Ptr CRelation -> Ptr CRelation -> IO (Ptr CRelation)++-- | /qsieve_compare_relation/ /a/ /b/ +--+-- Compare two relation based on, first large prime, then number of factor+-- and then offsets of factor in factor base.+foreign import ccall "qsieve.h qsieve_compare_relation"+ qsieve_compare_relation :: Ptr () -> Ptr () -> IO CInt++-- | /qsieve_remove_duplicates/ /rel_list/ /num_relations/ +--+-- Remove duplicate from given list of relations by sorting relations in+-- the list.+foreign import ccall "qsieve.h qsieve_remove_duplicates"+ qsieve_remove_duplicates :: Ptr (Ptr CRelation) -> CLong -> IO CInt++-- -- | /qsieve_insert_relation2/ /qs_inf/ /rel_list/ /num_relations/ +-- --+-- -- Given a list of relations, insert each relation from the list into the+-- -- matrix for further processing.+-- foreign import ccall "qsieve.h qsieve_insert_relation2"+-- qsieve_insert_relation2 :: Ptr CQs -> Ptr (Ptr CRelation) -> CLong -> IO ()++-- | /qsieve_process_relation/ /qs_inf/ +--+-- After we have accumulated required number of relations, first process+-- the file by reading all the relations, removes singleton. Then merge all+-- the possible partial to obtain full relations.+foreign import ccall "qsieve.h qsieve_process_relation"+ qsieve_process_relation :: Ptr CQs -> IO ()++-- | /qsieve_factor/ /factors/ /n/ +--+-- Factor \(n\) using the quadratic sieve method. It is required that \(n\)+-- is not a prime and not a perfect power. There is no guarantee that the+-- factors found will be prime, or distinct.+foreign import ccall "qsieve.h qsieve_factor"+ qsieve_factor :: Ptr CFmpzFactor -> Ptr CFmpz -> IO ()+
+ src/Data/Number/Flint/Qadic.hs view
@@ -0,0 +1,85 @@+{-|+module : Data.Number.Flint.Qadic+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++= Unramified extensions over p-adic numbers++A @Qadic@ represents an element +of \(\mathbb{Q}_q \cong \mathbb{Q}_p[X] / (f(X))\). +This module implements operations on q-adic numbers.++== Example++Calculate a root of the +polynomial \(x^{10}+10x^9+9x^8+8x^7+8x^6+2x^4+9x^3+x^2+3x+1\)+over \(K=\mathbb{Q}_{{11}^4} \cong \mathbb{Q}_{11}[X] /(X^4+8X^2+10X+2)\) to+standard padic precision using +Newton iteration. The iteration starts with \(x=8a^3+4a^2+3\) where \(a\)+is a generator of \(K\). The value of \(x\) is initialized using a `FmpzPoly`.++@ +import Data.Number.Flint++main = do+ let c = [1,10,9,8,8,0,2,9,1,3,1]+ withNewQadicCtx 11 4 0 128 "a" padic_series $ \\ctx -> do+ CQadicCtx pctx _ _ _ _ <- peek ctx+ withNewQadic $ \\x -> do+ withFmpzPoly (fromList [3,0,4,8]) $ \\poly -> do+ padic_poly_set_fmpz_poly x poly pctx+ newton x c ctx+ putStr "x = "+ qadic_print_pretty x ctx+ putStr "\\n"+ y <- horner x c ctx+ withQadic y $ \\y -> do+ putStr "y = "+ qadic_print_pretty y ctx+ putStr "\\n"+ +newton x c ctx = do+ withNewQadic $ \\y ->+ withNewQadic $ \\y' -> do+ qadic_set_ui y (c!!0) ctx+ qadic_set_ui y' 0 ctx+ withNewQadic $ \\tmp -> + forM_ (tail c) $ \\c -> do+ qadic_set_ui tmp c ctx+ qadic_mul y' y' x ctx+ qadic_add y' y' y ctx+ qadic_mul y y x ctx+ qadic_add y y tmp ctx+ is_zero <- qadic_is_zero y+ qadic_inv y' y' ctx+ qadic_mul y y y' ctx+ qadic_sub x x y ctx+ when (is_zero /= 1) $ newton x c ctx+ return ()++horner x c ctx = do+ y <- newQadic+ withQadic y $ \\y -> do+ qadic_set_ui y (head c) ctx+ withNewQadic $ \\tmp ->+ forM_ (tail c) $ \\c -> do+ qadic_mul y y x ctx+ qadic_set_ui tmp c ctx+ qadic_add y y tmp ctx+ return y++@++Running main yields:++>>> main +x = (8*a^3+4*a^2+3) + (8*a^2+2*a+5)*11 + (8*a^3+a^2+6)*11^2 + (7*a^3+6*a^2+2*a+6)*11^3 + (10*a^3+6*a^2+9*a+3)*11^4 + (6*a^3+6*a^2+3*a+7)*11^5 + (7*a^3+5*a^2+9*a+9)*11^6 + (2*a^2+4*a+3)*11^7 + (a^3+3*a^2+3*a+8)*11^8 + (2*a^3+2*a^2+8*a+2)*11^9 + (5*a^3+9*a^2)*11^10 + (2*a^3+3*a^2+2*a+7)*11^11 + (a^3+4*a^2+7*a+3)*11^12 + (10*a^3+9*a^2+10*a+6)*11^13 + (7*a^3+a^2+9*a+3)*11^14 + (10*a^3+10*a^2+6*a+4)*11^15 + (3*a^3+a^2+2*a+1)*11^16 + (4*a^3+6*a^2+8*a)*11^17 + (2*a^3+9*a^2+9*a+10)*11^18 + (4*a^3+4*a^2+5*a+4)*11^19+-}++module Data.Number.Flint.Qadic (+ module Data.Number.Flint.Qadic.FFI,+) where++import Data.Number.Flint.Qadic.FFI+
+ src/Data/Number/Flint/Qadic/FFI.hsc view
@@ -0,0 +1,878 @@+{-|+module : Data.Number.Flint.Qadic.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Qadic.FFI (+ -- * Unramified extensions over p-adic numbers+ -- + -- ** q-adic numbers + -- | Data structures+ -- We represent an element of the+ -- extension \(\mathbb{Q}_q \cong \mathbb{Q}_p[X]\ /\ f(X)\)+ -- as a polynomial in \(\mathbb{Q}_p[X]\) of degree less than \(\deg(f)\).+ -- As such, @qadic_struct@ and @qadic_t@ are typedef\'ed as+ -- @padic_poly_struct@ and @padic_poly_t@.+ Qadic (..)+ , CQadic (..)+ , newQadic+ , withQadic+ , withNewQadic+ -- * q-adic context+ --+ -- | Context+ -- We represent an unramified extension of \(\mathbb{Q}_p\) + -- via \(\mathbb{Q}_q \cong \mathbb{Q}_p[X]\ /\ f(X)\), + -- where \(f \in \mathbb{Q}_p[X]\) is a monic, irreducible polynomial which we+ -- assume to actually be in \(\mathbb{Z}[X]\). The first field in the+ -- context structure is a \(p\)-adic context struct @pctx@, which contains+ -- data about the prime \(p\), precomputed powers, the printing mode etc.+ -- The polynomial \(f\) is represented as a sparse polynomial using two+ -- arrays \(j\) and \(a\) of length @len@,+ -- where \(f(X) = \sum_{i} a_{i} X^{j_{i}}\).+ -- We also assume that the array \(j\) is sorted in ascending+ -- order. We choose this data structure to improve reduction modulo \(f(X)\)+ -- in \(\mathbb{Q}_p[X]\), assuming a sparse polynomial \(f(X)\)+ -- is chosen. The field @var@ contains the name of a generator of the+ -- extension, which is used when printing the elements.+ , QadicCtx (..)+ , CQadicCtx (..)+ , newQadicCtx+ , newQadicCtxConway+ , withQadicCtx+ , withNewQadicCtx+ , withNewQadicCtxConway+ , qadic_ctx_init+ , qadic_ctx_init_conway+ , qadic_ctx_clear+ , qadic_ctx_degree+ , qadic_ctx_print+ -- * Memory management+ , qadic_init+ , qadic_init2+ , qadic_clear+ , _fmpz_poly_reduce+ , _fmpz_mod_poly_reduce+ , qadic_reduce+ -- * Properties+ , qadic_val+ , qadic_prec+ -- * Randomisation+ , qadic_randtest+ , qadic_randtest_not_zero+ , qadic_randtest_val+ , qadic_randtest_int+ -- * Assignments and conversions+ , qadic_set+ , qadic_zero+ , qadic_one+ , qadic_gen+ , qadic_set_ui+ , qadic_get_padic+ -- * Comparison+ , qadic_is_zero+ , qadic_is_one+ , qadic_equal+ -- * Basic arithmetic+ , qadic_add+ , qadic_sub+ , qadic_neg+ , qadic_mul+ , _qadic_inv+ , qadic_inv+ , _qadic_pow+ , qadic_pow+ -- * Square root+ , qadic_sqrt+ -- * Special functions+ , _qadic_exp_rectangular+ , qadic_exp_rectangular+ , _qadic_exp_balanced+ , qadic_exp_balanced+ , _qadic_exp+ , qadic_exp+ , _qadic_log_rectangular+ , qadic_log_rectangular+ , _qadic_log_balanced+ , qadic_log_balanced+ , _qadic_log+ , qadic_log+ , _qadic_frobenius_a+ , _qadic_frobenius+ , qadic_frobenius+ , _qadic_teichmuller+ , qadic_teichmuller+ , _qadic_trace+ , _qadic_norm+ , qadic_norm+ , qadic_norm_analytic+ , qadic_norm_resultant+ -- * Output+ , qadic_fprint_pretty+ , qadic_print_pretty+) where++-- unramified extensions over p-adic numbers -----------------------------------++import Control.Monad++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr, castPtr )+import Foreign.Storable+import Foreign.Marshal ( free )+import Foreign.Marshal.Array++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpz.Vec+import Data.Number.Flint.Fmpq+import Data.Number.Flint.Padic+import Data.Number.Flint.Padic.Poly++#include <flint/flint.h>+#include <flint/qadic.h>++-- qadic_t --------------------------------------------------------------------++data Qadic = Qadic {-# UNPACK #-} !(ForeignPtr CQadic)+type CQadic = CPadicPoly++-- | Create new q-adic+newQadic = do+ x <- mallocForeignPtr+ withForeignPtr x qadic_init+ addForeignPtrFinalizer p_qadic_clear x+ return $ Qadic x++-- | Use q-adic+{-# INLINE withQadic #-}+withQadic (Qadic x) f = do+ withForeignPtr x $ \px -> f px >>= return . (Qadic x,)++-- | Apply `f` to new q-adic+{-# INLINE withNewQadic #-}+withNewQadic f = do+ x <- newQadic+ withQadic x f++-- qadic_ctx_t ----------------------------------------------------------------++data QadicCtx = QadicCtx {-# UNPACK #-} !(ForeignPtr CQadicCtx)+data CQadicCtx = CQadicCtx (Ptr CPadicCtx) (Ptr CFmpz) (Ptr CLong) CLong CString++instance Storable CQadicCtx where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size qadic_ctx_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment qadic_ctx_t}+ peek ptr = return CQadicCtx+ `ap` (return $ castPtr ptr)+ `ap` #{peek qadic_ctx_struct, a } ptr+ `ap` #{peek qadic_ctx_struct, j } ptr+ `ap` #{peek qadic_ctx_struct, len } ptr+ `ap` #{peek qadic_ctx_struct, var } ptr+ poke = undefined++{-# INLINE _newQadicCtx #-}+_newQadicCtx f p d min max var mode = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> do+ withFmpz p $ \p -> do+ withCString var $ \var -> do+ f x p d min max var mode+ addForeignPtrFinalizer p_qadic_ctx_clear x+ return $ QadicCtx x++-- | Create q-adic context with prime \(p\), extension \(d\),+-- precomputed powers \(p^{min}\) to \(p^{max}\) and `PadicPrintMode`+-- @mode@. Initialized with `qadic_ctx_init`.+newQadicCtx = _newQadicCtx qadic_ctx_init+-- | Create q-adic context with prime \(p\), extension \(d\),+-- precomputed powers \(p^{min}\) to \(p^{max}\) and `PadicPrintMode`+-- @mode@. Initialized with `qadic_ctx_init_conway`.+newQadicCtxConway = _newQadicCtx qadic_ctx_init_conway++-- | Use q-adic context+{-# INLINE withQadicCtx #-}+withQadicCtx (QadicCtx x) f = do+ withForeignPtr x $ \px -> f px >>= return . (QadicCtx x,)++_withNewQadicCtx initialize p d min max var mode f = do+ x <- initialize p d min max var mode+ withQadicCtx x f++withNewQadicCtx = _withNewQadicCtx newQadicCtx+withNewQadicCtxConway = _withNewQadicCtx newQadicCtxConway++--------------------------------------------------------------------------------++-- | /qadic_ctx_init/ /ctx/ /p/ /d/ /min/ /max/ /var/ /mode/ +-- +-- Initialises the context @ctx@ with prime \(p\), extension degree \(d\),+-- variable name @var@ and printing mode @mode@. The defining polynomial is+-- chosen as a Conway polynomial if possible and otherwise as a random+-- sparse polynomial.+-- +-- Stores powers of \(p\) with exponents between @min@ (inclusive) and+-- @max@ exclusive. Assumes that @min@ is at most @max@.+-- +-- Assumes that \(p\) is a prime.+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+-- +-- Assumes that the printing mode is one of @PADIC_TERSE@, @PADIC_SERIES@,+-- or @PADIC_VAL_UNIT@.+-- +-- This function also carries out some relevant precomputation for+-- arithmetic in \(\mathbb{Q}_p / (p^N)\) such as powers of \(p\) close to+-- \(p^N\).+foreign import ccall "qadic.h qadic_ctx_init"+ qadic_ctx_init :: Ptr CQadicCtx -> Ptr CFmpz -> CLong -> CLong -> CLong -> CString -> PadicPrintMode -> IO ()++-- | /qadic_ctx_init_conway/ /ctx/ /p/ /d/ /min/ /max/ /var/ /mode/ +-- +-- Initialises the context @ctx@ with prime \(p\), extension degree \(d\),+-- variable name @var@ and printing mode @mode@. The defining polynomial is+-- chosen as a Conway polynomial, hence has restrictions on the prime and+-- the degree.+-- +-- Stores powers of \(p\) with exponents between @min@ (inclusive) and+-- @max@ exclusive. Assumes that @min@ is at most @max@.+-- +-- Assumes that \(p\) is a prime.+-- +-- Assumes that the string @var@ is a null-terminated string of length at+-- least one.+-- +-- Assumes that the printing mode is one of @PADIC_TERSE@, @PADIC_SERIES@,+-- or @PADIC_VAL_UNIT@.+-- +-- This function also carries out some relevant precomputation for+-- arithmetic in \(\mathbb{Q}_p / (p^N)\) such as powers of \(p\) close to+-- \(p^N\).+foreign import ccall "qadic.h qadic_ctx_init_conway"+ qadic_ctx_init_conway :: Ptr CQadicCtx -> Ptr CFmpz -> CLong -> CLong -> CLong -> CString -> PadicPrintMode -> IO ()++-- | /qadic_ctx_clear/ /ctx/ +-- +-- Clears all memory that has been allocated as part of the context.+foreign import ccall "qadic.h qadic_ctx_clear"+ qadic_ctx_clear :: Ptr CQadicCtx -> IO ()++foreign import ccall "qadic.h &qadic_ctx_clear"+ p_qadic_ctx_clear :: FunPtr (Ptr CQadicCtx -> IO ())++-- | /qadic_ctx_degree/ /ctx/ +-- +-- Returns the extension degree.+foreign import ccall "qadic.h qadic_ctx_degree"+ qadic_ctx_degree :: Ptr CQadicCtx -> IO CLong++-- | /qadic_ctx_print/ /ctx/ +-- +-- Prints the data from the given context.+qadic_ctx_print ctx = do+ CQadicCtx pctx a j len var <- peek ctx+ CPadicCtx p _ _ _ _ mode <- peek pctx+ putStr "p = "+ fmpz_print p+ putStr "\n"+ d <- peek (j `advancePtr` (fromIntegral len - 1))+ putStrLn $ "d = " ++ show d+ putStr "f(X) = "+ fmpz_print a+ forM_ [1 .. fromIntegral len - 1] $ \k -> do+ i <- peek (j `advancePtr` k)+ flag1 <- fmpz_is_zero (a `advancePtr` k)+ case flag1 of + 1 -> return ()+ _ -> do+ putStr " + " + flag <- fmpz_is_one (a `advancePtr` k)+ case flag of + 1 -> return ()+ _ -> do+ fmpz_print (a `advancePtr` k)+ putStr "*"+ putStr "X"+ when ( i /= 1 ) $ putStr $ "^" ++ show i++-- Memory management -----------------------------------------------------------++-- | /qadic_init/ /rop/ +-- +-- Initialises the element @rop@, setting its value to \(0\).+foreign import ccall "qadic.h qadic_init"+ qadic_init :: Ptr CQadic -> IO ()++-- | /qadic_init2/ /rop/ /prec/ +-- +-- Initialises the element @rop@ with the given output precision, setting+-- the value to \(0\).+foreign import ccall "qadic.h qadic_init2"+ qadic_init2 :: Ptr CQadic -> CLong -> IO ()++-- | /qadic_clear/ /rop/ +-- +-- Clears the element @rop@.+foreign import ccall "qadic.h qadic_clear"+ qadic_clear :: Ptr CQadic -> IO ()++foreign import ccall "qadic.h &qadic_clear"+ p_qadic_clear :: FunPtr (Ptr CQadic -> IO ())++-- | /_fmpz_poly_reduce/ /R/ /lenR/ /a/ /j/ /len/ +-- +-- Reduces a polynomial @(R, lenR)@ modulo a sparse monic+-- polynomial \(f(X) = \sum_{i} a_{i} X^{j_{i}}\) of degree at least \(2\).+-- +-- Assumes that the array \(j\) of positive length @len@ is sorted in+-- ascending order.+-- +-- Allows zero-padding in @(R, lenR)@.+foreign import ccall "qadic.h _fmpz_poly_reduce"+ _fmpz_poly_reduce :: Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> IO ()++-- | /_fmpz_mod_poly_reduce/ /R/ /lenR/ /a/ /j/ /len/ /p/ +-- +-- Reduces a polynomial @(R, lenR)@ modulo a sparse monic+-- polynomial \(f(X) = \sum_{i} a_{i} X^{j_{i}}\) of degree at least \(2\) in+-- \(\mathbb{Z}/(p)\), where \(p\) is typically a prime power.+-- +-- Assumes that the array \(j\) of positive length @len@ is sorted in+-- ascending order.+-- +-- Allows zero-padding in @(R, lenR)@.+foreign import ccall "qadic.h _fmpz_mod_poly_reduce"+ _fmpz_mod_poly_reduce :: Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> IO ()++-- | /qadic_reduce/ /rop/ /ctx/ +-- +-- Reduces @rop@ modulo \(f(X)\) and \(p^N\).+foreign import ccall "qadic.h qadic_reduce"+ qadic_reduce :: Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- Properties ------------------------------------------------------------------++-- | /qadic_val/ /op/ +-- +-- Returns the valuation of @op@.+foreign import ccall "qadic.h qadic_val"+ qadic_val :: Ptr CQadic -> IO CLong++-- | /qadic_prec/ /op/ +-- +-- Returns the precision of @op@.+foreign import ccall "qadic.h qadic_prec"+ qadic_prec :: Ptr CQadic -> IO CLong++-- Randomisation ---------------------------------------------------------------++-- | /qadic_randtest/ /rop/ /state/ /ctx/ +-- +-- Generates a random element of \(\mathbb{Q}_q\).+foreign import ccall "qadic.h qadic_randtest"+ qadic_randtest :: Ptr CQadic -> Ptr CFRandState -> Ptr CQadicCtx -> IO ()++-- | /qadic_randtest_not_zero/ /rop/ /state/ /ctx/ +-- +-- Generates a random non-zero element of \(\mathbb{Q}_q\).+foreign import ccall "qadic.h qadic_randtest_not_zero"+ qadic_randtest_not_zero :: Ptr CQadic -> Ptr CFRandState -> Ptr CQadicCtx -> IO ()++-- | /qadic_randtest_val/ /rop/ /state/ /v/ /ctx/ +-- +-- Generates a random element of \(\mathbb{Q}_q\) with prescribed valuation+-- @val@.+-- +-- Note that if \(v \geq N\) then the element is necessarily zero.+foreign import ccall "qadic.h qadic_randtest_val"+ qadic_randtest_val :: Ptr CQadic -> Ptr CFRandState -> CLong -> Ptr CQadicCtx -> IO ()++-- | /qadic_randtest_int/ /rop/ /state/ /ctx/ +-- +-- Generates a random element of \(\mathbb{Q}_q\) with non-negative+-- valuation.+foreign import ccall "qadic.h qadic_randtest_int"+ qadic_randtest_int :: Ptr CQadic -> Ptr CFRandState -> Ptr CQadicCtx -> IO ()++-- Assignments and conversions -------------------------------------------------++-- | /qadic_set/ /rop/ /op/ +-- +-- Sets @rop@ to @op@.+foreign import ccall "qadic.h qadic_set"+ qadic_set :: Ptr CQadic -> Ptr CQadic -> IO ()++-- | /qadic_zero/ /rop/ +-- +-- Sets @rop@ to zero.+foreign import ccall "qadic.h qadic_zero"+ qadic_zero :: Ptr CQadic -> IO ()++-- | /qadic_one/ /rop/ /ctx/ +-- +-- Sets @rop@ to one, reduced in the given context.+-- +-- Note that if the precision \(N\) is non-positive then @rop@ is actually+-- set to zero.+foreign import ccall "qadic.h qadic_one"+ qadic_one :: Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- | /qadic_gen/ /rop/ /ctx/ +-- +-- Sets @rop@ to the generator \(X\) for the extension when \(N > 0\), and+-- zero otherwise. If the extension degree is one, raises an abort signal.+foreign import ccall "qadic.h qadic_gen"+ qadic_gen :: Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- | /qadic_set_ui/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the integer @op@, reduced in the context.+foreign import ccall "qadic.h qadic_set_ui"+ qadic_set_ui :: Ptr CQadic -> CULong -> Ptr CQadicCtx -> IO ()++-- | /qadic_get_padic/ /rop/ /op/ /ctx/ +-- +-- If the element @op@ lies in \(\mathbb{Q}_p\), sets @rop@ to its value+-- and returns \(1\); otherwise, returns \(0\).+foreign import ccall "qadic.h qadic_get_padic"+ qadic_get_padic :: Ptr CPadic -> Ptr CQadic -> Ptr CQadicCtx -> IO CInt++-- Comparison ------------------------------------------------------------------++-- | /qadic_is_zero/ /op/ +-- +-- Returns whether @op@ is equal to zero.+foreign import ccall "qadic.h qadic_is_zero"+ qadic_is_zero :: Ptr CQadic -> IO CInt++-- | /qadic_is_one/ /op/ /ctx/ +-- +-- Returns whether @op@ is equal to one in the given context.+foreign import ccall "qadic.h qadic_is_one"+ qadic_is_one :: Ptr CQadic -> Ptr CQadicCtx -> IO CInt++-- | /qadic_equal/ /op1/ /op2/ +-- +-- Returns whether @op1@ and @op2@ are equal.+foreign import ccall "qadic.h qadic_equal"+ qadic_equal :: Ptr CQadic -> Ptr CQadic -> IO CInt++-- Basic arithmetic ------------------------------------------------------------++-- | /qadic_add/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the sum of @op1@ and @op2@.+-- +-- Assumes that both @op1@ and @op2@ are reduced in the given context and+-- ensures that @rop@ is, too.+foreign import ccall "qadic.h qadic_add"+ qadic_add :: Ptr CQadic -> Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- | /qadic_sub/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the difference of @op1@ and @op2@.+-- +-- Assumes that both @op1@ and @op2@ are reduced in the given context and+-- ensures that @rop@ is, too.+foreign import ccall "qadic.h qadic_sub"+ qadic_sub :: Ptr CQadic -> Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- | /qadic_neg/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the negative of @op@.+-- +-- Assumes that @op@ is reduced in the given context and ensures that @rop@+-- is, too.+foreign import ccall "qadic.h qadic_neg"+ qadic_neg :: Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- | /qadic_mul/ /rop/ /op1/ /op2/ /ctx/ +-- +-- Sets @rop@ to the product of @op1@ and @op2@, reducing the output in the+-- given context.+foreign import ccall "qadic.h qadic_mul"+ qadic_mul :: Ptr CQadic -> Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- | /_qadic_inv/ /rop/ /op/ /len/ /a/ /j/ /lena/ /p/ /N/ +-- +-- Sets @(rop, d)@ to the inverse of @(op, len)@ modulo \(f(X)\) given by+-- @(a,j,lena)@ and \(p^N\).+-- +-- Assumes that @(op,len)@ has valuation \(0\), that is, that it represents+-- a \(p\)-adic unit.+-- +-- Assumes that @len@ is at most \(d\).+-- +-- Does not support aliasing.+foreign import ccall "qadic.h _qadic_inv"+ _qadic_inv :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /qadic_inv/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the inverse of @op@, reduced in the given context.+foreign import ccall "qadic.h qadic_inv"+ qadic_inv :: Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- | /_qadic_pow/ /rop/ /op/ /len/ /e/ /a/ /j/ /lena/ /p/ +-- +-- Sets @(rop, 2*d-1)@ to @(op,len)@ raised to the power \(e\), reduced+-- modulo \(f(X)\) given by @(a, j, lena)@ and \(p\), which is expected to+-- be a prime power.+-- +-- Assumes that \(e \geq 0\) and that @len@ is positive and at most \(d\).+-- +-- Although we require that @rop@ provides space for \(2d - 1\)+-- coefficients, the output will be reduces modulo \(f(X)\), which is a+-- polynomial of degree \(d\).+-- +-- Does not support aliasing.+foreign import ccall "qadic.h _qadic_pow"+ _qadic_pow :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> IO ()++-- | /qadic_pow/ /rop/ /op/ /e/ /ctx/ +-- +-- Sets @rop@ the @op@ raised to the power \(e\).+-- +-- Currently assumes that \(e \geq 0\).+-- +-- Note that for any input @op@, @rop@ is set to one in the given context+-- whenever \(e = 0\).+foreign import ccall "qadic.h qadic_pow"+ qadic_pow :: Ptr CQadic -> Ptr CQadic -> Ptr CFmpz -> Ptr CQadicCtx -> IO ()++-- Square root -----------------------------------------------------------------++-- | /qadic_sqrt/ /rop/ /op/ /ctx/ +-- +-- Return @1@ if the input is a square (to input precision). If so, set+-- @rop@ to a square root (truncated to output precision).+foreign import ccall "qadic.h qadic_sqrt"+ qadic_sqrt :: Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO CInt++-- Special functions -----------------------------------------------------------++-- | /_qadic_exp_rectangular/ /rop/ /op/ /v/ /len/ /a/ /j/ /lena/ /p/ /N/ /pN/ +-- +-- Sets @(rop, 2*d - 1)@ to the exponential of @(op, v, len)@ reduced+-- modulo \(p^N\), assuming that the series converges.+-- +-- Assumes that @(op, v, len)@ is non-zero.+-- +-- Does not support aliasing.+foreign import ccall "qadic.h _qadic_exp_rectangular"+ _qadic_exp_rectangular :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /qadic_exp_rectangular/ /rop/ /op/ /ctx/ +-- +-- Returns whether the exponential series converges at @op@ and sets @rop@+-- to its value reduced modulo in the given context.+foreign import ccall "qadic.h qadic_exp_rectangular"+ qadic_exp_rectangular :: Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO CInt++-- | /_qadic_exp_balanced/ /rop/ /x/ /v/ /len/ /a/ /j/ /lena/ /p/ /N/ /pN/ +-- +-- Sets @(rop, d)@ to the exponential of @(op, v, len)@ reduced modulo+-- \(p^N\), assuming that the series converges.+-- +-- Assumes that @len@ is in \([1,d)\) but supports zero padding, including+-- the special case when @(op, len)@ is zero.+-- +-- Supports aliasing between @rop@ and @op@.+foreign import ccall "qadic.h _qadic_exp_balanced"+ _qadic_exp_balanced :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /qadic_exp_balanced/ /rop/ /op/ /ctx/ +-- +-- Returns whether the exponential series converges at @op@ and sets @rop@+-- to its value reduced modulo in the given context.+foreign import ccall "qadic.h qadic_exp_balanced"+ qadic_exp_balanced :: Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO CInt++-- | /_qadic_exp/ /rop/ /op/ /v/ /len/ /a/ /j/ /lena/ /p/ /N/ +-- +-- Sets @(rop, 2*d - 1)@ to the exponential of @(op, v, len)@ reduced+-- modulo \(p^N\), assuming that the series converges.+-- +-- Assumes that @(op, v, len)@ is non-zero.+-- +-- Does not support aliasing.+foreign import ccall "qadic.h _qadic_exp"+ _qadic_exp :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /qadic_exp/ /rop/ /op/ /ctx/ +-- +-- Returns whether the exponential series converges at @op@ and sets @rop@+-- to its value reduced modulo in the given context.+-- +-- The exponential series converges if the valuation of @op@ is at least+-- \(2\) or \(1\) when \(p\) is even or odd, respectively.+foreign import ccall "qadic.h qadic_exp"+ qadic_exp :: Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO CInt++-- | /_qadic_log_rectangular/ /z/ /y/ /v/ /len/ /a/ /j/ /lena/ /p/ /N/ /pN/ +-- +-- Computes+-- +-- \[`\]+-- \[z = - \sum_{i = 1}^{\infty} \frac{y^i}{i} \pmod{p^N}.\]+-- +-- Note that this can be used to compute the \(p\)-adic logarithm via the+-- equation+-- +-- \[`\]+-- \[\begin{aligned}+-- \log(x) & = \sum_{i=1}^{\infty} (-1)^{i-1} \frac{(x-1)^i}{i} \\+-- & = - \sum_{i=1}^{\infty} \frac{(1-x)^i}{i}.+-- \end{aligned}\]+-- +-- Assumes that \(y = 1 - x\) is non-zero and that+-- \(v = \operatorname{ord}_p(y)\) is at least \(1\) when \(p\) is odd and+-- at least \(2\) when \(p = 2\) so that the series converges.+-- +-- Assumes that \(y\) is reduced modulo \(p^N\).+-- +-- Assumes that \(v < N\), and in particular \(N \geq 2\).+-- +-- Supports aliasing between \(y\) and \(z\).+foreign import ccall "qadic.h _qadic_log_rectangular"+ _qadic_log_rectangular :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /qadic_log_rectangular/ /rop/ /op/ /ctx/ +-- +-- Returns whether the \(p\)-adic logarithm function converges at @op@, and+-- if so sets @rop@ to its value.+foreign import ccall "qadic.h qadic_log_rectangular"+ qadic_log_rectangular :: Ptr CQadic -> Ptr CQadic -> Ptr CPadicCtx -> IO CInt++-- | /_qadic_log_balanced/ /z/ /y/ /len/ /a/ /j/ /lena/ /p/ /N/ /pN/ +-- +-- Computes \((z, d)\) as+-- +-- \[`\]+-- \[z = - \sum_{i = 1}^{\infty} \frac{y^i}{i} \pmod{p^N}.\]+-- +-- Assumes that \(v = \operatorname{ord}_p(y)\) is at least \(1\) when+-- \(p\) is odd and at least \(2\) when \(p = 2\) so that the series+-- converges.+-- +-- Supports aliasing between \(z\) and \(y\).+foreign import ccall "qadic.h _qadic_log_balanced"+ _qadic_log_balanced :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /qadic_log_balanced/ /rop/ /op/ /ctx/ +-- +-- Returns whether the \(p\)-adic logarithm function converges at @op@, and+-- if so sets @rop@ to its value.+foreign import ccall "qadic.h qadic_log_balanced"+ qadic_log_balanced :: Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO CInt++-- | /_qadic_log/ /z/ /y/ /v/ /len/ /a/ /j/ /lena/ /p/ /N/ /pN/ +-- +-- Computes \((z, d)\) as+-- +-- \[`\]+-- \[z = - \sum_{i = 1}^{\infty} \frac{y^i}{i} \pmod{p^N}.\]+-- +-- Note that this can be used to compute the \(p\)-adic logarithm via the+-- equation+-- +-- \[`\]+-- \[\begin{aligned}+-- \log(x) & = \sum_{i=1}^{\infty} (-1)^{i-1} \frac{(x-1)^i}{i} \\+-- & = - \sum_{i=1}^{\infty} \frac{(1-x)^i}{i}.+-- \end{aligned}\]+-- +-- Assumes that \(y = 1 - x\) is non-zero and that+-- \(v = \operatorname{ord}_p(y)\) is at least \(1\) when \(p\) is odd and+-- at least \(2\) when \(p = 2\) so that the series converges.+-- +-- Assumes that \((y, d)\) is reduced modulo \(p^N\).+-- +-- Assumes that \(v < N\), and hence in particular \(N \geq 2\).+-- +-- Supports aliasing between \(z\) and \(y\).+foreign import ccall "qadic.h _qadic_log"+ _qadic_log :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> Ptr CFmpz -> IO ()++-- | /qadic_log/ /rop/ /op/ /ctx/ +-- +-- Returns whether the \(p\)-adic logarithm function converges at @op@, and+-- if so sets @rop@ to its value.+-- +-- The \(p\)-adic logarithm function is defined by the usual series+-- +-- \[`\]+-- \[\log_p(x) = \sum_{i=1}^{\infty} (-1)^{i-1} \frac{(x-1)^i}{i}\]+-- +-- but this only converges when \(\operatorname{ord}_p(x)\) is at least+-- \(2\) or \(1\) when \(p = 2\) or \(p > 2\), respectively.+foreign import ccall "qadic.h qadic_log"+ qadic_log :: Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO CInt++-- | /_qadic_frobenius_a/ /rop/ /e/ /a/ /j/ /lena/ /p/ /N/ +-- +-- Computes \(\sigma^e(X) \bmod{p^N}\) where \(X\) is such that+-- \(\mathbb{Q}_q \cong \mathbb{Q}_p[X]/(f(X))\).+-- +-- Assumes that the precision \(N\) is at least \(2\) and that the+-- extension is non-trivial, i.e.\(d \geq 2\).+-- +-- Assumes that \(0 < e < d\).+-- +-- Sets @(rop, 2*d-1)@, although the actual length of the output will be at+-- most \(d\).+foreign import ccall "qadic.h _qadic_frobenius_a"+ _qadic_frobenius_a :: Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /_qadic_frobenius/ /rop/ /op/ /len/ /e/ /a/ /j/ /lena/ /p/ /N/ +-- +-- Sets @(rop, 2*d-1)@ to \(\Sigma\) evaluated at @(op, len)@.+-- +-- Assumes that @len@ is positive but at most \(d\).+-- +-- Assumes that \(0 < e < d\).+-- +-- Does not support aliasing.+foreign import ccall "qadic.h _qadic_frobenius"+ _qadic_frobenius :: Ptr CFmpz -> Ptr CFmpz -> CLong -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /qadic_frobenius/ /rop/ /op/ /e/ /ctx/ +-- +-- Evaluates the homomorphism \(\Sigma^e\) at @op@.+-- +-- Recall that \(\mathbb{Q}_q / \mathbb{Q}_p\) is Galois with Galois group+-- \(\langle \Sigma \rangle \cong \langle \sigma \rangle\), which is also+-- isomorphic to \(\mathbb{Z}/d\mathbb{Z}\), where+-- \(\sigma \in \operatorname{Gal}(\mathbb{F}_q/\mathbb{F}_p)\) is the+-- Frobenius element \(\sigma \colon x \mapsto x^p\) and \(\Sigma\) is its+-- lift to \(\operatorname{Gal}(\mathbb{Q}_q/\mathbb{Q}_p)\).+-- +-- This functionality is implemented as @GaloisImage()@ in Magma.+foreign import ccall "qadic.h qadic_frobenius"+ qadic_frobenius :: Ptr CQadic -> Ptr CQadic -> CLong -> Ptr CQadicCtx -> IO ()++-- | /_qadic_teichmuller/ /rop/ /op/ /len/ /a/ /j/ /lena/ /p/ /N/ +-- +-- Sets @(rop, d)@ to the Teichm\"uller lift of @(op, len)@ modulo \(p^N\).+-- +-- Does not support aliasing.+foreign import ccall "qadic.h _qadic_teichmuller"+ _qadic_teichmuller :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /qadic_teichmuller/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the Teichm\"uller lift of @op@ to the precision given in+-- the context.+-- +-- For a unit @op@, this is the unique \((q-1)`th root of unity +-- which is congruent to \)op modulo :math:\`p.+-- +-- Sets @rop@ to zero if @op@ is zero in the given context.+-- +-- Raises an exception if the valuation of @op@ is negative.+foreign import ccall "qadic.h qadic_teichmuller"+ qadic_teichmuller :: Ptr CQadic -> Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- | /_qadic_trace/ /rop/ /op/ /len/ /a/ /j/ /lena/ /pN/ +-- +-- Sets @rop@ to the trace of @op@.+-- +-- For an element \(a \in \mathbb{Q}_q\), multiplication by \(a\) defines a+-- \(\mathbb{Q}_p\)-linear map on \(\mathbb{Q}_q\). We define the trace of+-- \(a\) as the trace of this map. Equivalently, if \(\Sigma\) generates+-- \(\operatorname{Gal}(\mathbb{Q}_q / \mathbb{Q}_p)\) then the trace of+-- \(a\) is equal to \(\sum_{i=0}^{d-1} \Sigma^i (a)\).+foreign import ccall "qadic.h _qadic_trace"+ _qadic_trace :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> IO ()++-- | /_qadic_norm/ /rop/ /op/ /len/ /a/ /j/ /lena/ /p/ /N/ +-- +-- Sets @rop@ to the norm of the element @(op,len)@ in \(\mathbb{Z}_q\) to+-- precision \(N\), where @len@ is at least one.+-- +-- The result will be reduced modulo \(p^N\).+-- +-- Note that whenever @(op,len)@ is a unit, so is its norm. Thus, the+-- output @rop@ of this function will typically not have to be+-- canonicalised or reduced by the caller.+foreign import ccall "qadic.h _qadic_norm"+ _qadic_norm :: Ptr CFmpz -> Ptr CFmpz -> CLong -> Ptr CFmpz -> Ptr CLong -> CLong -> Ptr CFmpz -> CLong -> IO ()++-- | /qadic_norm/ /rop/ /op/ /ctx/ +-- +-- Computes the norm of @op@ to the given precision.+-- +-- Algorithm selection is automatic depending on the input.+foreign import ccall "qadic.h qadic_norm"+ qadic_norm :: Ptr CPadic -> Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- | /qadic_norm_analytic/ /rop/ /op/ /ctx/ +-- +-- Whenever @op@ has valuation greater than \((p-1)^{-1}\), this routine+-- computes its norm @rop@ via+-- +-- \[`\]+-- \[\operatorname{Norm} (x) = \exp \Bigl( \bigl( \operatorname{Trace} \log (x) \bigr) \Bigr).\]+-- +-- In the special case that @op@ lies in \(\mathbb{Q}_p\), returns its norm+-- as \(\operatorname{Norm}(x) = x^d\), where \(d\) is the extension+-- degree.+-- +-- Otherwise, raises an @abort@ signal.+-- +-- The complexity of this implementation is quasi-linear in \(d\) and+-- \(N\), and polynomial in \(\log p\).+foreign import ccall "qadic.h qadic_norm_analytic"+ qadic_norm_analytic :: Ptr CPadic -> Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- | /qadic_norm_resultant/ /rop/ /op/ /ctx/ +-- +-- Sets @rop@ to the norm of @op@, using the formula+-- +-- \[`\]+-- \[\operatorname{Norm}(x) = \ell(f)^{-\deg(a)} \operatorname{Res}(f(X), a(X)),\]+-- +-- where \(\mathbb{Q}_q \cong \mathbb{Q}_p[X] / (f(X))\), \(\ell(f)\) is+-- the leading coefficient of \(f(X)\), and \(a(X) \in \mathbb{Q}_p[X]\)+-- denotes the same polynomial as \(x\).+-- +-- The complexity of the current implementation is given+-- by \(\mathcal{O}(d^4 M(N \log p))\), where \(M(n)\) denotes the complexity+-- of multiplying to \(n\)-bit integers.+foreign import ccall "qadic.h qadic_norm_resultant"+ qadic_norm_resultant :: Ptr CPadic -> Ptr CQadic -> Ptr CQadicCtx -> IO ()++-- Output ----------------------------------------------------------------------++-- | /qadic_fprint_pretty/ /file/ /op/ /ctx/ +-- +-- Prints a pretty representation of @op@ to @file@.+-- +-- In the current implementation, always returns \(1\). The return code is+-- part of the function\'s signature to allow for a later implementation to+-- return the number of characters printed or a non-positive error code.+foreign import ccall "qadic.h qadic_fprint_pretty"+ qadic_fprint_pretty :: Ptr CFile -> Ptr CQadic -> Ptr CQadicCtx -> IO CInt++-- | /qadic_print_pretty/ /op/ /ctx/ +-- +-- Prints a pretty representation of @op@ to @stdout@.+-- +-- In the current implementation, always returns \(1\). The return code is+-- part of the function\'s signature to allow for a later implementation to+-- return the number of characters printed or a non-positive error code.+qadic_print_pretty x ctx = printCStr (flip qadic_get_str_pretty ctx) x++-- | /qadic_get_str__pretty/ /op/ /ctx/+--+-- Returns a pretty representation of @op@ in a C string.+foreign import ccall "qadic_get_str_pretty"+ qadic_get_str_pretty :: Ptr CQadic -> Ptr CQadicCtx -> IO CString++
+ src/Data/Number/Flint/Quotient.hs view
@@ -0,0 +1,27 @@+{-|+module : Data.Number.Flint.Quotient+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++== Quotients+-}++module Data.Number.Flint.Quotient where++class Quotient a b | a -> b where++ -- | /x/ \/\/ /y/+ --+ -- Construct an /quotient/ from numerator /x/ and denominator /y/.+ (//) :: b -> b -> a+ -- | /numerator/ /x/+ --+ -- Return the numerator of /x/+ numerator :: a -> b+ -- | /denominator/ /x/+ --+ -- Return the denominator of /x/+ denominator :: a -> b++infixl 7 //
+ src/Data/Number/Flint/Support/D/Extras.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Support.D.Extras (+ module Data.Number.Flint.Support.D.Extras.FFI+ ) where++import Data.Number.Flint.Support.D.Extras.FFI
+ src/Data/Number/Flint/Support/D/Extras/FFI.hsc view
@@ -0,0 +1,94 @@+{-|+module : Data.Number.Flint.Support.D.Extras.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Support.D.Extras.FFI (+ -- * Support functions for double arithmetic+ -- * Random functions+ d_randtest+ , d_randtest_signed+ , d_randtest_special+ -- * Arithmetic+ , d_polyval+ -- * Special functions+ , d_lambertw+ , d_is_nan+ , d_log2+) where++-- Support functions for double arithmetic -------------------------------------++import Foreign.Ptr+import Foreign.C.Types++import Data.Number.Flint.Flint++-- Random functions ------------------------------------------------------------++-- | /d_randtest/ /state/ +--+-- Returns a random number in the interval \([0.5, 1)\).+foreign import ccall "double_extras.h d_randtest"+ d_randtest :: Ptr CFRandState -> IO CDouble++-- | /d_randtest_signed/ /state/ /minexp/ /maxexp/ +--+-- Returns a random signed number with exponent between @minexp@ and+-- @maxexp@ or zero.+foreign import ccall "double_extras.h d_randtest_signed"+ d_randtest_signed :: Ptr CFRandState -> CLong -> CLong -> IO CDouble++-- | /d_randtest_special/ /state/ /minexp/ /maxexp/ +--+-- Returns a random signed number with exponent between @minexp@ and+-- @maxexp@, zero, @D_NAN@ or \(\pm\)@D_INF@.+foreign import ccall "double_extras.h d_randtest_special"+ d_randtest_special :: Ptr CFRandState -> CLong -> CLong -> IO CDouble++-- Arithmetic ------------------------------------------------------------------++-- | /d_polyval/ /poly/ /len/ /x/ +--+-- Uses Horner\'s rule to evaluate the polynomial defined by the given+-- @len@ coefficients. Requires that @len@ is nonzero.+foreign import ccall "double_extras.h d_polyval"+ d_polyval :: Ptr CDouble -> CInt -> CDouble -> IO CDouble++-- Special functions -----------------------------------------------------------++-- | /d_lambertw/ /x/ +--+-- Computes the principal branch of the Lambert W function, solving the+-- equation \(x = W(x) \exp(W(x))\). If \(x < -1/e\), the solution is+-- complex, and NaN is returned.+-- +-- Depending on the magnitude of \(x\), we start from a piecewise rational+-- approximation or a zeroth-order truncation of the asymptotic expansion+-- at infinity, and perform 0, 1 or 2 iterations with Halley\'s method to+-- obtain full accuracy.+-- +-- A test of \(10^7\) random inputs showed a maximum relative error smaller+-- than 0.95 times @DBL_EPSILON@ (2^{-52}) for positive \(x\). Accuracy for+-- negative \(x\) is slightly worse, and can grow to about 10 times+-- @DBL_EPSILON@ close to \(-1/e\). However, accuracy may be worse+-- depending on compiler flags and the accuracy of the system libm+-- functions.+foreign import ccall "double_extras.h d_lambertw"+ d_lambertw :: CDouble -> IO CDouble++-- | /d_is_nan/ /x/ +--+-- Returns a nonzero integral value if @x@ is @D_NAN@, and otherwise+-- returns 0.+foreign import ccall "double_extras.h d_is_nan"+ d_is_nan :: CDouble -> IO CInt++-- | /d_log2/ /x/ +--+-- Returns the base 2 logarithm of @x@ provided @x@ is positive. If a+-- domain or pole error occurs, the appropriate error value is returned.+foreign import ccall "double_extras.h d_log2"+ d_log2 :: CDouble -> IO CDouble+
+ src/Data/Number/Flint/Support/D/Interval.hs view
@@ -0,0 +1,9 @@+{- |+This module provides helper functions for computing fast enclosures+using @double@ arithmetic.+-}+module Data.Number.Flint.Support.D.Interval (+ module Data.Number.Flint.Support.D.Interval.FFI+ ) where++import Data.Number.Flint.Support.D.Interval.FFI
+ src/Data/Number/Flint/Support/D/Interval/FFI.hsc view
@@ -0,0 +1,257 @@+{-|+module : Data.Number.Flint.Support.D.Interval.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Support.D.Interval.FFI (+ -- * Double-precision interval arithmetic and helpers+ Di (..)+ , CDi (..)+ -- * Basic manipulation+ , di_interval+ , arb_get_di+ , arb_set_di+ , di_print+ , di_randtest2+ , di_randtest+ -- * Arithmetic+ , di_neg+ -- * Fast arithmetic+ , di_fast_add+ , di_fast_sub+ , di_fast_mul+ , di_fast_div+ , di_fast_sqr+ , di_fast_add_d+ , di_fast_sub_d+ , di_fast_mul_d+ , di_fast_div_d+ , di_fast_log_nonnegative+ , di_fast_mid+ , di_fast_ubound_radius+) where++-- Double-precision interval arithmetic and helpers ----------------------------++import System.IO.Unsafe++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.C.String+import Foreign.Storable++import Text.Printf++import Data.Number.Flint.Flint+import Data.Number.Flint.Arb+import Data.Number.Flint.Arb.Types+import Data.Number.Flint.Arb.Arf+import Data.Number.Flint.Arb.Mag+import Data.Number.Flint.Support.D.Extras++#include <flint/double_interval.h>+#include <flint/double_extras.h>++d_inf = 1/0 :: CDouble ++-- di_t ------------------------------------------------------------------------++data Di = Di {-# UNPACK #-} !(ForeignPtr CDi)+data CDi = CDi CDouble CDouble deriving Show++instance Storable CDi where+ sizeOf _ = #{size di_t}+ alignment _ = #{alignment di_t}+ peek ptr = CDi+ <$> #{peek di_t, a} ptr+ <*> #{peek di_t, b} ptr+ poke ptr (CDi a b) = do+ #{poke di_t, a} ptr a+ #{poke di_t, b} ptr b+ ++-- Basic manipulation ----------------------------------------------------------++-- | /di_interval/ /a/ /b/ +--+-- Returns the interval \([a, b]\). We require that the endpoints are+-- ordered and not NaN.+di_interval :: CDouble -> CDouble -> CDi+di_interval a b =+ if a <= b+ then CDi a b+ else error $ printf "di_interval endpoints %g, %g not ordered.\n"+ (realToFrac a :: Double)+ (realToFrac b :: Double)++_di_below x =+ if x <= 1e300 then+ x - (1e-300 + if x < 0 then -x else x) * 4.440892098500626e-16+ else+ if x /= x then -d_inf else 1e300++_di_above x =+ if x >= -1e300 then+ x + (1e-300 + if x < 0 then -x else x) * 4.440892098500626e-16+ else+ if x /= x then d_inf else -1e300+ +-- | /arb_get_di/ /x/ +--+-- Returns the ball /x/ converted to a double-precision interval.+arb_get_di :: Ptr CArb -> IO CDi+arb_get_di x = do+ (_, result) <- withNewArf $ \t -> do+ arb_get_lbound_arf t x 53+ a <- arf_get_d t arf_rnd_floor+ arb_get_ubound_arf t x 53+ b <- arf_get_d t arf_rnd_ceil+ return $ CDi a b+ return result++-- | /arb_set_di/ /res/ /x/ /prec/ +--+-- Sets the ball /res/ to the double-precision interval /x/, rounded to+-- /prec/ bits.+arb_set_di :: Ptr CArb -> CDi -> CLong -> IO ()+arb_set_di res (CDi a b) prec = do+ withNewArf $ \t -> do+ withNewArf $ \u -> do+ arf_set_d t a+ arf_set_d u b+ arb_set_interval_arf res t u prec+ return ()++-- | /di_print/ /x/ +--+-- Prints /x/ to standard output. This simply prints decimal+-- representations of the floating-point endpoints; the decimals are not+-- guaranteed to be rounded outward.+di_print :: CDi -> IO ()+di_print (CDi a b) = do+ putStr $ printf "[%.17g, %.17g]" (realToFrac a :: Double)+ (realToFrac b :: Double)+ +-- | /d_randtest2/ /state/ +--+-- Returns a random non-NaN @double@ with any exponent. The value can be+-- infinite or subnormal.+di_randtest2 :: Ptr CFRandState -> IO CDouble+di_randtest2 state = do+ x <- d_randtest state+ return x+ +-- | /di_randtest/ /state/ +--+-- Returns an interval with random endpoints.+di_randtest :: Ptr CFRandState -> IO CDi+di_randtest state = do+ a <- d_randtest state+ b <- d_randtest state+ return $ if a > b then CDi b a else CDi a b+ ++-- Arithmetic ------------------------------------------------------------------++-- | /di_neg/ /x/ +--+-- Returns the exact negation of /x/.+di_neg :: CDi -> CDi+di_neg (CDi a b) = CDi (-b) a++-- Fast arithmetic -------------------------------------------------------------++-- The following methods perform fast but sloppy interval arithmetic: we+-- manipulate the endpoints with default rounding and then add or subtract+-- generic perturbations regardless of whether the operations were exact.+-- It is currently assumed that the CPU rounding mode is to nearest.+--+-- | /di_fast_add/ /x/ /y/ +di_fast_add :: CDi -> CDi -> CDi+di_fast_add (CDi a b) (CDi a' b') = CDi (_di_below (a+a')) (_di_above (b+b'))+ +-- | /di_fast_sub/ /x/ /y/ +di_fast_sub :: CDi -> CDi -> CDi+di_fast_sub (CDi a b) (CDi a' b') = CDi (_di_below (a-b')) (_di_above (b-a'))++-- | /di_fast_mul/ /x/ /y/ +di_fast_mul :: CDi -> CDi -> CDi+di_fast_mul (CDi xa xb) (CDi ya yb) = CDi (_di_below u) (_di_above v) where+ (u, v) + | xa > 0 && ya > 0 = (xa*ya, xb*yb)+ | xa > 0 && yb < 0 = (xb*ya, xa*yb)+ | xb < 0 && ya > 0 = (xa*yb, xb*ya)+ | xb < 0 && yb < 0 = (xb*yb, xa*ya)+ | a /= a || b /= b || c /= c || d /= d = (-d_inf, d_inf)+ | otherwise = (min (min a b) (min c d), max (max a b) (max c d))+ where+ a = xa * ya+ b = xa * yb+ c = xb * ya+ d = xb * yb+ +-- | /di_fast_div/ /x/ /y/ +--+-- Returns the sum, difference, product or quotient of /x/ and /y/.+-- Division by zero is currently defined to return \([-\infty, +\infty]\).+di_fast_div :: CDi -> CDi -> CDi+di_fast_div (CDi xa xb) (CDi ya yb) = CDi (_di_below u) (_di_above v) where+ (u, v)+ | ya > 0 && xa >= 0 = (xa/yb, xb/ya)+ | ya > 0 && xb <= 0 = (xa/ya, xb/yb)+ | ya > 0 = (xa/ya, xb/ya)+ | yb < 0 && xa >= 0 = (xb/yb, xa/ya)+ | yb < 0 && xb <= 0 = (xb/ya, xa/yb)+ | yb <0 = (xb/yb, xa/yb)+ | otherwise = (-d_inf, d_inf)++-- | /di_fast_sqr/ /x/ +--+-- Returns the square of /x/. The output is clamped to be nonnegative.+di_fast_sqr :: CDi -> CDi+di_fast_sqr (CDi a b) =+ CDi (if a /= 0 then _di_below u else u) (_di_above b) where+ (u, v)+ | a >= 0 = (a*a, b*b)+ | b <= 0 = (b*b, a*a)+ | otherwise = (0, max (a*a) (b*b))++-- | /di_fast_add_d/ /x/ /y/ +di_fast_add_d :: CDi -> CDouble -> CDi+di_fast_add_d x y = di_fast_add x (di_interval y y)+-- -- | /di_fast_sub_d/ /x/ /y/ +di_fast_sub_d :: CDi -> CDouble -> CDi+di_fast_sub_d x y = di_fast_sub x (di_interval y y)+-- | /di_fast_mul_d/ /x/ /y/+di_fast_mul_d :: CDi -> CDouble -> CDi+di_fast_mul_d x y = di_fast_mul x (di_interval y y)+-- | /di_fast_div_d/ /x/ /y/+-- Arithmetic with an exact @double@ operand.+di_fast_div_d :: CDi -> CDouble -> CDi+di_fast_div_d x y = di_fast_div x (di_interval y y)++-- | /di_fast_log_nonnegative/ /x/ +--+-- Returns an enclosure of \(\log(x)\). The lower endpoint of /x/ is+-- rounded up to 0 if it is negative.+di_fast_log_nonnegative :: CDi -> CDi+di_fast_log_nonnegative (CDi a b) = CDi a' b' where+ a' = if a <= 0 then (-d_inf) else mag_d_log_lower_bound a+ b' = mag_d_log_upper_bound b++-- | /di_fast_mid/ /x/ +--+-- Returns an enclosure of the midpoint of /x/.+di_fast_mid :: CDi -> CDi+di_fast_mid (CDi a b)+ | a == -d_inf || b == d_inf = di_interval (-d_inf) d_inf+ | otherwise = di_fast_mul_d (di_fast_add (di_interval a a)+ (di_interval b b)) 0.5+ +-- | /di_fast_ubound_radius/ /x/ +--+-- Returns an upper bound for the radius of /x/.+di_fast_ubound_radius :: CDi -> CDouble+di_fast_ubound_radius (CDi a b) = _di_above (0.5 * (b -a))
+ src/Data/Number/Flint/Support/D/Mat.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Support.D.Mat (+ module Data.Number.Flint.Support.D.Mat.FFI+ ) where++import Data.Number.Flint.Support.D.Mat.FFI
+ src/Data/Number/Flint/Support/D/Mat/FFI.hsc view
@@ -0,0 +1,302 @@+{-|+module : Data.Number.Flint.Support.D.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Support.D.Mat.FFI (+ -- * Double precision matrices+ DMat (..)+ , CDMat (..)+ -- * Smart constructors+ , newDMat+ , withDMat+ , withNewDMat+ -- * Memory management+ , d_mat_init+ , d_mat_clear+ -- * Basic assignment and manipulation+ , d_mat_set+ , d_mat_swap+ , d_mat_swap_entrywise+ , d_mat_entry+ , d_mat_get_entry+ , d_mat_entry_ptr+ , d_mat_zero+ , d_mat_one+ -- * Random matrix generation+ , d_mat_randtest+ -- * Input and output+ , d_mat_get_str+ , d_mat_fprint+ , d_mat_print + -- * Comparison+ , d_mat_equal+ , d_mat_approx_equal+ , d_mat_is_zero+ , d_mat_is_approx_zero+ , d_mat_is_empty+ , d_mat_is_square+ -- * Transpose+ , d_mat_transpose+ -- * Matrix multiplication+ , d_mat_mul_classical+ -- * Gram-Schmidt Orthogonalisation and QR Decomposition+ , d_mat_gso+ , d_mat_qr+) where ++-- double precision matrices ---------------------------------------------------++import Foreign.C.Types+import Foreign.C.String+import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable+import Foreign.Marshal.Array++import Data.Number.Flint.Flint++#include <flint/d_mat.h>++-- d_mat_t ---------------------------------------------------------------------++data DMat = DMat {-# UNPACK #-} !(ForeignPtr CDMat)+data CDMat = CDMat (Ptr CDouble) CLong CLong (Ptr (Ptr CDouble))++instance Storable CDMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size d_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment d_mat_t}+ peek ptr = CDMat+ <$> #{peek d_mat_struct, entries} ptr+ <*> #{peek d_mat_struct, r } ptr+ <*> #{peek d_mat_struct, c } ptr+ <*> #{peek d_mat_struct, rows } ptr+ poke = error "CDMat.poke: Not defined."++-- | /newDMat/ /rows/ /cols/+--+-- Construct new `DMat` with /rows/ rows and /cols/ columns.+newDMat rows cols = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> d_mat_init x rows cols+ addForeignPtrFinalizer p_d_mat_clear x+ return $ DMat x++-- | /withDMat/ /mat/ /f/+--+-- Apply /f/ to a /mat/.+{-# INLINE withDMat #-}+withDMat (DMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (DMat x,)++-- | /withNewDMat/ /rows/ /cols/ /f/+--+-- Apply /f/ to a new `DMat` with /rows/ rows and /cols/ columns.+{-# INLINE withNewDMat #-}+withNewDMat rows cols f = do+ x <- newDMat rows cols+ withDMat x f+ +-- Memory management -----------------------------------------------------------++-- | /d_mat_init/ /mat/ /rows/ /cols/ +-- +-- Initialises a matrix with the given number of rows and columns for use.+foreign import ccall "d_mat.h d_mat_init"+ d_mat_init :: Ptr CDMat -> CLong -> CLong -> IO ()++-- | /d_mat_clear/ /mat/ +-- +-- Clears the given matrix.+foreign import ccall "d_mat.h d_mat_clear"+ d_mat_clear :: Ptr CDMat -> IO ()++foreign import ccall "d_mat.h &d_mat_clear"+ p_d_mat_clear :: FunPtr (Ptr CDMat -> IO ())++-- Basic assignment and manipulation -------------------------------------------++-- | /d_mat_set/ /mat1/ /mat2/ +-- +-- Sets @mat1@ to a copy of @mat2@. The dimensions of @mat1@ and @mat2@+-- must be the same.+foreign import ccall "d_mat.h d_mat_set"+ d_mat_set :: Ptr CDMat -> Ptr CDMat -> IO ()++-- | /d_mat_swap/ /mat1/ /mat2/ +-- +-- Swaps two matrices. The dimensions of @mat1@ and @mat2@ are allowed to+-- be different.+foreign import ccall "d_mat.h d_mat_swap"+ d_mat_swap :: Ptr CDMat -> Ptr CDMat -> IO ()++-- | /d_mat_swap_entrywise/ /mat1/ /mat2/ +-- +-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "d_mat.h d_mat_swap_entrywise"+ d_mat_swap_entrywise :: Ptr CDMat -> Ptr CDMat -> IO ()++-- | /d_mat_entry/ /mat/ /i/ /j/ +-- +-- Returns the entry of @mat@ at row \(i\) and column \(j\). Both \(i\) and+-- \(j\) must not exceed the dimensions of the matrix. This function is+-- implemented as a macro.+d_mat_entry :: Ptr CDMat -> CLong -> CLong -> IO CDouble+d_mat_entry mat i j = do+ CDMat _ r c rows <- peek mat+ row_i <- peek (rows `advancePtr` (fromIntegral i))+ result <- peek (row_i `advancePtr` (fromIntegral j))+ return result+ +-- | /d_mat_get_entry/ /mat/ /i/ /j/ +-- +-- Returns the entry of @mat@ at row \(i\) and column \(j\). Both \(i\) and+-- \(j\) must not exceed the dimensions of the matrix.+foreign import ccall "d_mat.h d_mat_get_entry"+ d_mat_get_entry :: Ptr CDMat -> CLong -> CLong -> IO CDouble++-- | /d_mat_entry_ptr/ /mat/ /i/ /j/ +-- +-- Returns a pointer to the entry of @mat@ at row \(i\) and column \(j\).+-- Both \(i\) and \(j\) must not exceed the dimensions of the matrix.+foreign import ccall "d_mat.h d_mat_entry_ptr"+ d_mat_entry_ptr :: Ptr CDMat -> CLong -> CLong -> IO (Ptr CDouble)++-- | /d_mat_zero/ /mat/ +-- +-- Sets all entries of @mat@ to 0.+foreign import ccall "d_mat.h d_mat_zero"+ d_mat_zero :: Ptr CDMat -> IO ()++-- | /d_mat_one/ /mat/ +-- +-- Sets @mat@ to the unit matrix, having ones on the main diagonal and+-- zeroes elsewhere. If @mat@ is nonsquare, it is set to the truncation of+-- a unit matrix.+foreign import ccall "d_mat.h d_mat_one"+ d_mat_one :: Ptr CDMat -> IO ()++-- Random matrix generation ----------------------------------------------------++-- | /d_mat_randtest/ /mat/ /state/ /minexp/ /maxexp/ +-- +-- Sets the entries of @mat@ to random signed numbers with exponents+-- between @minexp@ and @maxexp@ or zero.+foreign import ccall "d_mat.h d_mat_randtest"+ d_mat_randtest :: Ptr CDMat -> Ptr CFRandState -> CLong -> CLong -> IO ()++-- Input and output ------------------------------------------------------------++-- | /d_mat_get_str/ /mat/ +-- +-- Returns a string representation of the given matrix.+foreign import ccall "d_mat.h d_mat_get_str"+ d_mat_get_str :: Ptr CDMat -> IO CString++-- | /d_mat_fprint/ /file/ /mat/ +-- +-- Prints the given matrix to the stream @stdout@.+foreign import ccall "d_mat.h d_mat_fprint"+ d_mat_fprint :: Ptr CFile -> Ptr CDMat -> IO ()++-- | /d_mat_print/ /mat/ +-- +-- Prints the given matrix to the stream @stdout@.+d_mat_print :: Ptr CDMat -> IO ()+d_mat_print mat = do+ printCStr d_mat_get_str mat+ return ()++-- Comparison ------------------------------------------------------------------++-- | /d_mat_equal/ /mat1/ /mat2/ +-- +-- Returns a non-zero value if @mat1@ and @mat2@ have the same dimensions+-- and entries, and zero otherwise.+foreign import ccall "d_mat.h d_mat_equal"+ d_mat_equal :: Ptr CDMat -> Ptr CDMat -> IO CInt++-- | /d_mat_approx_equal/ /mat1/ /mat2/ /eps/ +-- +-- Returns a non-zero value if @mat1@ and @mat2@ have the same dimensions+-- and entries within @eps@ of each other, and zero otherwise.+foreign import ccall "d_mat.h d_mat_approx_equal"+ d_mat_approx_equal :: Ptr CDMat -> Ptr CDMat -> CDouble -> IO CInt++-- | /d_mat_is_zero/ /mat/ +-- +-- Returns a non-zero value if all entries @mat@ are zero, and otherwise+-- returns zero.+foreign import ccall "d_mat.h d_mat_is_zero"+ d_mat_is_zero :: Ptr CDMat -> IO CInt++-- | /d_mat_is_approx_zero/ /mat/ /eps/ +-- +-- Returns a non-zero value if all entries @mat@ are zero to within @eps@+-- and otherwise returns zero.+foreign import ccall "d_mat.h d_mat_is_approx_zero"+ d_mat_is_approx_zero :: Ptr CDMat -> CDouble -> IO CInt++-- | /d_mat_is_empty/ /mat/ +-- +-- Returns a non-zero value if the number of rows or the number of columns+-- in @mat@ is zero, and otherwise returns zero.+foreign import ccall "d_mat.h d_mat_is_empty"+ d_mat_is_empty :: Ptr CDMat -> IO CInt++-- | /d_mat_is_square/ /mat/ +-- +-- Returns a non-zero value if the number of rows is equal to the number of+-- columns in @mat@, and otherwise returns zero.+foreign import ccall "d_mat.h d_mat_is_square"+ d_mat_is_square :: Ptr CDMat -> IO CInt++-- Transpose -------------------------------------------------------------------++-- | /d_mat_transpose/ /B/ /A/ +-- +-- Sets \(B\) to \(A^T\), the transpose of \(A\). Dimensions must be+-- compatible. \(A\) and \(B\) are allowed to be the same object if \(A\)+-- is a square matrix.+foreign import ccall "d_mat.h d_mat_transpose"+ d_mat_transpose :: Ptr CDMat -> Ptr CDMat -> IO ()++-- Matrix multiplication -------------------------------------------------------++-- | /d_mat_mul_classical/ /C/ /A/ /B/ +-- +-- Sets @C@ to the matrix product \(C = A B\). The matrices must have+-- compatible dimensions for matrix multiplication (an exception is raised+-- otherwise). Aliasing is allowed.+foreign import ccall "d_mat.h d_mat_mul_classical"+ d_mat_mul_classical :: Ptr CDMat -> Ptr CDMat -> Ptr CDMat -> IO ()++-- Gram-Schmidt Orthogonalisation and QR Decomposition -------------------------++-- | /d_mat_gso/ /B/ /A/ +-- +-- Takes a subset of \(R^m\) \(S = {a_1, a_2, \ldots, a_n}\) (as the+-- columns of a \(m x n\) matrix @A@) and generates an orthonormal set+-- \(S' = {b_1, b_2, \ldots, b_n}\) (as the columns of the \(m x n\) matrix+-- @B@) that spans the same subspace of \(R^m\) as \(S\).+-- +-- This uses an algorithm of Schwarz-Rutishauser. See pp. 9 of+-- <https://people.inf.ethz.ch/gander/papers/qrneu.pdf>+foreign import ccall "d_mat.h d_mat_gso"+ d_mat_gso :: Ptr CDMat -> Ptr CDMat -> IO ()++-- | /d_mat_qr/ /Q/ /R/ /A/ +-- +-- Computes the \(QR\) decomposition of a matrix @A@ using the Gram-Schmidt+-- process. (Sets @Q@ and @R@ such that \(A = QR\) where @R@ is an upper+-- triangular matrix and @Q@ is an orthogonal matrix.)+-- +-- This uses an algorithm of Schwarz-Rutishauser. See pp. 9 of+-- <https://people.inf.ethz.ch/gander/papers/qrneu.pdf>+foreign import ccall "d_mat.h d_mat_qr"+ d_mat_qr :: Ptr CDMat -> Ptr CDMat -> Ptr CDMat -> IO ()+
+ src/Data/Number/Flint/Support/D/Mat/Instances.hs view
@@ -0,0 +1,16 @@+{-# OPTIONS_HADDOCK hide, prune, ignore-exports #-}+module Data.Number.Flint.Support.D.Mat.Instances where++import System.IO.Unsafe+import Foreign.C.String+import Foreign.Marshal.Alloc ( free )++import Data.Number.Flint.Support.D.Mat++instance Show DMat where+ show x = unsafePerformIO $ do+ (_, cs) <- withDMat x d_mat_get_str+ s <- peekCString cs+ free cs+ return s+
+ src/Data/Number/Flint/Support/D/Vec.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Support.D.Vec (+ module Data.Number.Flint.Support.D.Vec.FFI+ ) where++import Data.Number.Flint.Support.D.Vec.FFI
+ src/Data/Number/Flint/Support/D/Vec/FFI.hsc view
@@ -0,0 +1,154 @@+{-|+module : Data.Number.Flint.Support.D.Vec.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Support.D.Vec.FFI (+ -- * Double precision vectors+ -- * Memory management+ _d_vec_init+ , _d_vec_clear+ -- * Randomisation+ , _d_vec_randtest+ -- * Assignment and basic manipulation+ , _d_vec_set+ , _d_vec_zero+ -- * Comparison+ , _d_vec_equal+ , _d_vec_is_zero+ , _d_vec_is_approx_zero+ , _d_vec_approx_equal+ -- * Addition and subtraction+ , _d_vec_add+ , _d_vec_sub+ -- * Dot product and norm+ , _d_vec_dot+ , _d_vec_norm+ , _d_vec_dot_heuristic+ , _d_vec_dot_thrice+) where ++-- Double precision vectors ----------------------------------------------------++import Foreign.Ptr+import Foreign.C.Types++import Data.Number.Flint.Flint++-- Memory management -----------------------------------------------------------++-- | /_d_vec_init/ /len/ +-- +-- Returns an initialised vector of @double@s of given length. The entries+-- are not zeroed.+foreign import ccall "d_vec.h _d_vec_init"+ _d_vec_init :: CLong -> IO (Ptr CDouble)++-- | /_d_vec_clear/ /vec/ +-- +-- Frees the space allocated for @vec@.+foreign import ccall "d_vec.h _d_vec_clear"+ _d_vec_clear :: Ptr CDouble -> IO ()++-- Randomisation ---------------------------------------------------------------++-- | /_d_vec_randtest/ /f/ /state/ /len/ /minexp/ /maxexp/ +-- +-- Sets the entries of a vector of the given length to random signed+-- numbers with exponents between @minexp@ and @maxexp@ or zero.+foreign import ccall "d_vec.h _d_vec_randtest"+ _d_vec_randtest :: Ptr CDouble -> Ptr CFRandState -> CLong -> CLong -> CLong -> IO ()++-- Assignment and basic manipulation -------------------------------------------++-- | /_d_vec_set/ /vec1/ /vec2/ /len2/ +-- +-- Makes a copy of @(vec2, len2)@ into @vec1@.+foreign import ccall "d_vec.h _d_vec_set"+ _d_vec_set :: Ptr CDouble -> Ptr CDouble -> CLong -> IO ()++-- | /_d_vec_zero/ /vec/ /len/ +-- +-- Zeros the entries of @(vec, len)@.+foreign import ccall "d_vec.h _d_vec_zero"+ _d_vec_zero :: Ptr CDouble -> CLong -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /_d_vec_equal/ /vec1/ /vec2/ /len/ +-- +-- Compares two vectors of the given length and returns \(1\) if they are+-- equal, otherwise returns \(0\).+foreign import ccall "d_vec.h _d_vec_equal"+ _d_vec_equal :: Ptr CDouble -> Ptr CDouble -> CLong -> IO CInt++-- | /_d_vec_is_zero/ /vec/ /len/ +-- +-- Returns \(1\) if @(vec, len)@ is zero, and \(0\) otherwise.+foreign import ccall "d_vec.h _d_vec_is_zero"+ _d_vec_is_zero :: Ptr CDouble -> CLong -> IO CInt++-- | /_d_vec_is_approx_zero/ /vec/ /len/ /eps/ +-- +-- Returns \(1\) if the entries of @(vec, len)@ are zero to within @eps@,+-- and \(0\) otherwise.+foreign import ccall "d_vec.h _d_vec_is_approx_zero"+ _d_vec_is_approx_zero :: Ptr CDouble -> CLong -> CDouble -> IO CInt++-- | /_d_vec_approx_equal/ /vec1/ /vec2/ /len/ /eps/ +-- +-- Compares two vectors of the given length and returns \(1\) if their+-- entries are within @eps@ of each other, otherwise returns \(0\).+foreign import ccall "d_vec.h _d_vec_approx_equal"+ _d_vec_approx_equal :: Ptr CDouble -> Ptr CDouble -> CLong -> CDouble -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /_d_vec_add/ /res/ /vec1/ /vec2/ /len2/ +-- +-- Sets @(res, len2)@ to the sum of @(vec1, len2)@ and @(vec2, len2)@.+foreign import ccall "d_vec.h _d_vec_add"+ _d_vec_add :: Ptr CDouble -> Ptr CDouble -> Ptr CDouble -> CLong -> IO ()++-- | /_d_vec_sub/ /res/ /vec1/ /vec2/ /len2/ +-- +-- Sets @(res, len2)@ to @(vec1, len2)@ minus @(vec2, len2)@.+foreign import ccall "d_vec.h _d_vec_sub"+ _d_vec_sub :: Ptr CDouble -> Ptr CDouble -> Ptr CDouble -> CLong -> IO ()++-- Dot product and norm --------------------------------------------------------++-- | /_d_vec_dot/ /vec1/ /vec2/ /len2/ +-- +-- Returns the dot product of @(vec1, len2)@ and @(vec2, len2)@.+foreign import ccall "d_vec.h _d_vec_dot"+ _d_vec_dot :: Ptr CDouble -> Ptr CDouble -> CLong -> IO CDouble++-- | /_d_vec_norm/ /vec/ /len/ +-- +-- Returns the square of the Euclidean norm of @(vec, len)@.+foreign import ccall "d_vec.h _d_vec_norm"+ _d_vec_norm :: Ptr CDouble -> CLong -> IO CDouble++-- | /_d_vec_dot_heuristic/ /vec1/ /vec2/ /len2/ /err/ +-- +-- Returns the dot product of @(vec1, len2)@ and @(vec2, len2)@ by adding+-- up the positive and negative products, and doing a single subtraction of+-- the two sums at the end. @err@ is a pointer to a double in which an+-- error bound for the operation will be stored.+foreign import ccall "d_vec.h _d_vec_dot_heuristic"+ _d_vec_dot_heuristic :: Ptr CDouble -> Ptr CDouble -> CLong -> Ptr CDouble -> IO CDouble++-- | /_d_vec_dot_thrice/ /vec1/ /vec2/ /len2/ /err/ +-- +-- Returns the dot product of @(vec1, len2)@ and @(vec2, len2)@ using+-- error-free floating point sums and products to compute the dot product+-- with three times (thrice) the working precision. @err@ is a pointer to a+-- double in which an error bound for the operation will be stored.+-- +-- This implements the algorithm of Ogita-Rump-Oishi. See+-- <http://www.ti3.tuhh.de/paper/rump/OgRuOi05.pdf>.+foreign import ccall "d_vec.h _d_vec_dot_thrice"+ _d_vec_dot_thrice :: Ptr CDouble -> Ptr CDouble -> CLong -> Ptr CDouble -> IO CDouble+
+ src/Data/Number/Flint/Support/Mpf/Mat.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Support.Mpf.Mat (+ module Data.Number.Flint.Support.Mpf.Mat.FFI+ ) where++import Data.Number.Flint.Support.Mpf.Mat.FFI
+ src/Data/Number/Flint/Support/Mpf/Mat/FFI.hsc view
@@ -0,0 +1,241 @@+{-|+module : Data.Number.Flint.Support.Mpf.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Support.Mpf.Mat.FFI (+ -- * Matrices of MPF floating-point numbers+ MpfMat (..)+ , CMpfMat (..)+ , newMpfMat+ , withMpfMat+ , withNewMpfMat+ -- * Memory management+ , mpf_mat_init+ , mpf_mat_clear+ -- * Basic assignment and manipulation+ , mpf_mat_set+ , mpf_mat_swap+ , mpf_mat_swap_entrywise+ , mpf_mat_entry+ , mpf_mat_zero+ , mpf_mat_one+ -- * Random matrix generation+ , mpf_mat_randtest+ -- * Input and output+ , mpf_mat_print+ -- * Comparison+ , mpf_mat_equal+ , mpf_mat_approx_equal+ , mpf_mat_is_zero+ , mpf_mat_is_empty+ , mpf_mat_is_square+ -- * Matrix multiplication+ , mpf_mat_mul+ -- * Gram-Schmidt Orthogonalisation and QR Decomposition+ , mpf_mat_gso+ , mpf_mat_qr+) where ++-- matrices of MPF floating-point numbers --------------------------------------++import Foreign.C.Types+import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable+import Foreign.Marshal.Array++import Data.Number.Flint.Flint++#include <flint/flint.h>+#include <flint/mpf_mat.h>++-- mpf_mat_t -------------------------------------------------------------------++data MpfMat = MpfMat {-# UNPACK #-} !(ForeignPtr CMpfMat)+data CMpfMat = CMpfMat (Ptr CMpf) CLong CLong (Ptr (Ptr CMpf))++instance Storable CMpfMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size mpf_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment mpf_mat_t}+ peek ptr = CMpfMat+ <$> #{peek mpf_mat_struct, entries} ptr+ <*> #{peek mpf_mat_struct, r } ptr+ <*> #{peek mpf_mat_struct, c } ptr+ <*> #{peek mpf_mat_struct, rows } ptr+ poke = error "CMpfMat.poke: Not defined."++newMpfMat rows cols prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> mpf_mat_init x rows cols prec+ addForeignPtrFinalizer p_mpf_mat_clear x+ return $ MpfMat x++{-# INLINE withMpfMat #-}+withMpfMat (MpfMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (MpfMat x,)++withNewMpfMat rows cols prec f = do+ x <- newMpfMat rows cols prec+ withMpfMat x f+ +-- Memory management -----------------------------------------------------------++-- | /mpf_mat_init/ /mat/ /rows/ /cols/ /prec/ +-- +-- Initialises a matrix with the given number of rows and columns and the+-- given precision for use. The precision is at least the precision of the+-- entries.+foreign import ccall "mpf_mat.h mpf_mat_init"+ mpf_mat_init :: Ptr CMpfMat -> CLong -> CLong -> CFBitCnt -> IO ()++-- | /mpf_mat_clear/ /mat/ +-- +-- Clears the given matrix.+foreign import ccall "mpf_mat.h mpf_mat_clear"+ mpf_mat_clear :: Ptr CMpfMat -> IO ()++foreign import ccall "mpf_mat.h &mpf_mat_clear"+ p_mpf_mat_clear :: FunPtr (Ptr CMpfMat -> IO ())++-- Basic assignment and manipulation -------------------------------------------++-- | /mpf_mat_set/ /mat1/ /mat2/ +-- +-- Sets @mat1@ to a copy of @mat2@. The dimensions of @mat1@ and @mat2@+-- must be the same.+foreign import ccall "mpf_mat.h mpf_mat_set"+ mpf_mat_set :: Ptr CMpfMat -> Ptr CMpfMat -> IO ()++-- | /mpf_mat_swap/ /mat1/ /mat2/ +-- +-- Swaps two matrices. The dimensions of @mat1@ and @mat2@ are allowed to+-- be different.+foreign import ccall "mpf_mat.h mpf_mat_swap"+ mpf_mat_swap :: Ptr CMpfMat -> Ptr CMpfMat -> IO ()++-- | /mpf_mat_swap_entrywise/ /mat1/ /mat2/ +-- +-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "mpf_mat.h mpf_mat_swap_entrywise"+ mpf_mat_swap_entrywise :: Ptr CMpfMat -> Ptr CMpfMat -> IO ()++-- | /mpf_mat_entry/ /mat/ /i/ /j/ +-- +-- Returns a reference to the entry of @mat@ at row \(i\) and column \(j\).+-- Both \(i\) and \(j\) must not exceed the dimensions of the matrix. The+-- return value can be used to either retrieve or set the given entry.+mpf_mat_entry :: Ptr CMpfMat -> CLong -> CLong -> IO (Ptr CMpf)+mpf_mat_entry mat i j = do+ CMpfMat entries r c rows <- peek mat+ return $ entries `advancePtr` (fromIntegral (i*c + j))++-- | /mpf_mat_zero/ /mat/ +-- +-- Sets all entries of @mat@ to 0.+foreign import ccall "mpf_mat.h mpf_mat_zero"+ mpf_mat_zero :: Ptr CMpfMat -> IO ()++-- | /mpf_mat_one/ /mat/ +-- +-- Sets @mat@ to the unit matrix, having ones on the main diagonal and+-- zeroes elsewhere. If @mat@ is nonsquare, it is set to the truncation of+-- a unit matrix.+foreign import ccall "mpf_mat.h mpf_mat_one"+ mpf_mat_one :: Ptr CMpfMat -> IO ()++-- Random matrix generation ----------------------------------------------------++-- | /mpf_mat_randtest/ /mat/ /state/ /bits/ +-- +-- Sets the entries of @mat@ to random numbers in the interval \([0, 1)\)+-- with @bits@ significant bits in the mantissa or less if their precision+-- is smaller.+foreign import ccall "mpf_mat.h mpf_mat_randtest"+ mpf_mat_randtest :: Ptr CMpfMat -> Ptr CFRandState -> CFBitCnt -> IO ()++-- Input and output ------------------------------------------------------------++-- | /mpf_mat_print/ /mat/ +-- +-- Prints the given matrix to the stream @stdout@.+foreign import ccall "mpf_mat.h mpf_mat_print"+ mpf_mat_print :: Ptr CMpfMat -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /mpf_mat_equal/ /mat1/ /mat2/ +-- +-- Returns a non-zero value if @mat1@ and @mat2@ have the same dimensions+-- and entries, and zero otherwise.+foreign import ccall "mpf_mat.h mpf_mat_equal"+ mpf_mat_equal :: Ptr CMpfMat -> Ptr CMpfMat -> IO CInt++-- | /mpf_mat_approx_equal/ /mat1/ /mat2/ /bits/ +-- +-- Returns a non-zero value if @mat1@ and @mat2@ have the same dimensions+-- and the first @bits@ bits of their entries are equal, and zero+-- otherwise.+foreign import ccall "mpf_mat.h mpf_mat_approx_equal"+ mpf_mat_approx_equal :: Ptr CMpfMat -> Ptr CMpfMat -> CFBitCnt -> IO CInt++-- | /mpf_mat_is_zero/ /mat/ +-- +-- Returns a non-zero value if all entries @mat@ are zero, and otherwise+-- returns zero.+foreign import ccall "mpf_mat.h mpf_mat_is_zero"+ mpf_mat_is_zero :: Ptr CMpfMat -> IO CInt++-- | /mpf_mat_is_empty/ /mat/ +-- +-- Returns a non-zero value if the number of rows or the number of columns+-- in @mat@ is zero, and otherwise returns zero.+foreign import ccall "mpf_mat.h mpf_mat_is_empty"+ mpf_mat_is_empty :: Ptr CMpfMat -> IO CInt++-- | /mpf_mat_is_square/ /mat/ +-- +-- Returns a non-zero value if the number of rows is equal to the number of+-- columns in @mat@, and otherwise returns zero.+foreign import ccall "mpf_mat.h mpf_mat_is_square"+ mpf_mat_is_square :: Ptr CMpfMat -> IO CInt++-- Matrix multiplication -------------------------------------------------------++-- | /mpf_mat_mul/ /C/ /A/ /B/ +-- +-- Sets @C@ to the matrix product \(C = A B\). The matrices must have+-- compatible dimensions for matrix multiplication (an exception is raised+-- otherwise). Aliasing is allowed.+foreign import ccall "mpf_mat.h mpf_mat_mul"+ mpf_mat_mul :: Ptr CMpfMat -> Ptr CMpfMat -> Ptr CMpfMat -> IO ()++-- Gram-Schmidt Orthogonalisation and QR Decomposition -------------------------++-- | /mpf_mat_gso/ /B/ /A/ +-- +-- Takes a subset of \(R^m\) \(S = {a_1, a_2, \ldots ,a_n}\) (as the+-- columns of a \(m x n\) matrix @A@) and generates an orthonormal set+-- \(S' = {b_1, b_2, \ldots ,b_n}\) (as the columns of the \(m x n\) matrix+-- @B@) that spans the same subspace of \(R^m\) as \(S\).+-- +-- This uses an algorithm of Schwarz-Rutishauser. See pp. 9 of+-- <https://people.inf.ethz.ch/gander/papers/qrneu.pdf>+foreign import ccall "mpf_mat.h mpf_mat_gso"+ mpf_mat_gso :: Ptr CMpfMat -> Ptr CMpfMat -> IO ()++-- | /mpf_mat_qr/ /Q/ /R/ /A/ +-- +-- Computes the \(QR\) decomposition of a matrix @A@ using the Gram-Schmidt+-- process. (Sets @Q@ and @R@ such that \(A = QR\) where @R@ is an upper+-- triangular matrix and @Q@ is an orthogonal matrix.)+-- +-- This uses an algorithm of Schwarz-Rutishauser. See pp. 9 of+-- <https://people.inf.ethz.ch/gander/papers/qrneu.pdf>+foreign import ccall "mpf_mat.h mpf_mat_qr"+ mpf_mat_qr :: Ptr CMpfMat -> Ptr CMpfMat -> Ptr CMpfMat -> IO ()+
+ src/Data/Number/Flint/Support/Mpf/Vec.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Support.Mpf.Vec (+ module Data.Number.Flint.Support.Mpf.Vec.FFI+ ) where++import Data.Number.Flint.Support.Mpf.Vec.FFI
+ src/Data/Number/Flint/Support/Mpf/Vec/FFI.hsc view
@@ -0,0 +1,175 @@+{-|+module : Data.Number.Flint.Support.Mpf.Vec.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Support.Mpf.Vec.FFI (+ -- * Vectors of MPF floating-point numbers+ -- * Memory management+ _mpf_vec_init+ , _mpf_vec_clear+ -- * Randomisation+ , _mpf_vec_randtest+ -- * Assignment and basic manipulation+ , _mpf_vec_zero+ , _mpf_vec_set+ -- * Conversion+ , _mpf_vec_set_fmpz_vec+ -- * Comparison+ , _mpf_vec_equal+ , _mpf_vec_is_zero+ , _mpf_vec_approx_equal+ -- * Addition and subtraction+ , _mpf_vec_add+ , _mpf_vec_sub+ -- * Scalar multiplication+ , _mpf_vec_scalar_mul_mpf+ , _mpf_vec_scalar_mul_2exp+ -- * Dot product and norm+ , _mpf_vec_dot+ , _mpf_vec_norm+ , _mpf_vec_dot2+ , _mpf_vec_norm2+) where ++-- Vectors of MPF floating-point numbers ---------------------------------------++import Foreign.Ptr+import Foreign.C.Types++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz++-- Memory management -----------------------------------------------------------++-- | /_mpf_vec_init/ /len/ +-- +-- Returns a vector of the given length of initialised @mpf@\'s with at+-- least the given precision.+foreign import ccall "mpf_vec.h _mpf_vec_init"+ _mpf_vec_init :: CLong -> IO (Ptr CMpf)++-- | /_mpf_vec_clear/ /vec/ /len/ +-- +-- Clears the given vector.+foreign import ccall "mpf_vec.h _mpf_vec_clear"+ _mpf_vec_clear :: Ptr CMpf -> CLong -> IO ()++-- Randomisation ---------------------------------------------------------------++-- | /_mpf_vec_randtest/ /f/ /state/ /len/ /bits/ +-- +-- Sets the entries of a vector of the given length to random numbers in+-- the interval \([0, 1)\) with @bits@ significant bits in the mantissa or+-- less if their precision is smaller.+foreign import ccall "mpf_vec.h _mpf_vec_randtest"+ _mpf_vec_randtest :: Ptr CMpf -> Ptr CFRandState -> CLong -> CFBitCnt -> IO ()++-- Assignment and basic manipulation -------------------------------------------++-- | /_mpf_vec_zero/ /vec/ /len/ +-- +-- Zeros the vector @(vec, len)@.+foreign import ccall "mpf_vec.h _mpf_vec_zero"+ _mpf_vec_zero :: Ptr CMpf -> CLong -> IO ()++-- | /_mpf_vec_set/ /vec1/ /vec2/ /len2/ +-- +-- Copies the vector @vec2@ of the given length into @vec1@. A check is+-- made to ensure @vec1@ and @vec2@ are different.+foreign import ccall "mpf_vec.h _mpf_vec_set"+ _mpf_vec_set :: Ptr CMpf -> Ptr CMpf -> CLong -> IO ()++-- Conversion ------------------------------------------------------------------++-- | /_mpf_vec_set_fmpz_vec/ /appv/ /vec/ /len/ +-- +-- Export the array of @len@ entries starting at the pointer @vec@ to an+-- array of mpfs @appv@.+foreign import ccall "mpf_vec.h _mpf_vec_set_fmpz_vec"+ _mpf_vec_set_fmpz_vec :: Ptr CMpf -> Ptr CFmpz -> CLong -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /_mpf_vec_equal/ /vec1/ /vec2/ /len/ +-- +-- Compares two vectors of the given length and returns \(1\) if they are+-- equal, otherwise returns \(0\).+foreign import ccall "mpf_vec.h _mpf_vec_equal"+ _mpf_vec_equal :: Ptr CMpf -> Ptr CMpf -> CLong -> IO CInt++-- | /_mpf_vec_is_zero/ /vec/ /len/ +-- +-- Returns \(1\) if @(vec, len)@ is zero, and \(0\) otherwise.+foreign import ccall "mpf_vec.h _mpf_vec_is_zero"+ _mpf_vec_is_zero :: Ptr CMpf -> CLong -> IO CInt++-- | /_mpf_vec_approx_equal/ /vec1/ /vec2/ /len/ /bits/ +-- +-- Compares two vectors of the given length and returns \(1\) if the first+-- @bits@ bits of their entries are equal, otherwise returns \(0\).+foreign import ccall "mpf_vec.h _mpf_vec_approx_equal"+ _mpf_vec_approx_equal :: Ptr CMpf -> Ptr CMpf -> CLong -> CFBitCnt -> IO CInt++-- Addition and subtraction ----------------------------------------------------++-- | /_mpf_vec_add/ /res/ /vec1/ /vec2/ /len2/ +-- +-- Adds the given vectors of the given length together and stores the+-- result in @res@.+foreign import ccall "mpf_vec.h _mpf_vec_add"+ _mpf_vec_add :: Ptr CMpf -> Ptr CMpf -> Ptr CMpf -> CLong -> IO ()++-- | /_mpf_vec_sub/ /res/ /vec1/ /vec2/ /len2/ +-- +-- Sets @(res, len2)@ to @(vec1, len2)@ minus @(vec2, len2)@.+foreign import ccall "mpf_vec.h _mpf_vec_sub"+ _mpf_vec_sub :: Ptr CMpf -> Ptr CMpf -> Ptr CMpf -> CLong -> IO ()++-- Scalar multiplication -------------------------------------------------------++-- | /_mpf_vec_scalar_mul_mpf/ /res/ /vec/ /len/ /c/ +-- +-- Multiplies the vector with given length by the scalar \(c\) and sets+-- @res@ to the result.+foreign import ccall "mpf_vec.h _mpf_vec_scalar_mul_mpf"+ _mpf_vec_scalar_mul_mpf :: Ptr CMpf -> Ptr CMpf -> CLong -> Ptr CMpf -> IO ()++-- | /_mpf_vec_scalar_mul_2exp/ /res/ /vec/ /len/ /exp/ +-- +-- Multiplies the given vector of the given length by @2^exp@.+foreign import ccall "mpf_vec.h _mpf_vec_scalar_mul_2exp"+ _mpf_vec_scalar_mul_2exp :: Ptr CMpf -> Ptr CMpf -> CLong -> CFBitCnt -> IO ()++-- Dot product and norm --------------------------------------------------------++-- | /_mpf_vec_dot/ /res/ /vec1/ /vec2/ /len2/ +-- +-- Sets @res@ to the dot product of @(vec1, len2)@ with @(vec2, len2)@.+foreign import ccall "mpf_vec.h _mpf_vec_dot"+ _mpf_vec_dot :: Ptr CMpf -> Ptr CMpf -> Ptr CMpf -> CLong -> IO ()++-- | /_mpf_vec_norm/ /res/ /vec/ /len/ +-- +-- Sets @res@ to the square of the Euclidean norm of @(vec, len)@.+foreign import ccall "mpf_vec.h _mpf_vec_norm"+ _mpf_vec_norm :: Ptr CMpf -> Ptr CMpf -> CLong -> IO ()++-- | /_mpf_vec_dot2/ /res/ /vec1/ /vec2/ /len2/ /prec/ +-- +-- Sets @res@ to the dot product of @(vec1, len2)@ with @(vec2, len2)@. The+-- temporary variable used has its precision set to be at least @prec@+-- bits. Returns 0 if a probable cancellation is detected, and otherwise+-- returns a non-zero value.+foreign import ccall "mpf_vec.h _mpf_vec_dot2"+ _mpf_vec_dot2 :: Ptr CMpf -> Ptr CMpf -> Ptr CMpf -> CLong -> CFBitCnt -> IO CInt++-- | /_mpf_vec_norm2/ /res/ /vec/ /len/ /prec/ +-- +-- Sets @res@ to the square of the Euclidean norm of @(vec, len)@. The+-- temporary variable used has its precision set to be at least @prec@+-- bits.+foreign import ccall "mpf_vec.h _mpf_vec_norm2"+ _mpf_vec_norm2 :: Ptr CMpf -> Ptr CMpf -> CLong -> CFBitCnt -> IO ()+
+ src/Data/Number/Flint/Support/Mpfr/Mat.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Support.Mpfr.Mat (+ module Data.Number.Flint.Support.Mpfr.Mat.FFI+ ) where++import Data.Number.Flint.Support.Mpfr.Mat.FFI
+ src/Data/Number/Flint/Support/Mpfr/Mat/FFI.hsc view
@@ -0,0 +1,151 @@+{-|+module : Data.Number.Flint.Support.Mpfr.Mat.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Support.Mpfr.Mat.FFI (+ -- * Matrices of MPFR floating-point numbers+ MpfrMat (..)+ , CMpfrMat (..)+ , newMpfrMat+ , withMpfrMat+ , withNewMpfrMat+ -- * Memory management+ , mpfr_mat_init+ , mpfr_mat_clear+ -- * Basic manipulation+ , mpfr_mat_swap+ , mpfr_mat_swap_entrywise+ , mpfr_mat_entry+ , mpfr_mat_set+ , mpfr_mat_zero+ -- * Comparison+ , mpfr_mat_equal+ -- * Randomisation+ , mpfr_mat_randtest+ -- * Basic arithmetic+ , mpfr_mat_mul_classical+) where++-- Matrices of MPFR floating-point numbers -------------------------------------++import Foreign.C.Types+import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Marshal.Array+import Foreign.Storable++import Data.Number.Flint.Flint++#include <flint/flint.h>+#include <flint/mpfr_mat.h>++-- mpfr_mat_t ------------------------------------------------------------------++data MpfrMat = MpfrMat {-# UNPACK #-} !(ForeignPtr CMpfrMat)+data CMpfrMat = CMpfrMat (Ptr CMpfr) CLong CLong (Ptr (Ptr CMpfr))++instance Storable CMpfrMat where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size mpfr_mat_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment mpfr_mat_t}+ peek ptr = CMpfrMat+ <$> #{peek mpfr_mat_struct, entries} ptr+ <*> #{peek mpfr_mat_struct, r } ptr+ <*> #{peek mpfr_mat_struct, c } ptr+ <*> #{peek mpfr_mat_struct, rows } ptr+ poke = error "CMpfrMat.poke: Not defined."++newMpfrMat rows cols prec = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> mpfr_mat_init x rows cols prec+ addForeignPtrFinalizer p_mpfr_mat_clear x+ return $ MpfrMat x++{-# INLINE withMpfrMat #-}+withMpfrMat (MpfrMat x) f = do+ withForeignPtr x $ \px -> f px >>= return . (MpfrMat x,)++withNewMpfrMat rows cols prec f = do+ x <- newMpfrMat rows cols prec+ withMpfrMat x f+ +-- Memory management -----------------------------------------------------------++-- | /mpfr_mat_init/ /mat/ /rows/ /cols/ /prec/ +-- +-- Initialises a matrix with the given number of rows and columns and the+-- given precision for use. The precision is the exact precision of the+-- entries.+foreign import ccall "mpfr_mat.h mpfr_mat_init"+ mpfr_mat_init :: Ptr CMpfrMat -> CLong -> CLong -> CMpfrPrec -> IO ()++-- | /mpfr_mat_clear/ /mat/ +-- +-- Clears the given matrix.+foreign import ccall "mpfr_mat.h mpfr_mat_clear"+ mpfr_mat_clear :: Ptr CMpfrMat -> IO ()++foreign import ccall "mpfr_mat.h &mpfr_mat_clear"+ p_mpfr_mat_clear :: FunPtr (Ptr CMpfrMat -> IO ())++-- Basic manipulation ----------------------------------------------------------++mpfr_mat_entry mat i j = do+ CMpfrMat entries r c rows <- peek mat+ return $ entries `advancePtr` (fromIntegral (i*c + j))++-- | /mpfr_mat_swap/ /mat1/ /mat2/ +-- +-- Efficiently swap matrices @mat1@ and @mat2@.+foreign import ccall "mpfr_mat.h mpfr_mat_swap"+ mpfr_mat_swap :: Ptr CMpfrMat -> Ptr CMpfrMat -> IO ()++-- | /mpfr_mat_swap_entrywise/ /mat1/ /mat2/ +-- +-- Swaps two matrices by swapping the individual entries rather than+-- swapping the contents of the structs.+foreign import ccall "mpfr_mat.h mpfr_mat_swap_entrywise_"+ mpfr_mat_swap_entrywise :: Ptr CMpfrMat -> Ptr CMpfrMat -> IO ()++-- | /mpfr_mat_set/ /mat1/ /mat2/ +-- +-- Set @mat1@ to the value of @mat2@.+foreign import ccall "mpfr_mat.h mpfr_mat_set"+ mpfr_mat_set :: Ptr CMpfrMat -> Ptr CMpfrMat -> IO ()++-- | /mpfr_mat_zero/ /mat/ +-- +-- Set @mat@ to the zero matrix.+foreign import ccall "mpfr_mat.h mpfr_mat_zero"+ mpfr_mat_zero :: Ptr CMpfrMat -> IO ()++-- Comparison ------------------------------------------------------------------++-- | /mpfr_mat_equal/ /mat1/ /mat2/ +-- +-- Return \(1\) if the two given matrices are equal, otherwise return+-- \(0\).+foreign import ccall "mpfr_mat.h mpfr_mat_equal"+ mpfr_mat_equal :: Ptr CMpfrMat -> Ptr CMpfrMat -> IO CInt++-- Randomisation ---------------------------------------------------------------++-- | /mpfr_mat_randtest/ /mat/ /state/ +-- +-- Generate a random matrix with random number of rows and columns and+-- random entries for use in test code.+foreign import ccall "mpfr_mat.h mpfr_mat_randtest"+ mpfr_mat_randtest :: Ptr CMpfrMat -> Ptr CFRandState -> IO ()++-- Basic arithmetic ------------------------------------------------------------++-- | /mpfr_mat_mul_classical/ /C/ /A/ /B/ /rnd/ +-- +-- Set \(C\) to the product of \(A\) and \(B\) with the given rounding+-- mode, using the classical algorithm.+foreign import ccall "mpfr_mat.h mpfr_mat_mul_classical"+ mpfr_mat_mul_classical :: Ptr CMpfrMat -> Ptr CMpfrMat -> Ptr CMpfrMat -> CMpfrRnd -> IO ()+
+ src/Data/Number/Flint/Support/Mpfr/Vec.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Support.Mpfr.Vec (+ module Data.Number.Flint.Support.Mpfr.Vec.FFI+ ) where++import Data.Number.Flint.Support.Mpfr.Vec.FFI
+ src/Data/Number/Flint/Support/Mpfr/Vec/FFI.hsc view
@@ -0,0 +1,84 @@+{-|+module : Data.Number.Flint.Support.Mpfr.Vec.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Support.Mpfr.Vec.FFI (+ -- * Vectors of MPFR floating-point numbers+ -- * Memory management+ _mpfr_vec_init+ , _mpfr_vec_clear+ -- * Arithmetic+ , _mpfr_vec_zero+ , _mpfr_vec_set+ , _mpfr_vec_add+ , _mpfr_vec_scalar_mul_mpfr+ , _mpfr_vec_scalar_mul_2exp+ , _mpfr_vec_scalar_product+) where++-- Vectors of MPFR floating-point numbers --------------------------------------++import Data.Number.Flint.Flint++import Foreign.Ptr+import Foreign.C.Types++-- Memory management -----------------------------------------------------------++-- | /_mpfr_vec_init/ /len/ /prec/ +-- +-- Returns a vector of the given length of initialised @mpfr@\'s with the+-- given exact precision.+foreign import ccall "mpfr_vec.h _mpfr_vec_init"+ _mpfr_vec_init :: CLong -> CFBitCnt -> IO (Ptr CMpfr)++-- | /_mpfr_vec_clear/ /vec/ /len/ +-- +-- Clears the given vector.+foreign import ccall "mpfr_vec.h _mpfr_vec_clear"+ _mpfr_vec_clear :: Ptr CMpfr -> CLong -> IO ()++-- Arithmetic ------------------------------------------------------------------++-- | /_mpfr_vec_zero/ /vec/ /len/ +-- +-- Zeros the vector @(vec, len)@.+foreign import ccall "mpfr_vec.h _mpfr_vec_zero"+ _mpfr_vec_zero :: Ptr CMpfr -> CLong -> IO ()++-- | /_mpfr_vec_set/ /vec1/ /vec2/ /len/ +-- +-- Copies the vector @vec2@ of the given length into @vec1@. No check is+-- made to ensure @vec1@ and @vec2@ are different.+foreign import ccall "mpfr_vec.h _mpfr_vec_set"+ _mpfr_vec_set :: Ptr CMpfr -> Ptr CMpfr -> CLong -> IO ()++-- | /_mpfr_vec_add/ /res/ /vec1/ /vec2/ /len/ +-- +-- Adds the given vectors of the given length together and stores the+-- result in @res@.+foreign import ccall "mpfr_vec.h _mpfr_vec_add"+ _mpfr_vec_add :: Ptr CMpfr -> Ptr CMpfr -> Ptr CMpfr -> CLong -> IO ()++-- | /_mpfr_vec_scalar_mul_mpfr/ /res/ /vec/ /len/ /c/ +-- +-- Multiplies the vector with given length by the scalar \(c\) and sets+-- @res@ to the result.+foreign import ccall "mpfr_vec.h _mpfr_vec_scalar_mul_mpfr"+ _mpfr_vec_scalar_mul_mpfr :: Ptr CMpfr -> Ptr CMpfr -> CLong -> Ptr CMpfr -> IO ()++-- | /_mpfr_vec_scalar_mul_2exp/ /res/ /vec/ /len/ /exp/ +-- +-- Multiplies the given vector of the given length by @2^exp@.+foreign import ccall "mpfr_vec.h _mpfr_vec_scalar_mul_2exp"+ _mpfr_vec_scalar_mul_2exp :: Ptr CMpfr -> Ptr CMpfr -> CLong -> CFBitCnt -> IO ()++-- | /_mpfr_vec_scalar_product/ /res/ /vec1/ /vec2/ /len/ +-- +-- Sets @res@ to the scalar product of @(vec1, len)@ with @(vec2, len)@.+-- Assumes @len > 0@.+foreign import ccall "mpfr_vec.h _mpfr_vec_scalar_product"+ _mpfr_vec_scalar_product :: Ptr CMpfr -> Ptr CMpfr -> Ptr CMpfr -> CLong -> IO ()+
+ src/Data/Number/Flint/Support/ULong/Extras.hs view
@@ -0,0 +1,5 @@+module Data.Number.Flint.Support.ULong.Extras (+ module Data.Number.Flint.Support.ULong.Extras.FFI+ ) where++import Data.Number.Flint.Support.ULong.Extras.FFI
+ src/Data/Number/Flint/Support/ULong/Extras/FFI.hsc view
@@ -0,0 +1,1870 @@+{-|+module : Data.Number.Flint.Support.ULong.Extras.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.Support.ULong.Extras.FFI (+ -- * Arithmetic and number-theoretic functions for single-word integers+ NPrimes (..)+ , CNPrimes (..)+ , newNPrimes+ , withNPrimes+ , withNewNPrimes+ , NFactor (..)+ , CNFactor (..)+ , newNFactor+ , withNFactor+ -- * Random functions+ , n_randlimb+ , n_randbits+ , n_randtest_bits+ , n_randint+ , n_urandint+ , n_randtest+ , n_randtest_not_zero+ , n_randprime+ , n_randtest_prime+ -- * Basic arithmetic+ , n_pow+ , n_flog+ , n_clog+ , n_clog_2exp+ -- * Miscellaneous+ , n_revbin+ , n_sizeinbase+ -- * Basic arithmetic with precomputed inverses+ , n_preinvert_limb_prenorm+ , n_preinvert_limb+ , n_precompute_inverse+ , n_mod_precomp+ , n_mod2_precomp+ , n_divrem2_preinv+ , n_div2_preinv+ , n_mod2_preinv+ , n_divrem2_precomp+ , n_ll_mod_preinv+ , n_lll_mod_preinv+ , n_mulmod_precomp+ , n_mulmod2_preinv+ , n_mulmod2+ , n_mulmod_preinv+ -- * Greatest common divisor+ , n_gcd+ , n_gcdinv+ , n_xgcd+ -- * Jacobi and Kronecker symbols+ , n_jacobi+ , n_jacobi_unsigned+ -- * Modular Arithmetic+ , n_addmod+ , n_submod+ , n_invmod+ , n_powmod_precomp+ , n_powmod_ui_precomp+ , n_powmod+ , n_powmod2_preinv+ , n_powmod2+ , n_powmod2_ui_preinv+ , n_powmod2_fmpz_preinv+ , n_sqrtmod+ , n_sqrtmod_2pow+ , n_sqrtmod_primepow+ , n_sqrtmodn+ , n_mulmod_shoup+ , n_mulmod_precomp_shoup+ -- * Divisibility testing+ , n_divides+ -- * Prime number generation and counting+ , n_primes_init+ , n_primes_clear+ , n_primes_next+ , n_primes_jump_after+ , n_primes_extend_small+ , n_primes_sieve_range+ , n_compute_primes+ , n_primes_arr_readonly+ , n_prime_inverses_arr_readonly+ , n_cleanup_primes+ , n_nextprime+ , n_prime_pi+ , n_prime_pi_bounds+ , n_nth_prime+ , n_nth_prime_bounds+ -- * Primality testing+ , n_is_oddprime_small+ , n_is_oddprime_binary+ , n_is_prime_pocklington+ , n_is_prime_pseudosquare+ , n_is_prime+ , n_is_strong_probabprime_precomp+ , n_is_strong_probabprime2_preinv+ , n_is_probabprime_fermat+ , n_is_probabprime_fibonacci+ , n_is_probabprime_BPSW+ , n_is_probabprime_lucas+ , n_is_probabprime+ -- * Chinese remaindering+ , n_CRT+ -- * Square root and perfect power testing+ , n_sqrt+ , n_sqrtrem+ , n_is_square+ , n_is_perfect_power235+ , n_is_perfect_power+ , n_rootrem+ , n_cbrt+ , n_cbrt_newton_iteration+ , n_cbrt_binary_search+ , n_cbrt_chebyshev_approx+ , n_cbrtrem+ -- * Factorisation+ , n_remove+ , n_remove2_precomp+ , n_factor_insert+ , n_factor_trial_range+ , n_factor_trial+ , n_factor_power235+ , n_factor_one_line+ , n_factor_lehman+ , n_factor_SQUFOF+ , n_factor+ , n_factor_trial_partial+ , n_factor_partial+ , n_factor_pp1+ , n_factor_pp1_wrapper+ , n_factor_pollard_brent_single+ , n_factor_pollard_brent+ -- * Arithmetic functions+ , n_moebius_mu+ , n_moebius_mu_vec+ , n_is_squarefree+ , n_euler_phi+ -- * Factorials+ , n_factorial_fast_mod2_preinv+ , n_factorial_mod2_preinv+ -- * Primitive Roots and Discrete Logarithms+ , n_primitive_root_prime_prefactor+ , n_primitive_root_prime+ , n_discrete_log_bsgs+ -- * Elliptic curve method for factorization of @mp_limb_t@+ , n_factor_ecm_double+ , n_factor_ecm_add+ , n_factor_ecm_mul_montgomery_ladder+ , n_factor_ecm_select_curve+ , n_factor_ecm_stage_I+ , n_factor_ecm_stage_II+ , n_factor_ecm+) where ++-- Arithmetic and number-theoretic functions for single-word integers ----------++import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.Types+import Foreign.Storable++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz++#define ULONG_EXTRAS_INLINES_C+#include <flint/ulong_extras.h>++-- n_factor_t ------------------------------------------------------------------++data NFactor = NFactor {-# UNPACK #-} !(ForeignPtr CNFactor)+data CNFactor = CNFactor CInt (Ptr CInt) (Ptr CULong)++instance Storable CNFactor where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size n_factor_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment n_factor_t}+ peek ptr = do+ num <- #{peek n_factor_t, num} ptr+ exp <- return $ castPtr $ ptr `plusPtr` (sizeOf (undefined :: CInt))+ p <- return $ castPtr $ ptr `plusPtr` (sizeOf (undefined :: CInt) * (1 + #const FLINT_MAX_FACTORS_IN_LIMB))+ return $ CNFactor num exp p+ poke = undefined++newNFactor = do+ x <- mallocForeignPtr+ withForeignPtr x n_factor_init+ -- addForeignPtrFinalizer p_n_factor_clear x+ return $ NFactor x++{-# INLINE withNFactor #-}+withNFactor (NFactor x) f = do+ withForeignPtr x $ \px -> f px >>= return . (NFactor x,)++-- n_primes_t ------------------------------------------------------------------++data NPrimes = NPrimes {-# UNPACK #-} !(ForeignPtr CNPrimes)+type CNPrimes = CFlint NPrimes++instance Storable CNPrimes where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size n_primes_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment n_primes_t}+ peek = undefined+ poke = undefined++newNPrimes = do+ x <- mallocForeignPtr+ withForeignPtr x n_primes_init+ addForeignPtrFinalizer p_n_primes_clear x+ return $ NPrimes x++{-# INLINE withNPrimes #-}+withNPrimes (NPrimes x) f = do+ withForeignPtr x $ \px -> f px >>= return . (NPrimes x,)++withNewNPrimes f = do+ x <- newNPrimes+ withNPrimes x f+ +-- n_ecm_t ---------------------------------------------------------------------++data NEcm = NEcm {-# UNPACK #-} !(ForeignPtr CNEcm)+type CNEcm = CFlint NEcm++instance Storable CNEcm where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size n_ecm_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment n_ecm_t}+ peek = undefined+ poke = undefined++newNEcm = do+ x <- mallocForeignPtr+ return $ NEcm x++{-# INLINE withNEcm #-}+withNEcm (NEcm x) f = do+ withForeignPtr x $ \px -> f px >>= return . (NEcm x,)++-- Random functions ------------------------------------------------------------++-- | /n_randlimb/ /state/ +--+-- Returns a uniformly pseudo random limb.+-- +-- The algorithm generates two random half limbs \(s_j\), \(j = 0, 1\), by+-- iterating respectively \(v_{i+1} = (v_i a + b) \bmod{p_j}\) for some+-- initial seed \(v_0\), randomly chosen values \(a\) and \(b\) and+-- @p_0 = 4294967311 = nextprime(2^32)@ on a 64-bit machine and+-- @p_0 = nextprime(2^16)@ on a 32-bit machine and @p_1 = nextprime(p_0)@.+foreign import ccall "ulong_extras.h n_randlimb"+ n_randlimb :: Ptr CFRandState -> IO CULong++-- | /n_randbits/ /state/ /bits/ +--+-- Returns a uniformly pseudo random number with the given number of bits.+-- The most significant bit is always set, unless zero is passed, in which+-- case zero is returned.+foreign import ccall "ulong_extras.h n_randbits"+ n_randbits :: Ptr CFRandState -> CUInt -> IO CULong++-- | /n_randtest_bits/ /state/ /bits/ +--+-- Returns a uniformly pseudo random number with the given number of bits.+-- The most significant bit is always set, unless zero is passed, in which+-- case zero is returned. The probability of a value with a sparse binary+-- representation being returned is increased. This function is intended+-- for use in test code.+foreign import ccall "ulong_extras.h n_randtest_bits"+ n_randtest_bits :: Ptr CFRandState -> CInt -> IO CULong++-- | /n_randint/ /state/ /limit/ +--+-- Returns a uniformly pseudo random number up to but not including the+-- given limit. If zero is passed as a parameter, an entire random limb is+-- returned.+foreign import ccall "ulong_extras.h n_randint"+ n_randint :: Ptr CFRandState -> CULong -> IO CULong++-- | /n_urandint/ /state/ /limit/ +--+-- Returns a uniformly pseudo random number up to but not including the+-- given limit. If zero is passed as a parameter, an entire random limb is+-- returned. This function provides somewhat better randomness as compared+-- to @n_randint@, especially for larger values of limit.+foreign import ccall "ulong_extras.h n_urandint"+ n_urandint :: Ptr CFRandState -> CULong -> IO CULong++-- | /n_randtest/ /state/ +--+-- Returns a pseudo random number with a random number of bits, from \(0\)+-- to @FLINT_BITS@. The probability of the special values \(0\), \(1\),+-- @COEFF_MAX@ and @WORD_MAX@ is increased as is the probability of a value+-- with sparse binary representation. This random function is mainly used+-- for testing purposes. This function is intended for use in test code.+foreign import ccall "ulong_extras.h n_randtest"+ n_randtest :: Ptr CFRandState -> IO CULong++-- | /n_randtest_not_zero/ /state/ +--+-- As for @n_randtest@, but does not return \(0\). This function is+-- intended for use in test code.+foreign import ccall "ulong_extras.h n_randtest_not_zero"+ n_randtest_not_zero :: Ptr CFRandState -> IO CULong++-- | /n_randprime/ /state/ /bits/ /proved/ +--+-- Returns a random prime number @(proved = 1)@ or probable prime+-- @(proved = 0)@ with @bits@ bits, where @bits@ must be at least 2 and at+-- most @FLINT_BITS@.+foreign import ccall "ulong_extras.h n_randprime"+ n_randprime :: Ptr CFRandState -> CULong -> CInt -> IO CULong++-- | /n_randtest_prime/ /state/ /proved/ +--+-- Returns a random prime number @(proved = 1)@ or probable prime+-- @(proved = 0)@ with size randomly chosen between 2 and @FLINT_BITS@+-- bits. This function is intended for use in test code.+foreign import ccall "ulong_extras.h n_randtest_prime"+ n_randtest_prime :: Ptr CFRandState -> CInt -> IO CULong++-- Basic arithmetic ------------------------------------------------------------++-- | /n_pow/ /n/ /exp/ +--+-- Returns @n^exp@. No checking is done for overflow. The exponent may be+-- zero. We define \(0^0 = 1\).+-- +-- The algorithm simply uses a for loop. Repeated squaring is unlikely to+-- speed up this algorithm.+foreign import ccall "ulong_extras.h n_pow"+ n_pow :: CULong -> CULong -> IO CULong++-- | /n_flog/ /n/ /b/ +--+-- Returns \(\lfloor\log_b n\rfloor\).+-- +-- Assumes that \(n \geq 1\) and \(b \geq 2\).+foreign import ccall "ulong_extras.h n_flog"+ n_flog :: CULong -> CULong -> IO CULong++-- | /n_clog/ /n/ /b/ +--+-- Returns \(\lceil\log_b n\rceil\).+-- +-- Assumes that \(n \geq 1\) and \(b \geq 2\).+foreign import ccall "ulong_extras.h n_clog"+ n_clog :: CULong -> CULong -> IO CULong++-- | /n_clog_2exp/ /n/ /b/ +--+-- Returns \(\lceil\log_b 2^n\rceil\).+-- +-- Assumes that \(b \geq 2\).+foreign import ccall "ulong_extras.h n_clog_2exp"+ n_clog_2exp :: CULong -> CULong -> IO CULong++-- Miscellaneous ---------------------------------------------------------------++-- | /n_revbin/ /n/ /b/ +--+-- Returns the binary reverse of \(n\), assuming it is \(b\) bits in+-- length, e.g. @n_revbin(10110, 6)@ will return @110100@.+foreign import ccall "ulong_extras.h n_revbin"+ n_revbin :: CULong -> CULong -> IO CULong++-- | /n_sizeinbase/ /n/ /base/ +--+-- Returns the exact number of digits needed to represent \(n\) as a string+-- in base @base@ assumed to be between 2 and 36. Returns 1 when \(n = 0\).+foreign import ccall "ulong_extras.h n_sizeinbase"+ n_sizeinbase :: CULong -> CInt -> IO CInt++-- Basic arithmetic with precomputed inverses ----------------------------------++-- | /n_preinvert_limb_prenorm/ /n/ +--+-- Computes an approximate inverse @invxl@ of the limb @xl@, with an+-- implicit leading~\`1\`. More formally it computes:+-- +-- > invxl = (B^2 - B*x - 1)/x = (B^2 - 1)/x - B+-- +-- Note that \(x\) must be normalised, i.e. with msb set. This inverse+-- makes use of the following theorem of Torbjorn Granlund and Peter+-- Montgomery~[Lemma~8.1]< [GraMon1994]>:+-- +-- Let \(d\) be normalised, \(d < B\), i.e. it fits in a word, and suppose+-- that \(m d < B^2 \leq (m+1) d\). Let \(0 \leq n \leq B d - 1\). Write+-- \(n = n_2 B + n_1 B/2 + n_0\) with \(n_1 = 0\) or \(1\) and+-- \(n_0 < B/2\). Suppose+-- \(q_1 B + q_0 = n_2 B + (n_2 + n_1) (m - B) + n_1 (d-B/2) + n_0\) and+-- \(0 \leq q_0 < B\). Then \(0 \leq q_1 < B\) and+-- \(0 \leq n - q_1 d < 2 d\).+-- +-- In the theorem, \(m\) is the inverse of \(d\). If we let @m = invxl + B@+-- and \(d = x\) we have \(m d = B^2 - 1 < B^2\) and+-- \((m+1) x = B^2 + d - 1 \geq B^2\).+-- +-- The theorem is often applied as follows: note that \(n_0\) and+-- \(n_1 (d-B/2)\) are both less than \(B/2\). Also note that+-- \(n_1 (m-B) < B\). Thus the sum of all these terms contributes at most+-- \(1\) to \(q_1\). We are left with \(n_2 B + n_2 (m-B)\). But note that+-- \((m-B)\) is precisely our precomputed inverse @invxl@. If we write+-- \(q_1 B + q_0 = n_2 B + n_2 (m-B)\), then from the theorem, we have+-- \(0 \leq n - q_1 d < 3 d\), i.e. the quotient is out by at most \(2\)+-- and is always either correct or too small.+foreign import ccall "ulong_extras.h n_preinvert_limb_prenorm"+ n_preinvert_limb_prenorm :: CULong -> IO CULong++-- | /n_preinvert_limb/ /n/ +--+-- Returns a precomputed inverse of \(n\), as defined in < [GraMol2010]>.+-- This precomputed inverse can be used with all of the functions that take+-- a precomputed inverse whose names are suffixed by @_preinv@.+-- +-- We require \(n > 0\).+foreign import ccall "ulong_extras.h n_preinvert_limb"+ n_preinvert_limb :: CULong -> IO CULong++-- | /n_precompute_inverse/ /n/ +--+-- Returns a precomputed inverse of \(n\) with double precision value+-- \(1/n\). This precomputed inverse can be used with all of the functions+-- that take a precomputed inverse whose names are suffixed by @_precomp@.+-- +-- We require \(n > 0\).+foreign import ccall "ulong_extras.h n_precompute_inverse"+ n_precompute_inverse :: CULong -> IO CDouble++-- | /n_mod_precomp/ /a/ /n/ /ninv/ +--+-- Returns \(a \bmod{n}\) given a precomputed inverse of \(n\) computed by+-- @n_precompute_inverse@. We require @n \< 2^FLINT_D_BITS@ and+-- @a \< 2^(FLINT_BITS-1)@ and \(0 \leq a < n^2\).+-- +-- We assume the processor is in the standard round to nearest mode. Thus+-- @ninv@ is correct to \(53\) binary bits, the least significant bit of+-- which we shall call a place, and can be at most half a place out. When+-- \(a\) is multiplied by \(ninv\), the binary representation of \(a\) is+-- exact and the mantissa is less than \(2\), thus we see that @a * ninv@+-- can be at most one out in the mantissa. We now truncate @a * ninv@ to+-- the nearest integer, which is always a round down. Either we already+-- have an integer, or we need to make a change down of at least \(1\) in+-- the last place. In the latter case we either get precisely the exact+-- quotient or below it as when we rounded the product to the nearest place+-- we changed by at most half a place. In the case that truncating to an+-- integer takes us below the exact quotient, we have rounded down by less+-- than \(1\) plus half a place. But as the product is less than \(n\) and+-- \(n\) is less than \(2^{53}\), half a place is less than \(1\), thus we+-- are out by less than \(2\) from the exact quotient, i.e. the quotient we+-- have computed is the quotient we are after or one too small. That leaves+-- only the case where we had to round up to the nearest place which+-- happened to be an integer, so that truncating to an integer didn\'t+-- change anything. But this implies that the exact quotient \(a/n\) is+-- less than \(2^{-54}\) from an integer. We deal with this rare case by+-- subtracting 1 from the quotient. Then the quotient we have computed is+-- either exactly what we are after, or one too small.+foreign import ccall "ulong_extras.h n_mod_precomp"+ n_mod_precomp :: CULong -> CULong -> CDouble -> IO CULong++-- | /n_mod2_precomp/ /a/ /n/ /ninv/ +--+-- Returns \(a \bmod{n}\) given a precomputed inverse of \(n\) computed by+-- @n_precompute_inverse@. There are no restrictions on \(a\) or on \(n\).+-- +-- As for @n_mod_precomp@ for \(n < 2^{53}\) and \(a < n^2\) the computed+-- quotient is either what we are after or one too large or small. We deal+-- with these cases. Otherwise we can be sure that the top \(52\) bits of+-- the quotient are computed correctly. We take the remainder and adjust+-- the quotient by multiplying the remainder by @ninv@ to compute another+-- approximate quotient as per @mod_precomp@. Now the remainder may be+-- either negative or positive, so the quotient we compute may be one out+-- in either direction.+foreign import ccall "ulong_extras.h n_mod2_precomp"+ n_mod2_precomp :: CULong -> CULong -> CDouble -> IO CULong++-- | /n_divrem2_preinv/ /q/ /a/ /n/ /ninv/ +--+-- Returns \(a \bmod{n}\) and sets \(q\) to the quotient of \(a\) by \(n\),+-- given a precomputed inverse of \(n\) computed by @n_preinvert_limb()@.+-- There are no restrictions on \(a\) and the only restriction on \(n\) is+-- that it be nonzero.+-- +-- This uses the algorithm of Granlund and Möller < [GraMol2010]>. First+-- \(n\) is normalised and \(a\) is shifted into two limbs to compensate.+-- Then their algorithm is applied verbatim and the remainder shifted back.+foreign import ccall "ulong_extras.h n_divrem2_preinv"+ n_divrem2_preinv :: Ptr CULong -> CULong -> CULong -> CULong -> IO CULong++-- | /n_div2_preinv/ /a/ /n/ /ninv/ +--+-- Returns the Euclidean quotient of \(a\) by \(n\) given a precomputed+-- inverse of \(n\) computed by @n_preinvert_limb@. There are no+-- restrictions on \(a\) and the only restriction on \(n\) is that it be+-- nonzero.+-- +-- This uses the algorithm of Granlund and Möller < [GraMol2010]>. First+-- \(n\) is normalised and \(a\) is shifted into two limbs to compensate.+-- Then their algorithm is applied verbatim.+foreign import ccall "ulong_extras.h n_div2_preinv"+ n_div2_preinv :: CULong -> CULong -> CULong -> IO CULong++-- | /n_mod2_preinv/ /a/ /n/ /ninv/ +--+-- Returns \(a \bmod{n}\) given a precomputed inverse of \(n\) computed by+-- @n_preinvert_limb()@. There are no restrictions on \(a\) and the only+-- restriction on \(n\) is that it be nonzero.+-- +-- This uses the algorithm of Granlund and Möller < [GraMol2010]>. First+-- \(n\) is normalised and \(a\) is shifted into two limbs to compensate.+-- Then their algorithm is applied verbatim and the result shifted back.+foreign import ccall "ulong_extras.h n_mod2_preinv"+ n_mod2_preinv :: CULong -> CULong -> CULong -> IO CULong++-- | /n_divrem2_precomp/ /q/ /a/ /n/ /npre/ +--+-- Returns \(a \bmod{n}\) given a precomputed inverse of \(n\) computed by+-- @n_precompute_inverse@ and sets \(q\) to the quotient. There are no+-- restrictions on \(a\) or on \(n\).+-- +-- This is as for @n_mod2_precomp@ with some additional care taken to+-- retain the quotient information. There are also special cases to deal+-- with the case where \(a\) is already reduced modulo \(n\) and where+-- \(n\) is \(64\) bits and \(a\) is not reduced modulo \(n\).+foreign import ccall "ulong_extras.h n_divrem2_precomp"+ n_divrem2_precomp :: Ptr CULong -> CULong -> CULong -> CDouble -> IO CULong++-- | /n_ll_mod_preinv/ /a_hi/ /a_lo/ /n/ /ninv/ +--+-- Returns \(a \bmod{n}\) given a precomputed inverse of \(n\) computed by+-- @n_preinvert_limb@. There are no restrictions on \(a\), which will be+-- two limbs @(a_hi, a_lo)@, or on \(n\).+-- +-- The old version of this function merely reduced the top limb @a_hi@+-- modulo \(n\) so that @udiv_qrnnd_preinv()@ could be used.+-- +-- The new version reduces the top limb modulo \(n\) as per @n_mod2_preinv@+-- and then the algorithm of Granlund and Möller < [GraMol2010]> is used+-- again to reduce modulo \(n\).+foreign import ccall "ulong_extras.h n_ll_mod_preinv"+ n_ll_mod_preinv :: CULong -> CULong -> CULong -> CULong -> IO CULong++-- | /n_lll_mod_preinv/ /a_hi/ /a_mi/ /a_lo/ /n/ /ninv/ +--+-- Returns \(a \bmod{n}\), where \(a\) has three limbs+-- @(a_hi, a_mi, a_lo)@, given a precomputed inverse of \(n\) computed by+-- @n_preinvert_limb@. It is assumed that @a_hi@ is reduced modulo \(n\).+-- There are no restrictions on \(n\).+-- +-- This function uses the algorithm of Granlund and Möller < [GraMol2010]>+-- to first reduce the top two limbs modulo \(n\), then does the same on+-- the bottom two limbs.+foreign import ccall "ulong_extras.h n_lll_mod_preinv"+ n_lll_mod_preinv :: CULong -> CULong -> CULong -> CULong -> CULong -> IO CULong++-- | /n_mulmod_precomp/ /a/ /b/ /n/ /ninv/ +--+-- Returns \(a b \bmod{n}\) given a precomputed inverse of \(n\) computed+-- by @n_precompute_inverse@. We require @n \< 2^FLINT_D_BITS@ and+-- \(0 \leq a, b < n\).+-- +-- We assume the processor is in the standard round to nearest mode. Thus+-- @ninv@ is correct to \(53\) binary bits, the least significant bit of+-- which we shall call a place, and can be at most half a place out. The+-- product of \(a\) and \(b\) is computed with error at most half a place.+-- When @a * b@ is multiplied by \(ninv\) we find that the exact quotient+-- and computed quotient differ by less than two places. As the quotient is+-- less than \(n\) this means that the exact quotient is at most \(1\) away+-- from the computed quotient. We truncate this quotient to an integer+-- which reduces the value by less than \(1\). We end up with a value which+-- can be no more than two above the quotient we are after and no less than+-- two below. However an argument similar to that for @n_mod_precomp@ shows+-- that the truncated computed quotient cannot be two smaller than the+-- truncated exact quotient. In other words the computed integer quotient+-- is at most two above and one below the quotient we are after.+foreign import ccall "ulong_extras.h n_mulmod_precomp"+ n_mulmod_precomp :: CULong -> CULong -> CULong -> CDouble -> IO CULong++-- | /n_mulmod2_preinv/ /a/ /b/ /n/ /ninv/ +--+-- Returns \(a b \bmod{n}\) given a precomputed inverse of \(n\) computed+-- by @n_preinvert_limb@. There are no restrictions on \(a\), \(b\) or on+-- \(n\). This is implemented by multiplying using @umul_ppmm@ and then+-- reducing using @n_ll_mod_preinv@.+foreign import ccall "ulong_extras.h n_mulmod2_preinv"+ n_mulmod2_preinv :: CULong -> CULong -> CULong -> CULong -> IO CULong++-- | /n_mulmod2/ /a/ /b/ /n/ +--+-- Returns \(a b \bmod{n}\). There are no restrictions on \(a\), \(b\) or+-- on \(n\). This is implemented by multiplying using @umul_ppmm@ and then+-- reducing using @n_ll_mod_preinv@ after computing a precomputed inverse.+foreign import ccall "ulong_extras.h n_mulmod2"+ n_mulmod2 :: CULong -> CULong -> CULong -> IO CULong++-- | /n_mulmod_preinv/ /a/ /b/ /n/ /ninv/ /norm/ +--+-- Returns \(a b \pmod{n}\) given a precomputed inverse of \(n\) computed+-- by @n_preinvert_limb@, assuming \(a\) and \(b\) are reduced modulo \(n\)+-- and \(n\) is normalised, i.e. with most significant bit set. There are+-- no other restrictions on \(a\), \(b\) or \(n\).+-- +-- The value @norm@ is provided for convenience. As \(n\) is required to be+-- normalised, it may be that \(a\) and \(b\) have been shifted to the left+-- by @norm@ bits before calling the function. Their product then has an+-- extra factor of \(2^\text{norm}\). Specifying a nonzero @norm@ will+-- shift the product right by this many bits before reducing it.+-- +-- The algorithm used is that of Granlund and Möller < [GraMol2010]>.+foreign import ccall "ulong_extras.h n_mulmod_preinv"+ n_mulmod_preinv :: CULong -> CULong -> CULong -> CULong -> CULong -> IO CULong++-- Greatest common divisor -----------------------------------------------------++-- | /n_gcd/ /x/ /y/ +--+-- Returns the greatest common divisor \(g\) of \(x\) and \(y\). No+-- assumptions are made about the values \(x\) and \(y\).+-- +-- This function wraps GMP\'s @mpn_gcd_1@.+foreign import ccall "ulong_extras.h n_gcd"+ n_gcd :: CULong -> CULong -> IO CULong++-- | /n_gcdinv/ /a/ /x/ /y/ +--+-- Returns the greatest common divisor \(g\) of \(x\) and \(y\) and+-- computes \(a\) such that \(0 \leq a < y\) and+-- \(a x = \gcd(x, y) \bmod{y}\), when this is defined. We require+-- \(x < y\).+-- +-- When \(y = 1\) the greatest common divisor is set to \(1\) and \(a\) is+-- set to \(0\).+-- +-- This is merely an adaption of the extended Euclidean algorithm computing+-- just one cofactor and reducing it modulo \(y\).+foreign import ccall "ulong_extras.h n_gcdinv"+ n_gcdinv :: Ptr CULong -> CULong -> CULong -> IO CULong++-- | /n_xgcd/ /a/ /b/ /x/ /y/ +--+-- Returns the greatest common divisor \(g\) of \(x\) and \(y\) and+-- unsigned values \(a\) and \(b\) such that \(a x - b y = g\). We require+-- \(x \geq y\).+-- +-- We claim that computing the extended greatest common divisor via the+-- Euclidean algorithm always results in cofactor+-- \(\lvert a \rvert < x/2\), \(\lvert b\rvert < x/2\), with perhaps some+-- small degenerate exceptions.+-- +-- We proceed by induction.+-- +-- Suppose we are at some step of the algorithm, with \(x_n = q y_n + r\)+-- with \(r \geq 1\), and suppose \(1 = s y_n - t r\) with \(s < y_n / 2\),+-- \(t < y_n / 2\) by hypothesis.+-- +-- Write \(1 = s y_n - t (x_n - q y_n) = (s + t q) y_n - t x_n\).+-- +-- It suffices to show that \((s + t q) < x_n / 2\) as+-- \(t < y_n / 2 < x_n / 2\), which will complete the induction step.+-- +-- But at the previous step in the backsubstitution we would have had+-- \(1 = s r - c d\) with \(s < r/2\) and \(c < r/2\).+-- +-- Then \(s + t q < r/2 + y_n / 2 q = (r + q y_n)/2 = x_n / 2\).+-- +-- See the documentation of @n_gcd@ for a description of the branching in+-- the algorithm, which is faster than using division.+foreign import ccall "ulong_extras.h n_xgcd"+ n_xgcd :: Ptr CULong -> Ptr CULong -> CULong -> CULong -> IO CULong++-- Jacobi and Kronecker symbols ------------------------------------------------++-- | /n_jacobi/ /x/ /y/ +--+-- Computes the Jacobi symbol \(\left(\frac{x}{y}\right)\) for any \(x\)+-- and odd \(y\).+foreign import ccall "ulong_extras.h n_jacobi"+ n_jacobi :: CLong -> CULong -> IO CInt++-- | /n_jacobi_unsigned/ /x/ /y/ +--+-- Computes the Jacobi symbol, allowing \(x\) to go up to a full limb.+foreign import ccall "ulong_extras.h n_jacobi_unsigned"+ n_jacobi_unsigned :: CULong -> CULong -> IO CInt++-- Modular Arithmetic ----------------------------------------------------------++-- | /n_addmod/ /a/ /b/ /n/ +--+-- Returns \((a + b) \bmod{n}\).+foreign import ccall "ulong_extras.h n_addmod"+ n_addmod :: CULong -> CULong -> CULong -> IO CULong++-- | /n_submod/ /a/ /b/ /n/ +--+-- Returns \((a - b) \bmod{n}\).+foreign import ccall "ulong_extras.h n_submod"+ n_submod :: CULong -> CULong -> CULong -> IO CULong++-- | /n_invmod/ /x/ /y/ +--+-- Returns the inverse of \(x\) modulo \(y\), if it exists. Otherwise an+-- exception is thrown.+-- +-- This is merely an adaption of the extended Euclidean algorithm with+-- appropriate normalisation.+foreign import ccall "ulong_extras.h n_invmod"+ n_invmod :: CULong -> CULong -> IO CULong++-- | /n_powmod_precomp/ /a/ /exp/ /n/ /npre/ +--+-- Returns @a^exp@ modulo \(n\) given a precomputed inverse of \(n\)+-- computed by @n_precompute_inverse@. We require \(n < 2^{53}\) and+-- \(0 \leq a < n\). There are no restrictions on @exp@, i.e. it can be+-- negative.+-- +-- This is implemented as a standard binary powering algorithm using+-- repeated squaring and reducing modulo \(n\) at each step.+foreign import ccall "ulong_extras.h n_powmod_precomp"+ n_powmod_precomp :: CULong -> CLong -> CULong -> CDouble -> IO CULong++-- | /n_powmod_ui_precomp/ /a/ /exp/ /n/ /npre/ +--+-- Returns @a^exp@ modulo \(n\) given a precomputed inverse of \(n\)+-- computed by @n_precompute_inverse@. We require \(n < 2^{53}\) and+-- \(0 \leq a < n\). The exponent @exp@ is unsigned and so can be larger+-- than allowed by @n_powmod_precomp@.+-- +-- This is implemented as a standard binary powering algorithm using+-- repeated squaring and reducing modulo \(n\) at each step.+foreign import ccall "ulong_extras.h n_powmod_ui_precomp"+ n_powmod_ui_precomp :: CULong -> CULong -> CULong -> CDouble -> IO CULong++-- | /n_powmod/ /a/ /exp/ /n/ +--+-- Returns @a^exp@ modulo \(n\). We require @n \< 2^FLINT_D_BITS@ and+-- \(0 \leq a < n\). There are no restrictions on @exp@, i.e. it can be+-- negative.+-- +-- This is implemented by precomputing an inverse and calling the @precomp@+-- version of this function.+foreign import ccall "ulong_extras.h n_powmod"+ n_powmod :: CULong -> CLong -> CULong -> IO CULong++-- | /n_powmod2_preinv/ /a/ /exp/ /n/ /ninv/ +--+-- Returns @(a^exp) % n@ given a precomputed inverse of \(n\) computed by+-- @n_preinvert_limb@. We require \(0 \leq a < n\), but there are no+-- restrictions on \(n\) or on @exp@, i.e. it can be negative.+-- +-- This is implemented as a standard binary powering algorithm using+-- repeated squaring and reducing modulo \(n\) at each step.+-- +-- If @exp@ is negative but \(a\) is not invertible modulo \(n\), an+-- exception is raised.+foreign import ccall "ulong_extras.h n_powmod2_preinv"+ n_powmod2_preinv :: CULong -> CLong -> CULong -> CULong -> IO CULong++-- | /n_powmod2/ /a/ /exp/ /n/ +--+-- Returns @(a^exp) % n@. We require \(0 \leq a < n\), but there are no+-- restrictions on \(n\) or on @exp@, i.e. it can be negative.+-- +-- This is implemented by precomputing an inverse limb and calling the+-- @preinv@ version of this function.+-- +-- If @exp@ is negative but \(a\) is not invertible modulo \(n\), an+-- exception is raised.+foreign import ccall "ulong_extras.h n_powmod2"+ n_powmod2 :: CULong -> CLong -> CULong -> IO CULong++-- | /n_powmod2_ui_preinv/ /a/ /exp/ /n/ /ninv/ +--+-- Returns @(a^exp) % n@ given a precomputed inverse of \(n\) computed by+-- @n_preinvert_limb@. We require \(0 \leq a < n\), but there are no+-- restrictions on \(n\). The exponent @exp@ is unsigned and so can be+-- larger than allowed by @n_powmod2_preinv@.+-- +-- This is implemented as a standard binary powering algorithm using+-- repeated squaring and reducing modulo \(n\) at each step.+foreign import ccall "ulong_extras.h n_powmod2_ui_preinv"+ n_powmod2_ui_preinv :: CULong -> CULong -> CULong -> CULong -> IO CULong++-- | /n_powmod2_fmpz_preinv/ /a/ /exp/ /n/ /ninv/ +--+-- Returns @(a^exp) % n@ given a precomputed inverse of \(n\) computed by+-- @n_preinvert_limb@. We require \(0 \leq a < n\), but there are no+-- restrictions on \(n\). The exponent @exp@ must not be negative.+-- +-- This is implemented as a standard binary powering algorithm using+-- repeated squaring and reducing modulo \(n\) at each step.+foreign import ccall "ulong_extras.h n_powmod2_fmpz_preinv"+ n_powmod2_fmpz_preinv :: CULong -> Ptr CFmpz -> CULong -> CULong -> IO CULong++-- | /n_sqrtmod/ /a/ /p/ +--+-- If \(p\) is prime, compute a square root of \(a\) modulo \(p\) if \(a\)+-- is a quadratic residue modulo \(p\), otherwise return \(0\).+-- +-- If \(p\) is not prime the result is with high probability \(0\),+-- indicating that \(p\) is not prime, or \(a\) is not a square modulo+-- \(p\). Otherwise the result is meaningless.+-- +-- Assumes that \(a\) is reduced modulo \(p\).+foreign import ccall "ulong_extras.h n_sqrtmod"+ n_sqrtmod :: CULong -> CULong -> IO CULong++-- | /n_sqrtmod_2pow/ /sqrt/ /a/ /exp/ +--+-- Computes all the square roots of @a@ modulo @2^exp@. The roots are+-- stored in an array which is created and whose address is stored in the+-- location pointed to by @sqrt@. The array of roots is allocated by the+-- function but must be cleaned up by the user by calling @flint_free@. The+-- number of roots is returned by the function. If @a@ is not a quadratic+-- residue modulo @2^exp@ then 0 is returned by the function and the+-- location @sqrt@ points to is set to NULL.+foreign import ccall "ulong_extras.h n_sqrtmod_2pow"+ n_sqrtmod_2pow :: Ptr (Ptr CULong) -> CULong -> CLong -> IO CLong++-- | /n_sqrtmod_primepow/ /sqrt/ /a/ /p/ /exp/ +--+-- Computes all the square roots of @a@ modulo @p^exp@. The roots are+-- stored in an array which is created and whose address is stored in the+-- location pointed to by @sqrt@. The array of roots is allocated by the+-- function but must be cleaned up by the user by calling @flint_free@. The+-- number of roots is returned by the function. If @a@ is not a quadratic+-- residue modulo @p^exp@ then 0 is returned by the function and the+-- location @sqrt@ points to is set to NULL.+foreign import ccall "ulong_extras.h n_sqrtmod_primepow"+ n_sqrtmod_primepow :: Ptr (Ptr CULong) -> CULong -> CULong -> CLong -> IO CLong++-- | /n_sqrtmodn/ /sqrt/ /a/ /fac/ +--+-- Computes all the square roots of @a@ modulo @m@ given the factorisation+-- of @m@ in @fac@. The roots are stored in an array which is created and+-- whose address is stored in the location pointed to by @sqrt@. The array+-- of roots is allocated by the function but must be cleaned up by the user+-- by calling @flint_free@. The number of roots is returned by the+-- function. If @a@ is not a quadratic residue modulo @m@ then 0 is+-- returned by the function and the location @sqrt@ points to is set to+-- NULL.+foreign import ccall "ulong_extras.h n_sqrtmodn"+ n_sqrtmodn :: Ptr (Ptr CULong) -> CULong -> Ptr (Ptr CNFactor) -> IO CLong++-- | /n_mulmod_shoup/ /w/ /t/ /w_precomp/ /p/ +--+-- Returns \(w t \bmod{p}\) given a precomputed scaled approximation of+-- \(w / p\) computed by @n_mulmod_precomp_shoup@. The value of \(p\)+-- should be less than \(2^{\mathtt{FLINT\_BITS} - 1}\). \(w\) and \(t\)+-- should be less than \(p\). Works faster than @n_mulmod2_preinv@ if \(w\)+-- fixed and \(t\) from array (for example, scalar multiplication of+-- vector).+foreign import ccall "ulong_extras.h n_mulmod_shoup"+ n_mulmod_shoup :: CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> IO CMpLimb++-- | /n_mulmod_precomp_shoup/ /w/ /p/ +--+-- Returns \(w'\), scaled approximation of \(w / p\). \(w'\) is equal to+-- the integer part of \(w \cdot 2^{\mathtt{FLINT\_BITS}} / p\).+foreign import ccall "ulong_extras.h n_mulmod_precomp_shoup"+ n_mulmod_precomp_shoup :: CMpLimb -> CMpLimb -> IO CMpLimb++-- Divisibility testing --------------------------------------------------------++-- | /n_divides/ /q/ /n/ /p/ +--+-- Returns @1@ if @p@ divides @n@ and sets @q@ to the quotient, otherwise+-- returns @0@ and sets @q@ to @0@.+foreign import ccall "ulong_extras.h n_divides"+ n_divides :: Ptr CMpLimb -> CMpLimb -> CMpLimb -> IO CInt++-- Prime number generation and counting ----------------------------------------++-- | /n_primes_init/ /iter/ +--+-- Initialises the prime number iterator @iter@ for use.+foreign import ccall "ulong_extras.h n_primes_init"+ n_primes_init :: Ptr CNPrimes -> IO ()++-- | /n_primes_clear/ /iter/ +--+-- Clears memory allocated by the prime number iterator @iter@.+foreign import ccall "ulong_extras.h n_primes_clear"+ n_primes_clear :: Ptr CNPrimes -> IO ()++foreign import ccall "ulong_extras.h &n_primes_clear"+ p_n_primes_clear :: FunPtr (Ptr CNPrimes -> IO ())++-- | /n_primes_next/ /iter/ +--+-- Returns the next prime number and advances the state of @iter@. The+-- first call returns 2.+-- +-- Small primes are looked up from @flint_small_primes@. When this table is+-- exhausted, primes are generated in blocks by calling+-- @n_primes_sieve_range@.+foreign import ccall "ulong_extras.h n_primes_next"+ n_primes_next :: Ptr CNPrimes -> IO CULong++-- | /n_primes_jump_after/ /iter/ /n/ +--+-- Changes the state of @iter@ to start generating primes after \(n\)+-- (excluding \(n\) itself).+foreign import ccall "ulong_extras.h n_primes_jump_after"+ n_primes_jump_after :: Ptr CNPrimes -> CULong -> IO ()++-- | /n_primes_extend_small/ /iter/ /bound/ +--+-- Extends the table of small primes in @iter@ to contain at least two+-- primes larger than or equal to @bound@.+foreign import ccall "ulong_extras.h n_primes_extend_small"+ n_primes_extend_small :: Ptr CNPrimes -> CULong -> IO ()++-- | /n_primes_sieve_range/ /iter/ /a/ /b/ +--+-- Sets the block endpoints of @iter@ to the smallest and largest odd+-- numbers between \(a\) and \(b\) inclusive, and sieves to mark all odd+-- primes in this range. The iterator state is changed to point to the+-- first number in the sieved range.+foreign import ccall "ulong_extras.h n_primes_sieve_range"+ n_primes_sieve_range :: Ptr CNPrimes -> CULong -> CULong -> IO ()++-- | /n_compute_primes/ /num_primes/ +--+-- Precomputes at least @num_primes@ primes and their @double@ precomputed+-- inverses and stores them in an internal cache. Assuming that FLINT has+-- been built with support for thread-local storage, each thread has its+-- own cache.+foreign import ccall "ulong_extras.h n_compute_primes"+ n_compute_primes :: CULong -> IO ()++-- | /n_primes_arr_readonly/ /num_primes/ +--+-- Returns a pointer to a read-only array of the first @num_primes@ prime+-- numbers. The computed primes are cached for repeated calls. The pointer+-- is valid until the user calls @n_cleanup_primes@ in the same thread.+foreign import ccall "ulong_extras.h n_primes_arr_readonly"+ n_primes_arr_readonly :: CULong -> IO (Ptr CULong)++-- | /n_prime_inverses_arr_readonly/ /n/ +--+-- Returns a pointer to a read-only array of inverses of the first+-- @num_primes@ prime numbers. The computed primes are cached for repeated+-- calls. The pointer is valid until the user calls @n_cleanup_primes@ in+-- the same thread.+foreign import ccall "ulong_extras.h n_prime_inverses_arr_readonly"+ n_prime_inverses_arr_readonly :: CULong -> IO (Ptr CDouble)++-- | /n_cleanup_primes/ +--+-- Frees the internal cache of prime numbers used by the current thread.+-- This will invalidate any pointers returned by @n_primes_arr_readonly@ or+-- @n_prime_inverses_arr_readonly@.+foreign import ccall "ulong_extras.h n_cleanup_primes"+ n_cleanup_primes :: IO ()++-- | /n_nextprime/ /n/ /proved/ +--+-- Returns the next prime after \(n\). Assumes the result will fit in an+-- @ulong@. If proved is \(0\), i.e. false, the prime is not proven prime,+-- otherwise it is.+foreign import ccall "ulong_extras.h n_nextprime"+ n_nextprime :: CULong -> CInt -> IO CULong++-- | /n_prime_pi/ /n/ +--+-- Returns the value of the prime counting function \(\pi(n)\), i.e. the+-- number of primes less than or equal to \(n\). The invariant+-- @n_prime_pi(n_nth_prime(n)) == n@.+-- +-- Currently, this function simply extends the table of cached primes up to+-- an upper limit and then performs a binary search.+foreign import ccall "ulong_extras.h n_prime_pi"+ n_prime_pi :: CULong -> IO CULong++-- | /n_prime_pi_bounds/ /lo/ /hi/ /n/ +--+-- Calculates lower and upper bounds for the value of the prime counting+-- function @lo \<= pi(n) \<= hi@. If @lo@ and @hi@ point to the same+-- location, the high value will be stored.+-- +-- This does a table lookup for small values, then switches over to some+-- proven bounds.+-- +-- The upper approximation is \(1.25506 n / \ln n\), and the lower is+-- \(n / \ln n\). These bounds are due to Rosser and Schoenfeld+-- < [RosSch1962]> and valid for \(n \geq 17\).+-- +-- We use the number of bits in \(n\) (or one less) to form an+-- approximation to \(\ln n\), taking care to use a value too small or too+-- large to maintain the inequality.+foreign import ccall "ulong_extras.h n_prime_pi_bounds"+ n_prime_pi_bounds :: Ptr CULong -> Ptr CULong -> CULong -> IO ()++-- | /n_nth_prime/ /n/ +--+-- Returns the \(n\)th prime number \(p_n\), using the mathematical+-- indexing convention \(p_1 = 2, p_2 = 3, \dotsc\).+-- +-- This function simply ensures that the table of cached primes is large+-- enough and then looks up the entry.+foreign import ccall "ulong_extras.h n_nth_prime"+ n_nth_prime :: CULong -> IO CULong++-- | /n_nth_prime_bounds/ /lo/ /hi/ /n/ +--+-- Calculates lower and upper bounds for the \(n\)th prime number \(p_n\) ,+-- @lo \<= p_n \<= hi@. If @lo@ and @hi@ point to the same location, the+-- high value will be stored. Note that this function will overflow for+-- sufficiently large \(n\).+-- +-- We use the following estimates, valid for \(n > 5\) :+-- +-- \[`\]+-- \[\begin{aligned}+-- p_n & > n (\ln n + \ln \ln n - 1) \\+-- p_n & < n (\ln n + \ln \ln n) \\+-- p_n & < n (\ln n + \ln \ln n - 0.9427) \quad (n \geq 15985)+-- \end{aligned}\]+-- +-- The first inequality was proved by Dusart < [Dus1999]>, and the last is+-- due to Massias and Robin < [MasRob1996]>. For a further overview, see+-- <http://primes.utm.edu/howmany.shtml> .+-- +-- We bound \(\ln n\) using the number of bits in \(n\) as in+-- @n_prime_pi_bounds()@, and estimate \(\ln \ln n\) to the nearest+-- integer; this function is nearly constant.+foreign import ccall "ulong_extras.h n_nth_prime_bounds"+ n_nth_prime_bounds :: Ptr CULong -> Ptr CULong -> CULong -> IO ()++-- Primality testing -----------------------------------------------------------++-- | /n_is_oddprime_small/ /n/ +--+-- Returns \(1\) if \(n\) is an odd prime smaller than+-- @FLINT_ODDPRIME_SMALL_CUTOFF@. Expects \(n\) to be odd and smaller than+-- the cutoff.+-- +-- This function merely uses a lookup table with one bit allocated for each+-- odd number up to the cutoff.+foreign import ccall "ulong_extras.h n_is_oddprime_small"+ n_is_oddprime_small :: CULong -> IO CInt++-- | /n_is_oddprime_binary/ /n/ +--+-- This function performs a simple binary search through the table of+-- cached primes for \(n\). If it exists in the array it returns \(1\),+-- otherwise \(0\). For the algorithm to operate correctly \(n\) should be+-- odd and at least \(17\).+-- +-- Lower and upper bounds are computed with @n_prime_pi_bounds@. Once we+-- have bounds on where to look in the table, we refine our search with a+-- simple binary algorithm, taking the top or bottom of the current+-- interval as necessary.+foreign import ccall "ulong_extras.h n_is_oddprime_binary"+ n_is_oddprime_binary :: CULong -> IO CInt++-- | /n_is_prime_pocklington/ /n/ /iterations/ +--+-- Tests if \(n\) is a prime using the Pocklington--Lehmer primality test.+-- If \(1\) is returned \(n\) has been proved prime. If \(0\) is returned+-- \(n\) is composite. However \(-1\) may be returned if nothing was proved+-- either way due to the number of iterations being too small.+-- +-- The most time consuming part of the algorithm is factoring \(n - 1\).+-- For this reason @n_factor_partial@ is used, which uses a combination of+-- trial factoring and Hart\'s one line factor algorithm < [Har2012]> to+-- try to quickly factor \(n - 1\). Additionally if the cofactor is less+-- than the square root of \(n - 1\) the algorithm can still proceed.+-- +-- One can also specify a number of iterations if less time should be+-- taken. Simply set this to @WORD(0)@ if this is irrelevant. In most cases+-- a greater number of iterations will not significantly affect timings as+-- most of the time is spent factoring.+-- +-- See <https://mathworld.wolfram.com/PocklingtonsTheorem.html> for a+-- description of the algorithm.+foreign import ccall "ulong_extras.h n_is_prime_pocklington"+ n_is_prime_pocklington :: CULong -> CULong -> IO CInt++-- | /n_is_prime_pseudosquare/ /n/ +--+-- Tests if \(n\) is a prime according to Theorem 2.7 < [LukPatWil1996]>.+-- +-- We first factor \(N\) using trial division up to some limit \(B\). In+-- fact, the number of primes used in the trial factoring is at most+-- @FLINT_PSEUDOSQUARES_CUTOFF@.+-- +-- Next we compute \(N/B\) and find the next pseudosquare \(L_p\) above+-- this value, using a static table as per+-- <https://oeis.org/A002189/b002189.txt> .+-- +-- As noted in the text, if \(p\) is prime then Step 3 will pass. This test+-- rejects many composites, and so by this time we suspect that \(p\) is+-- prime. If \(N\) is \(3\) or \(7\) modulo \(8\), we are done, and \(N\)+-- is prime.+-- +-- We now run a probable prime test, for which no known counterexamples are+-- known, to reject any composites. We then proceed to prove \(N\) prime by+-- executing Step 4. In the case that \(N\) is \(1\) modulo \(8\), if Step+-- 4 fails, we extend the number of primes \(p_i\) at Step 3 and hope to+-- find one which passes Step 4. We take the test one past the largest+-- \(p\) for which we have pseudosquares \(L_p\) tabulated, as this already+-- corresponds to the next \(L_p\) which is bigger than \(2^{64}\) and+-- hence larger than any prime we might be testing.+-- +-- As explained in the text, Condition 4 cannot fail if \(N\) is prime.+-- +-- The possibility exists that the probable prime test declares a composite+-- prime. However in that case an error is printed, as that would be of+-- independent interest.+foreign import ccall "ulong_extras.h n_is_prime_pseudosquare"+ n_is_prime_pseudosquare :: CULong -> IO CInt++-- | /n_is_prime/ /n/ +--+-- Tests if \(n\) is a prime. This first sieves for small prime factors,+-- then simply calls @n_is_probabprime@. This has been checked against the+-- tables of Feitsma and Galway+-- <http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html> and thus+-- constitutes a check for primality (rather than just pseudoprimality) up+-- to \(2^{64}\).+-- +-- In future, this test may produce and check a certificate of primality.+-- This is likely to be significantly slower for prime inputs.+foreign import ccall "ulong_extras.h n_is_prime"+ n_is_prime :: CULong -> IO CInt++-- | /n_is_strong_probabprime_precomp/ /n/ /npre/ /a/ /d/ +--+-- Tests if \(n\) is a strong probable prime to the base \(a\). We require+-- that \(d\) is set to the largest odd factor of \(n - 1\) and @npre@ is a+-- precomputed inverse of \(n\) computed with @n_precompute_inverse@. We+-- also require that \(n < 2^{53}\), \(a\) to be reduced modulo \(n\) and+-- not \(0\) and \(n\) to be odd.+-- +-- If we write \(n - 1 = 2^s d\) where \(d\) is odd then \(n\) is a strong+-- probable prime to the base \(a\), i.e. an \(a\)-SPRP, if either+-- \(a^d = 1 \pmod n\) or \((a^d)^{2^r} = -1 \pmod n\) for some \(r\) less+-- than \(s\).+-- +-- A description of strong probable primes is given here:+-- <https://mathworld.wolfram.com/StrongPseudoprime.html>+foreign import ccall "ulong_extras.h n_is_strong_probabprime_precomp"+ n_is_strong_probabprime_precomp :: CULong -> CDouble -> CULong -> CULong -> IO CInt++-- | /n_is_strong_probabprime2_preinv/ /n/ /ninv/ /a/ /d/ +--+-- Tests if \(n\) is a strong probable prime to the base \(a\). We require+-- that \(d\) is set to the largest odd factor of \(n - 1\) and @npre@ is a+-- precomputed inverse of \(n\) computed with @n_preinvert_limb@. We+-- require a to be reduced modulo \(n\) and not \(0\) and \(n\) to be odd.+-- +-- If we write \(n - 1 = 2^s d\) where \(d\) is odd then \(n\) is a strong+-- probable prime to the base \(a\) (an \(a\)-SPRP) if either+-- \(a^d = 1 \pmod n\) or \((a^d)^{2^r} = -1 \pmod n\) for some \(r\) less+-- than \(s\).+-- +-- A description of strong probable primes is given here:+-- <https://mathworld.wolfram.com/StrongPseudoprime.html>+foreign import ccall "ulong_extras.h n_is_strong_probabprime2_preinv"+ n_is_strong_probabprime2_preinv :: CULong -> CULong -> CULong -> CULong -> IO CInt++-- | /n_is_probabprime_fermat/ /n/ /i/ +--+-- Returns \(1\) if \(n\) is a base \(i\) Fermat probable prime. Requires+-- \(1 < i < n\) and that \(i\) does not divide \(n\).+-- +-- By Fermat\'s Little Theorem if \(i^{n-1}\) is not congruent to \(1\)+-- then \(n\) is not prime.+foreign import ccall "ulong_extras.h n_is_probabprime_fermat"+ n_is_probabprime_fermat :: CULong -> CULong -> IO CInt++-- | /n_is_probabprime_fibonacci/ /n/ +--+-- Let \(F_j\) be the \(j\)th element of the Fibonacci sequence+-- \(0, 1, 1, 2, 3, 5, \dotsc\), starting at \(j = 0\). Then if \(n\) is+-- prime we have \(F_{n - (n/5)} = 0 \pmod n\), where \((n/5)\) is the+-- Jacobi symbol.+-- +-- For further details, see pp. 142 < [CraPom2005]>.+-- +-- We require that \(n\) is not divisible by \(2\) or \(5\).+foreign import ccall "ulong_extras.h n_is_probabprime_fibonacci"+ n_is_probabprime_fibonacci :: CULong -> IO CInt++-- | /n_is_probabprime_BPSW/ /n/ +--+-- Implements a Baillie--Pomerance--Selfridge--Wagstaff probable primality+-- test. This is a variant of the usual BPSW test (which only uses strong+-- base-2 probable prime and Lucas-Selfridge tests, see Baillie and+-- Wagstaff < [BaiWag1980]>).+-- +-- This implementation makes use of a weakening of the usual Baillie-PSW+-- test given in < [Chen2003]>, namely replacing the Lucas test with a+-- Fibonacci test when \(n \equiv 2, 3 \pmod{5}\) (see also the comment on+-- page 143 of < [CraPom2005]>), regarding Fibonacci pseudoprimes.+-- +-- There are no known counterexamples to this being a primality test.+-- +-- Up to \(2^{64}\) the test we use has been checked against tables of+-- pseudoprimes. Thus it is a primality test up to this limit.+foreign import ccall "ulong_extras.h n_is_probabprime_BPSW"+ n_is_probabprime_BPSW :: CULong -> IO CInt++-- | /n_is_probabprime_lucas/ /n/ +--+-- For details on Lucas pseudoprimes, see [pp. 143] < [CraPom2005]>.+-- +-- We implement a variant of the Lucas pseudoprime test similar to that+-- described by Baillie and Wagstaff < [BaiWag1980]>.+foreign import ccall "ulong_extras.h n_is_probabprime_lucas"+ n_is_probabprime_lucas :: CULong -> IO CInt++-- | /n_is_probabprime/ /n/ +--+-- Tests if \(n\) is a probable prime. Up to @FLINT_ODDPRIME_SMALL_CUTOFF@+-- this algorithm uses @n_is_oddprime_small@ which uses a lookup table.+-- +-- Next it calls @n_compute_primes@ with the maximum table size and uses+-- this table to perform a binary search for \(n\) up to the table limit.+-- +-- Then up to \(1050535501\) it uses a number of strong probable prime+-- tests, @n_is_strong_probabprime_preinv@, etc., for various bases. The+-- output of the algorithm is guaranteed to be correct up to this bound due+-- to exhaustive tables, described at+-- <http://uucode.com/obf/dalbec/alg.html> .+-- +-- Beyond that point the BPSW probabilistic primality test is used, by+-- calling the function @n_is_probabprime_BPSW@. There are no known+-- counterexamples, and it has been checked against the tables of Feitsma+-- and Galway and up to the accuracy of those tables, this is an exhaustive+-- check up to \(2^{64}\), i.e. there are no counterexamples.+foreign import ccall "ulong_extras.h n_is_probabprime"+ n_is_probabprime :: CULong -> IO CInt++-- Chinese remaindering --------------------------------------------------------++-- | /n_CRT/ /r1/ /m1/ /r2/ /m2/ +--+-- Use the Chinese Remainder Theorem to return the unique value+-- \(0 \le x < M\) congruent to \(r_1\) modulo \(m_1\) and \(r_2\) modulo+-- \(m_2\), where \(M = m_1 \times m_2\) is assumed to fit a ulong.+-- +-- It is assumed that \(m_1\) and \(m_2\) are positive integers greater+-- than \(1\) and coprime. It is assumed that \(0 \le r_1 < m_1\) and+-- \(0 \le r_2 < m_2\).+foreign import ccall "ulong_extras.h n_CRT"+ n_CRT :: CULong -> CULong -> CULong -> CULong -> IO CULong++-- Square root and perfect power testing ---------------------------------------++-- | /n_sqrt/ /a/ +--+-- Computes the integer truncation of the square root of \(a\).+-- +-- The implementation uses a call to the IEEE floating point sqrt function.+-- The integer itself is represented by the nearest double and its square+-- root is computed to the nearest place. If \(a\) is one below a square,+-- the rounding may be up, whereas if it is one above a square, the+-- rounding will be down. Thus the square root may be one too large in some+-- instances which we then adjust by checking if we have the right value.+-- We also have to be careful when the square of this too large value+-- causes an overflow. The same assumptions hold for a single precision+-- float provided the square root itself can be represented in a single+-- float, i.e. for \(a < 281474976710656 = 2^{46}\).+foreign import ccall "ulong_extras.h n_sqrt"+ n_sqrt :: CULong -> IO CULong++-- | /n_sqrtrem/ /r/ /a/ +--+-- Computes the integer truncation of the square root of \(a\).+-- +-- The integer itself is represented by the nearest double and its square+-- root is computed to the nearest place. If \(a\) is one below a square,+-- the rounding may be up, whereas if it is one above a square, the+-- rounding will be down. Thus the square root may be one too large in some+-- instances which we then adjust by checking if we have the right value.+-- We also have to be careful when the square of this too large value+-- causes an overflow. The same assumptions hold for a single precision+-- float provided the square root itself can be represented in a single+-- float, i.e. for \(a < 281474976710656 = 2^{46}\).+-- +-- The remainder is computed by subtracting the square of the computed+-- square root from \(a\).+foreign import ccall "ulong_extras.h n_sqrtrem"+ n_sqrtrem :: Ptr CULong -> CULong -> IO CULong++-- | /n_is_square/ /x/ +--+-- Returns \(1\) if \(x\) is a square, otherwise \(0\).+-- +-- This code first checks if \(x\) is a square modulo \(64\),+-- \(63 = 3 \times 3 \times 7\) and \(65 = 5 \times 13\), using lookup+-- tables, and if so it then takes a square root and checks that the square+-- of this equals the original value.+foreign import ccall "ulong_extras.h n_is_square"+ n_is_square :: CULong -> IO CInt++-- | /n_is_perfect_power235/ /n/ +--+-- Returns \(1\) if \(n\) is a perfect square, cube or fifth power.+-- +-- This function uses a series of modular tests to reject most non+-- 235-powers. Each modular test returns a value from 0 to 7 whose bits+-- respectively indicate whether the value is a square, cube or fifth power+-- modulo the given modulus. When these are logically @AND@-ed together,+-- this gives a powerful test which will reject most non-235 powers.+-- +-- If a bit remains set indicating it may be a square, a standard square+-- root test is performed. Similarly a cube root or fifth root can be+-- taken, if indicated, to determine whether the power of that root is+-- exactly equal to \(n\).+foreign import ccall "ulong_extras.h n_is_perfect_power235"+ n_is_perfect_power235 :: CULong -> IO CInt++-- | /n_is_perfect_power/ /root/ /n/ +--+-- If \(n = r^k\), return \(k\) and set @root@ to \(r\). Note that \(0\)+-- and \(1\) are considered squares. No guarantees are made about \(r\) or+-- \(k\) being the minimum possible value.+foreign import ccall "ulong_extras.h n_is_perfect_power"+ n_is_perfect_power :: Ptr CULong -> CULong -> IO CInt++-- | /n_rootrem/ /remainder/ /n/ /root/ +--+-- This function uses the Newton iteration method to calculate the nth root+-- of a number. First approximation is calculated by an algorithm mentioned+-- in this article:+-- <https://en.wikipedia.org/wiki/Fast_inverse_square_root> . Instead of+-- the inverse square root, the nth root is calculated.+-- +-- Returns the integer part of @n ^ 1\/root@. Remainder is set as+-- @n - base^root@. In case \(n < 1\) or @root \< 1@, \(0\) is returned.+foreign import ccall "ulong_extras.h n_rootrem"+ n_rootrem :: Ptr CULong -> CULong -> CULong -> IO CULong++-- | /n_cbrt/ /n/ +--+-- This function returns the integer truncation of the cube root of \(n\).+-- First approximation is calculated by an algorithm mentioned in this+-- article: <https://en.wikipedia.org/wiki/Fast_inverse_square_root> .+-- Instead of the inverse square root, the cube root is calculated. This+-- functions uses different algorithms to calculate the cube root,+-- depending upon the size of \(n\). For numbers greater than \(2^{46}\),+-- it uses @n_cbrt_chebyshev_approx@. Otherwise, it makes use of the+-- iteration,+-- \(x \leftarrow x - (x\cdot x\cdot x - a)\cdot x/(2\cdot x\cdot x\cdot x + a)\)+-- for getting a good estimate, as mentioned in the paper by W. Kahan+-- < [Kahan1991]> .+foreign import ccall "ulong_extras.h n_cbrt"+ n_cbrt :: CULong -> IO CULong++-- | /n_cbrt_newton_iteration/ /n/ +--+-- This function returns the integer truncation of the cube root of \(n\).+-- Makes use of Newton iterations to get a close value, and then adjusts+-- the estimate so as to get the correct value.+foreign import ccall "ulong_extras.h n_cbrt_newton_iteration"+ n_cbrt_newton_iteration :: CULong -> IO CULong++-- | /n_cbrt_binary_search/ /n/ +--+-- This function returns the integer truncation of the cube root of \(n\).+-- Uses binary search to get the correct value.+foreign import ccall "ulong_extras.h n_cbrt_binary_search"+ n_cbrt_binary_search :: CULong -> IO CULong++-- | /n_cbrt_chebyshev_approx/ /n/ +--+-- This function returns the integer truncation of the cube root of \(n\).+-- The number is first expressed in the form @x * 2^exp@. This ensures+-- \(x\) is in the range [0.5, 1]. Cube root of x is calculated using+-- Chebyshev\'s approximation polynomial for the function \(y = x^{1/3}\).+-- The values of the coefficient are calculated from the Python module+-- mpmath, <https://mpmath.org>, using the function chebyfit. x is+-- multiplied by @2^exp@ and the cube root of 1, 2 or 4 (according to+-- @exp%3@).+foreign import ccall "ulong_extras.h n_cbrt_chebyshev_approx"+ n_cbrt_chebyshev_approx :: CULong -> IO CULong++-- | /n_cbrtrem/ /remainder/ /n/ +--+-- This function returns the integer truncation of the cube root of \(n\).+-- Remainder is set as \(n\) minus the cube of the value returned.+foreign import ccall "ulong_extras.h n_cbrtrem"+ n_cbrtrem :: Ptr CULong -> CULong -> IO CULong++-- Factorisation ---------------------------------------------------------------++-- | /n_remove/ /n/ /p/ +--+-- Removes the highest possible power of \(p\) from \(n\), replacing \(n\)+-- with the quotient. The return value is the highest power of \(p\) that+-- divided \(n\). Assumes \(n\) is not \(0\).+-- +-- For \(p = 2\) trailing zeroes are counted. For other primes \(p\) is+-- repeatedly squared and stored in a table of powers with the current+-- highest power of \(p\) removed at each step until no higher power can be+-- removed. The algorithm then proceeds down the power tree again removing+-- powers of \(p\) until none remain.+foreign import ccall "ulong_extras.h n_remove"+ n_remove :: Ptr CULong -> CULong -> IO CInt++-- | /n_remove2_precomp/ /n/ /p/ /ppre/ +--+-- Removes the highest possible power of \(p\) from \(n\), replacing \(n\)+-- with the quotient. The return value is the highest power of \(p\) that+-- divided \(n\). Assumes \(n\) is not \(0\). We require @ppre@ to be set+-- to a precomputed inverse of \(p\) computed with @n_precompute_inverse@.+-- +-- For \(p = 2\) trailing zeroes are counted. For other primes \(p\) we+-- make repeated use of @n_divrem2_precomp@ until division by \(p\) is no+-- longer possible.+foreign import ccall "ulong_extras.h n_remove2_precomp"+ n_remove2_precomp :: Ptr CULong -> CULong -> CDouble -> IO CInt++foreign import ccall "ulong_extras.h n_factor_init"+ n_factor_init :: Ptr CNFactor -> IO ()++-- | /n_factor_insert/ /factors/ /p/ /exp/ +--+-- Inserts the given prime power factor @p^exp@ into the @n_factor_t@+-- @factors@. See the documentation for @n_factor_trial@ for a description+-- of the @n_factor_t@ type.+-- +-- The algorithm performs a simple search to see if \(p\) already exists as+-- a prime factor in the structure. If so the exponent there is increased+-- by the supplied exponent. Otherwise a new factor @p^exp@ is added to the+-- end of the structure.+-- +-- There is no test code for this function other than its use by the+-- various factoring functions, which have test code.+foreign import ccall "ulong_extras.h n_factor_insert"+ n_factor_insert :: Ptr (Ptr CNFactor) -> CULong -> CULong -> IO ()++-- | /n_factor_trial_range/ /factors/ /n/ /start/ /num_primes/ +--+-- Trial factor \(n\) with the first @num_primes@ primes, but starting at+-- the prime with index start (counting from zero).+-- +-- One requires an initialised @n_factor_t@ structure, but factors will be+-- added by default to an already used @n_factor_t@. Use the function+-- @n_factor_init@ defined in @ulong_extras@ if initialisation has not+-- already been completed on factors.+-- +-- Once completed, @num@ will contain the number of distinct prime factors+-- found. The field \(p\) is an array of @ulong@s containing the distinct+-- prime factors, @exp@ an array containing the corresponding exponents.+-- +-- The return value is the unfactored cofactor after trial factoring is+-- done.+-- +-- The function calls @n_compute_primes@ automatically. See the+-- documentation for that function regarding limits.+-- +-- The algorithm stops when the current prime has a square exceeding \(n\),+-- as no prime factor of \(n\) can exceed this unless \(n\) is prime.+-- +-- The precomputed inverses of all the primes computed by+-- @n_compute_primes@ are utilised with the @n_remove2_precomp@ function.+foreign import ccall "ulong_extras.h n_factor_trial_range"+ n_factor_trial_range :: Ptr (Ptr CNFactor) -> CULong -> CULong -> CULong -> IO CULong++-- | /n_factor_trial/ /factors/ /n/ /num_primes/ +--+-- This function calls @n_factor_trial_range@, with the value of \(0\) for+-- @start@. By default this adds factors to an already existing+-- @n_factor_t@ or to a newly initialised one.+foreign import ccall "ulong_extras.h n_factor_trial"+ n_factor_trial :: Ptr (Ptr CNFactor) -> CULong -> CULong -> IO CULong++-- | /n_factor_power235/ /exp/ /n/ +--+-- Returns \(0\) if \(n\) is not a perfect square, cube or fifth power.+-- Otherwise it returns the root and sets @exp@ to either \(2\), \(3\) or+-- \(5\) appropriately.+-- +-- This function uses a series of modular tests to reject most non+-- 235-powers. Each modular test returns a value from 0 to 7 whose bits+-- respectively indicate whether the value is a square, cube or fifth power+-- modulo the given modulus. When these are logically @AND@-ed together,+-- this gives a powerful test which will reject most non-235 powers.+-- +-- If a bit remains set indicating it may be a square, a standard square+-- root test is performed. Similarly a cube root or fifth root can be+-- taken, if indicated, to determine whether the power of that root is+-- exactly equal to \(n\).+foreign import ccall "ulong_extras.h n_factor_power235"+ n_factor_power235 :: Ptr CULong -> CULong -> IO CULong++-- | /n_factor_one_line/ /n/ /iters/ +--+-- This implements Bill Hart\'s one line factoring algorithm < [Har2012]>.+-- It is a variant of Fermat\'s algorithm which cycles through a large+-- number of multipliers instead of incrementing the square root. It is+-- faster than SQUFOF for \(n\) less than about \(2^{40}\).+foreign import ccall "ulong_extras.h n_factor_one_line"+ n_factor_one_line :: CULong -> CULong -> IO CULong++-- | /n_factor_lehman/ /n/ +--+-- Lehman\'s factoring algorithm. Currently works up to \(10^{16}\), but is+-- not particularly efficient and so is not used in the general factor+-- function. Always returns a factor of \(n\).+foreign import ccall "ulong_extras.h n_factor_lehman"+ n_factor_lehman :: CULong -> IO CULong++-- | /n_factor_SQUFOF/ /n/ /iters/ +--+-- Attempts to split \(n\) using the given number of iterations of SQUFOF.+-- Simply set @iters@ to @WORD(0)@ for maximum persistence.+-- +-- The version of SQUFOF implemented here is as described by Gower and+-- Wagstaff < [GowWag2008]>.+-- +-- We start by trying SQUFOF directly on \(n\). If that fails we multiply+-- it by each of the primes in @flint_primes_small@ in turn. As this+-- multiplication may result in a two limb value we allow this in our+-- implementation of SQUFOF. As SQUFOF works with values about half the+-- size of \(n\) it only needs single limb arithmetic internally.+-- +-- If SQUFOF fails to factor \(n\) we return \(0\), however with @iters@+-- large enough this should never happen.+foreign import ccall "ulong_extras.h n_factor_SQUFOF"+ n_factor_SQUFOF :: CULong -> CULong -> IO CULong++-- | /n_factor/ /factors/ /n/ /proved/ +--+-- Factors \(n\) with no restrictions on \(n\). If the prime factors are+-- required to be checked with a primality test, one may set @proved@ to+-- \(1\), otherwise set it to \(0\), and they will only be probable primes.+-- NB: at the present there is no difference because the probable prime+-- tests have been exhaustively tested up to \(2^{64}\).+-- +-- However, in future, this flag may produce and separately check a+-- primality certificate. This may be quite slow (and probably no less+-- reliable in practice).+-- +-- For details on the @n_factor_t@ structure, see @n_factor_trial@.+-- +-- This function first tries trial factoring with a number of primes+-- specified by the constant @FLINT_FACTOR_TRIAL_PRIMES@. If the cofactor+-- is \(1\) or prime the function returns with all the factors.+-- +-- Otherwise, the cofactor is placed in the array @factor_arr@. Whilst+-- there are factors remaining in there which have not been split, the+-- algorithm continues. At each step each factor is first checked to+-- determine if it is a perfect power. If so it is replaced by the power+-- that has been found. Next if the factor is small enough and composite,+-- in particular, less than @FLINT_FACTOR_ONE_LINE_MAX@ then+-- @n_factor_one_line@ is called with @FLINT_FACTOR_ONE_LINE_ITERS@ to try+-- and split the factor. If that fails or the factor is too large for+-- @n_factor_one_line@ then @n_factor_SQUFOF@ is called, with+-- @FLINT_FACTOR_SQUFOF_ITERS@. If that fails an error results and the+-- program aborts. However this should not happen in practice.+foreign import ccall "ulong_extras.h n_factor"+ n_factor :: Ptr CNFactor -> CULong -> CInt -> IO ()++-- | /n_factor_trial_partial/ /factors/ /n/ /prod/ /num_primes/ /limit/ +--+-- Attempts trial factoring of \(n\) with the first @num_primes primes@,+-- but stops when the product of prime factors so far exceeds @limit@.+-- +-- One requires an initialised @n_factor_t@ structure, but factors will be+-- added by default to an already used @n_factor_t@. Use the function+-- @n_factor_init@ defined in @ulong_extras@ if initialisation has not+-- already been completed on @factors@.+-- +-- Once completed, @num@ will contain the number of distinct prime factors+-- found. The field \(p\) is an array of @ulong@s containing the distinct+-- prime factors, @exp@ an array containing the corresponding exponents.+-- +-- The return value is the unfactored cofactor after trial factoring is+-- done. The value @prod@ will be set to the product of the factors found.+-- +-- The function calls @n_compute_primes@ automatically. See the+-- documentation for that function regarding limits.+-- +-- The algorithm stops when the current prime has a square exceeding \(n\),+-- as no prime factor of \(n\) can exceed this unless \(n\) is prime.+-- +-- The precomputed inverses of all the primes computed by+-- @n_compute_primes@ are utilised with the @n_remove2_precomp@ function.+foreign import ccall "ulong_extras.h n_factor_trial_partial"+ n_factor_trial_partial :: Ptr (Ptr CNFactor) -> CULong -> Ptr CULong -> CULong -> CULong -> IO CULong++-- | /n_factor_partial/ /factors/ /n/ /limit/ /proved/ +--+-- Factors \(n\), but stops when the product of prime factors so far+-- exceeds @limit@.+-- +-- One requires an initialised @n_factor_t@ structure, but factors will be+-- added by default to an already used @n_factor_t@. Use the function+-- @n_factor_init()@ defined in @ulong_extras@ if initialisation has not+-- already been completed on @factors@.+-- +-- On exit, @num@ will contain the number of distinct prime factors found.+-- The field \(p\) is an array of @ulong@s containing the distinct prime+-- factors, @exp@ an array containing the corresponding exponents.+-- +-- The return value is the unfactored cofactor after factoring is done.+-- +-- The factors are proved prime if @proved@ is \(1\), otherwise they are+-- merely probably prime.+foreign import ccall "ulong_extras.h n_factor_partial"+ n_factor_partial :: Ptr (Ptr CNFactor) -> CULong -> CULong -> CInt -> IO CULong++-- | /n_factor_pp1/ /n/ /B1/ /c/ +--+-- Factors \(n\) using Williams\' \(p + 1\) factoring algorithm, with prime+-- limit set to \(B1\). We require \(c\) to be set to a random value. Each+-- trial of the algorithm with a different value of \(c\) gives another+-- chance to factor \(n\), with roughly exponentially decreasing chance of+-- finding a missing factor. If \(p + 1\) (or \(p - 1\)) is not smooth for+-- any factor \(p\) of \(n\), the algorithm will never succeed. The value+-- \(c\) should be less than \(n\) and greater than \(2\).+-- +-- If the algorithm succeeds, it returns the factor, otherwise it returns+-- \(0\) or \(1\) (the trivial factors modulo \(n\)).+foreign import ccall "ulong_extras.h n_factor_pp1"+ n_factor_pp1 :: CULong -> CULong -> CULong -> IO CULong++-- | /n_factor_pp1_wrapper/ /n/ +--+-- A simple wrapper around @n_factor_pp1@ which works in the range+-- \(31\)-64 bits. Below this point, trial factoring will always succeed.+-- This function mainly exists for @n_factor@ and is tuned to minimise the+-- time for @n_factor@ on numbers that reach the @n_factor_pp1@ stage, i.e.+-- after trial factoring and one line factoring.+foreign import ccall "ulong_extras.h n_factor_pp1_wrapper"+ n_factor_pp1_wrapper :: CULong -> IO CULong++-- | /n_factor_pollard_brent_single/ /factor/ /n/ /ninv/ /ai/ /xi/ /normbits/ /max_iters/ +--+-- Pollard Rho algorithm (with Brent modification) for integer+-- factorization. Assumes that the \(n\) is not prime. \(factor\) is set as+-- the factor if found. It is not assured that the factor found will be+-- prime. Does not compute the complete factorization, just one factor.+-- Returns 1 if factorization is successful (non trivial factor is found),+-- else returns 0. Assumes \(n\) is normalized (shifted by normbits bits),+-- and takes as input a precomputed inverse of \(n\) as computed by+-- @n_preinvert_limb@. \(ai\) and \(xi\) should also be shifted left by+-- \(normbits\).+-- +-- \(ai\) is the constant of the polynomial used, \(xi\) is the initial+-- value. \(max\_iters\) is the number of iterations tried in process of+-- finding the cycle.+-- +-- The algorithm used is a modification of the original Pollard Rho+-- algorithm, suggested by Richard Brent in the paper, available at+-- <https://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf>+foreign import ccall "ulong_extras.h n_factor_pollard_brent_single"+ n_factor_pollard_brent_single :: Ptr CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> IO CInt++-- | /n_factor_pollard_brent/ /factor/ /state/ /n_in/ /max_tries/ /max_iters/ +--+-- Pollard Rho algorithm, modified as suggested by Richard Brent. Makes a+-- call to @n_factor_pollard_brent_single@. The input parameters ai and xi+-- for @n_factor_pollard_brent_single@ are selected at random.+-- +-- If the algorithm fails to find a non trivial factor in one call, it+-- tries again (this time with a different set of random values). This+-- process is repeated a maximum of \(max\_tries\) times.+-- +-- Assumes \(n\) is not prime. \(factor\) is set as the factor found, if+-- factorization is successful. In such a case, 1 is returned. Otherwise, 0+-- is returned. Factor discovered is not necessarily prime.+foreign import ccall "ulong_extras.h n_factor_pollard_brent"+ n_factor_pollard_brent :: Ptr CMpLimb -> Ptr CFRandState -> CMpLimb -> CMpLimb -> CMpLimb -> IO CInt++-- Arithmetic functions --------------------------------------------------------++-- | /n_moebius_mu/ /n/ +--+-- Computes the Moebius function \(\mu(n)\), which is defined as+-- \(\mu(n) = 0\) if \(n\) has a prime factor of multiplicity greater than+-- \(1\), \(\mu(n) = -1\) if \(n\) has an odd number of distinct prime+-- factors, and \(\mu(n) = 1\) if \(n\) has an even number of distinct+-- prime factors. By convention, \(\mu(0) = 0\).+-- +-- For even numbers, we use the identities \(\mu(4n) = 0\) and+-- \(\mu(2n) = - \mu(n)\). Odd numbers up to a cutoff are then looked up+-- from a precomputed table storing \(\mu(n) + 1\) in groups of two bits.+-- +-- For larger \(n\), we first check if \(n\) is divisible by a small odd+-- square and otherwise call @n_factor()@ and count the factors.+foreign import ccall "ulong_extras.h n_moebius_mu"+ n_moebius_mu :: CULong -> IO CInt++-- | /n_moebius_mu_vec/ /mu/ /len/ +--+-- Computes \(\mu(n)\) for @n = 0, 1, ..., len - 1@. This is done by+-- sieving over each prime in the range, flipping the sign of \(\mu(n)\)+-- for every multiple of a prime \(p\) and setting \(\mu(n) = 0\) for every+-- multiple of \(p^2\).+foreign import ccall "ulong_extras.h n_moebius_mu_vec"+ n_moebius_mu_vec :: Ptr CInt -> CULong -> IO ()++-- | /n_is_squarefree/ /n/ +--+-- Returns \(0\) if \(n\) is divisible by some perfect square, and \(1\)+-- otherwise. This simply amounts to testing whether \(\mu(n) \neq 0\). As+-- special cases, \(1\) is considered squarefree and \(0\) is not+-- considered squarefree.+foreign import ccall "ulong_extras.h n_is_squarefree"+ n_is_squarefree :: CULong -> IO CInt++-- | /n_euler_phi/ /n/ +--+-- Computes the Euler totient function \(\phi(n)\), counting the number of+-- positive integers less than or equal to \(n\) that are coprime to \(n\).+foreign import ccall "ulong_extras.h n_euler_phi"+ n_euler_phi :: CULong -> IO CULong++-- Factorials ------------------------------------------------------------------++-- | /n_factorial_fast_mod2_preinv/ /n/ /p/ /pinv/ +--+-- Returns \(n! \bmod p\) given a precomputed inverse of \(p\) as computed+-- by @n_preinvert_limb@. \(p\) is not required to be a prime, but no+-- special optimisations are made for composite \(p\). Uses fast multipoint+-- evaluation, running in about \(O(n^{1/2})\) time.+foreign import ccall "ulong_extras.h n_factorial_fast_mod2_preinv"+ n_factorial_fast_mod2_preinv :: CULong -> CULong -> CULong -> IO CULong++-- | /n_factorial_mod2_preinv/ /n/ /p/ /pinv/ +--+-- Returns \(n! \bmod p\) given a precomputed inverse of \(p\) as computed+-- by @n_preinvert_limb@. \(p\) is not required to be a prime, but no+-- special optimisations are made for composite \(p\).+-- +-- Uses a lookup table for small \(n\), otherwise computes the product if+-- \(n\) is not too large, and calls the fast algorithm for extremely large+-- \(n\).+foreign import ccall "ulong_extras.h n_factorial_mod2_preinv"+ n_factorial_mod2_preinv :: CULong -> CULong -> CULong -> IO CULong++-- Primitive Roots and Discrete Logarithms -------------------------------------++-- | /n_primitive_root_prime_prefactor/ /p/ /factors/ +--+-- Returns a primitive root for the multiplicative subgroup of+-- \(\mathbb{Z}/p\mathbb{Z}\) where \(p\) is prime given the factorisation+-- (@factors@) of \(p - 1\).+foreign import ccall "ulong_extras.h n_primitive_root_prime_prefactor"+ n_primitive_root_prime_prefactor :: CULong -> Ptr (Ptr CNFactor) -> IO CULong++-- | /n_primitive_root_prime/ /p/ +--+-- Returns a primitive root for the multiplicative subgroup of+-- \(\mathbb{Z}/p\mathbb{Z}\) where \(p\) is prime.+foreign import ccall "ulong_extras.h n_primitive_root_prime"+ n_primitive_root_prime :: CULong -> IO CULong++-- | /n_discrete_log_bsgs/ /b/ /a/ /n/ +--+-- Returns the discrete logarithm of \(b\) with respect to \(a\) in the+-- multiplicative subgroup of \(\mathbb{Z}/n\mathbb{Z}\) when+-- \(\mathbb{Z}/n\mathbb{Z}\) is cyclic. That is, it returns a number \(x\)+-- such that \(a^x = b \bmod n\). The multiplicative subgroup is only+-- cyclic when \(n\) is \(2\), \(4\), \(p^k\), or \(2p^k\) where \(p\) is+-- an odd prime and \(k\) is a positive integer.+foreign import ccall "ulong_extras.h n_discrete_log_bsgs"+ n_discrete_log_bsgs :: CULong -> CULong -> CULong -> IO CULong++-- Elliptic curve method for factorization of @mp_limb_t@ ----------------------+ +-- | /n_factor_ecm_double/ /x/ /z/ /x0/ /z0/ /n/ /n_ecm_inf/ +--+-- Sets the point \((x : z)\) to two times \((x_0 : z_0)\) modulo \(n\)+-- according to the formula+-- +-- \(x = (x_0 + z_0)^2 \cdot (x_0 - z_0)^2 \mod n,\)+-- +-- \(z = 4 x_0 z_0 \left((x_0 - z_0)^2 + 4a_{24}x_0z_0\right) \mod n.\)+-- +-- This group doubling is valid only for points expressed in Montgomery+-- projective coordinates.+foreign import ccall "ulong_extras.h n_factor_ecm_double"+ n_factor_ecm_double :: Ptr CMpLimb -> Ptr CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> Ptr CNEcm -> IO ()++-- | /n_factor_ecm_add/ /x/ /z/ /x1/ /z1/ /x2/ /z2/ /x0/ /z0/ /n/ /n_ecm_inf/ +--+-- Sets the point \((x : z)\) to the sum of \((x_1 : z_1)\) and+-- \((x_2 : z_2)\) modulo \(n\), given the difference \((x_0 : z_0)\)+-- according to the formula+-- +-- This group doubling is valid only for points expressed in Montgomery+-- projective coordinates.+foreign import ccall "ulong_extras.h n_factor_ecm_add"+ n_factor_ecm_add :: Ptr CMpLimb -> Ptr CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> Ptr CNEcm -> IO ()++-- | /n_factor_ecm_mul_montgomery_ladder/ /x/ /z/ /x0/ /z0/ /k/ /n/ /n_ecm_inf/ +--+-- Montgomery ladder algorithm for scalar multiplication of elliptic+-- points.+-- +-- Sets the point \((x : z)\) to \(k(x_0 : z_0)\) modulo \(n\).+-- +-- Valid only for points expressed in Montgomery projective coordinates.+foreign import ccall "ulong_extras.h n_factor_ecm_mul_montgomery_ladder"+ n_factor_ecm_mul_montgomery_ladder :: Ptr CMpLimb -> Ptr CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> Ptr CNEcm -> IO ()++-- | /n_factor_ecm_select_curve/ /f/ /sigma/ /n/ /n_ecm_inf/ +--+-- Selects a random elliptic curve given a random integer @sigma@,+-- according to Suyama\'s parameterization. If the factor is found while+-- selecting the curve, \(1\) is returned. In case the curve found is not+-- suitable, \(0\) is returned.+-- +-- Also selects the initial point \(x_0\), and the value of \((a + 2)/4\),+-- where \(a\) is a curve parameter. Sets \(z_0\) as \(1\) (shifted left by+-- @n_ecm_inf->normbits@). All these are stored in the @n_ecm_t@ struct.+-- +-- The curve selected is of Montgomery form, the points selected satisfy+-- the curve and are projective coordinates.+foreign import ccall "ulong_extras.h n_factor_ecm_select_curve"+ n_factor_ecm_select_curve :: Ptr CMpLimb -> CMpLimb -> CMpLimb -> Ptr CNEcm -> IO CInt++-- | /n_factor_ecm_stage_I/ /f/ /prime_array/ /num/ /B1/ /n/ /n_ecm_inf/ +--+-- Stage I implementation of the ECM algorithm.+-- +-- @f@ is set as the factor if found. @num@ is number of prime numbers+-- \(<=\) the bound @B1@. @prime_array@ is an array of first @B1@ primes.+-- \(n\) is the number being factored.+-- +-- If the factor is found, \(1\) is returned, otherwise \(0\).+foreign import ccall "ulong_extras.h n_factor_ecm_stage_I"+ n_factor_ecm_stage_I :: Ptr CMpLimb -> Ptr CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> Ptr CNEcm -> IO CInt++-- | /n_factor_ecm_stage_II/ /f/ /B1/ /B2/ /P/ /n/ /n_ecm_inf/ +--+-- Stage II implementation of the ECM algorithm.+-- +-- @f@ is set as the factor if found. @B1@, @B2@ are the two bounds. @P@ is+-- the primorial (approximately equal to \(\sqrt{B2}\)). \(n\) is the+-- number being factored.+-- +-- If the factor is found, \(1\) is returned, otherwise \(0\).+foreign import ccall "ulong_extras.h n_factor_ecm_stage_II"+ n_factor_ecm_stage_II :: Ptr CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> Ptr CNEcm -> IO CInt++-- | /n_factor_ecm/ /f/ /curves/ /B1/ /B2/ /state/ /n/ +--+-- Outer wrapper function for the ECM algorithm. It factors \(n\) which+-- must fit into a @mp_limb_t@.+-- +-- The function calls stage I and II, and the precomputations (builds+-- @prime_array@ for stage I, @GCD_table@ and @prime_table@ for stage II).+-- +-- @f@ is set as the factor if found. @curves@ is the number of random+-- curves being tried. @B1@, @B2@ are the two bounds or stage I and stage+-- II. \(n\) is the number being factored.+-- +-- If a factor is found in stage I, \(1\) is returned. If a factor is found+-- in stage II, \(2\) is returned. If a factor is found while selecting the+-- curve, \(-1\) is returned. Otherwise \(0\) is returned.+foreign import ccall "ulong_extras.h n_factor_ecm"+ n_factor_ecm :: Ptr CMpLimb -> CMpLimb -> CMpLimb -> CMpLimb -> Ptr CFRandState -> CMpLimb -> IO CInt+
+ src/Data/Number/Flint/ThreadPool.hs view
@@ -0,0 +1,13 @@+{-|+module : Data.Number.Flint.ThreadPool+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}++module Data.Number.Flint.ThreadPool (+ module Data.Number.Flint.ThreadPool.FFI,+) where++import Data.Number.Flint.ThreadPool.FFI+
+ src/Data/Number/Flint/ThreadPool/FFI.hsc view
@@ -0,0 +1,131 @@+{-|+module : Data.Number.Flint.ThreadPool.FFI+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de+-}+module Data.Number.Flint.ThreadPool.FFI (+ -- * Thread pool+ ThreadPool (..)+ , CThreadPool (..)+ , ThreadPoolHandle (..)+ , CThreadPoolHandle (..)+ -- * Thread pool functions+ , thread_pool_init+ , thread_pool_get_size+ , thread_pool_set_size+ , thread_pool_request+ , thread_pool_wake+ , thread_pool_wait+ , thread_pool_give_back+ , thread_pool_clear+) where++-- thread pool -----------------------------------------------------------------++import Foreign.C.String+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr ( Ptr, FunPtr, plusPtr )+import Foreign.Storable+import Foreign.Marshal ( free )++import Data.Number.Flint.Flint+import Data.Number.Flint.Fmpz+import Data.Number.Flint.Fmpq++#include <flint/flint.h>+#include <flint/thread_pool.h>++-- thread_pool_t ---------------------------------------------------------------++data ThreadPool = ThreadPool {-# UNPACK #-} !(ForeignPtr CThreadPool)+type CThreadPool = CFlint ThreadPool++instance Storable CThreadPool where+ {-# INLINE sizeOf #-}+ sizeOf _ = #{size thread_pool_t}+ {-# INLINE alignment #-}+ alignment _ = #{alignment thread_pool_t}+ peek = undefined+ poke = undefined++newThreadPool size = do+ x <- mallocForeignPtr+ withForeignPtr x $ \x -> thread_pool_init x size+ addForeignPtrFinalizer p_thread_pool_clear x+ return $ ThreadPool x++{-# INLINE withThreadPool #-}+withThreadPool (ThreadPool x) f = do+ withForeignPtr x $ \px -> f px >>= return . (ThreadPool x,)++-- thread_pool_handle_t --------------------------------------------------------++data ThreadPoolHandle = ThreadPoolHandle {-# UNPACK #-} !(ForeignPtr CThreadPoolHandle)+type CThreadPoolHandle = CFlint ThreadPoolHandle++-- Thread pool -----------------------------------------------------------------++-- | /thread_pool_init/ /T/ /size/ +-- +-- Initialise @T@ and create @size@ sleeping threads that are available to+-- work. If @size \\le 0@ no threads are created and future calls to+-- @thread_pool_request@ will return \(0\) (unless @thread_pool_set_size@+-- has been called).+foreign import ccall "flint/thread_pool.h thread_pool_init"+ thread_pool_init :: Ptr CThreadPool -> CLong -> IO ()++-- | /thread_pool_get_size/ /T/ +-- +-- Return the number of threads in @T@.+foreign import ccall "flint/thread_pool.h thread_pool_get_size"+ thread_pool_get_size :: Ptr CThreadPool -> IO CLong++-- | /thread_pool_set_size/ /T/ /new_size/ +-- +-- If all threads in @T@ are in the available state, resize @T@ and return+-- 1. Otherwise, return @0@.+foreign import ccall "flint/thread_pool.h thread_pool_set_size"+ thread_pool_set_size :: Ptr CThreadPool -> CLong -> IO CInt++-- | /thread_pool_request/ /T/ /out/ /requested/ +-- +-- Put at most @requested@ threads in the unavailable state and return+-- their handles. The handles are written to @out@ and the number of+-- handles written is returned. These threads must be released by a call to+-- @thread_pool_give_back@.+foreign import ccall "flint/thread_pool.h thread_pool_request"+ thread_pool_request :: Ptr CThreadPool -> Ptr CThreadPoolHandle -> CLong -> IO CLong++-- | /thread_pool_wake/ /T/ /i/ /max_workers/ /f/ /a/ +-- +-- Wake up a sleeping thread @i@ and have it work on @f(a)@. The thread+-- being woken will be allowed to start @max_workers@ additional worker+-- threads. Usually this value should be set to @0@.+foreign import ccall "flint/thread_pool.h thread_pool_wake"+ thread_pool_wake :: Ptr CThreadPool -> Ptr CThreadPoolHandle -> CInt -> FunPtr (Ptr () -> IO ()) -> Ptr () -> IO ()++-- | /thread_pool_wait/ /T/ /i/ +-- +-- Wait for thread @i@ to finish working and go back to sleep.+foreign import ccall "flint/thread_pool.h thread_pool_wait"+ thread_pool_wait :: Ptr CThreadPool -> Ptr CThreadPoolHandle -> IO ()++-- | /thread_pool_give_back/ /T/ /i/ +-- +-- Put thread @i@ back in the available state. This thread should be+-- sleeping when this function is called.+foreign import ccall "flint/thread_pool.h thread_pool_give_back"+ thread_pool_give_back :: Ptr CThreadPool -> Ptr CThreadPoolHandle -> IO ()++-- | /thread_pool_clear/ /T/ +-- +-- Release any resources used by @T@. All threads should be given back+-- before this function is called.+foreign import ccall "flint/thread_pool.h thread_pool_clear"+ thread_pool_clear :: Ptr CThreadPool -> IO ()++foreign import ccall "flint/thread_pool.h &thread_pool_clear"+ p_thread_pool_clear :: FunPtr (Ptr CThreadPool -> IO ())+
+ src/Data/Number/Flint/UFD.hs view
@@ -0,0 +1,24 @@+{-|+module : Data.Number.Flint.UFD+copyright : (c) 2022 Hartmut Monien+license : GNU GPL, version 2 or above (see LICENSE)+maintainer : hmonien@uni-bonn.de++= Unique factorization domain++Specifically, a UFD is an integral domain (a nontrivial commutative ring in which the product of any two non-zero elements is non-zero) in which every non-zero non-unit element can be written as a product of prime elements (or irreducible elements), uniquely up to order and units.+-}+module Data.Number.Flint.UFD where++class (Num a) => UFD a where+ -- | factor /x/ + --+ -- Factor /x/ into `prime` factors \(x = p_1^{e_1}\ldots p_n^{e_n}\) + -- with the representation \([(p_1, e_1) \ldots (p_n, e_n)]\)+ --+ factor :: a -> [(a, Int)]+ -- | unfactor /f/+ --+ -- Find /x/ which has the unique factorization /f/.+ unfactor :: [(a, Int)] -> a+ unfactor x = product $ map (uncurry (^)) x
+ test/Spec.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"