/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef FMPZ_FACTORXX_H #define FMPZ_FACTORXX_H #include "fmpz_factor.h" #include "fmpz_vec.h" #include "flintxx/ltuple.h" // TODO codegen // TODO factor_pp1 multiple return values namespace flint { FLINT_DEFINE_THREEARY(factor_trial_range) FLINT_DEFINE_UNOP(expand) FLINT_DEFINE_UNOP(expand_iterative) FLINT_DEFINE_UNOP(expand_multiexp) namespace detail { template class fmpz_factorxx_delayed { private: fmpz_factor_t inner; void copy_init(const fmpz_factorxx_delayed& o) { _fmpz_factor_fit_length(inner, o.inner->num); _fmpz_factor_set_length(inner, o.inner->num); inner->sign = o.inner->sign; for(slong i = 0;i < o.inner->num;++i) { fmpz_set(inner->p + i, o.inner->p + i); inner->exp[i] = o.inner->exp[i]; } } public: fmpz_factorxx_delayed() {fmpz_factor_init(inner);} ~fmpz_factorxx_delayed() {fmpz_factor_clear(inner);} fmpz_factorxx_delayed(const fmpz_factorxx_delayed& o) { fmpz_factor_init(inner); copy_init(o); } fmpz_factorxx_delayed& operator=(const fmpz_factorxx_delayed& o) { copy_init(o); return *this; } bool operator==(const fmpz_factorxx_delayed& o) { if(o.sign() != sign() || o.size() != size()) return false; for(ulong i = 0;i < size();++i) if(p(i) != o.p(i) || exp(i) != o.exp(i)) return false; return true; } ulong size() const {return inner->num;} ulong exp(slong i) const {return inner->exp[i];} ulong& exp(slong i) {return inner->exp[i];} fmpzxx_srcref p(slong i) const {return fmpzxx_srcref::make(inner->p + i);} fmpzxx_ref p(slong i) {return fmpzxx_ref::make(inner->p + i);} int sign() const {return inner->sign;} int& sign() {return inner->sign;} fmpz_factor_t& _data() {return inner;} const fmpz_factor_t& _data() const {return inner;} void print() const {fmpz_factor_print(inner);} template typename mp::enable_if >::type set_factor(const Fmpz& f) { fmpz_factor(_data(), f.evaluate()._fmpz()); } template typename mp::enable_if >::type set_factor(T t) { fmpz_factor_si(_data(), t); } template typename mp::enable_if, bool>::type set_factor_trial_range(const Fmpz& f, ulong start, ulong nprimes) { return fmpz_factor_trial_range(_data(), f.evaluate()._fmpz(), start, nprimes); } template typename mp::enable_if, bool>::type set_factor_pp1(const Fmpz& f, ulong B1, ulong B2_sqrt, ulong c) { return fmpz_factor_pp1(_data(), f.evaluate()._fmpz(), B1, B2_sqrt, c); } #define FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(funcname, Class, rtype) \ FLINT_UNOP_BUILD_RETTYPE(funcname, rtype, Class) \ funcname() const {return flint::funcname(*this);} FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(expand, fmpz_factorxx_delayed, fmpzxx) FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(expand_iterative, fmpz_factorxx_delayed, fmpzxx) FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(expand_multiexp, fmpz_factorxx_delayed, fmpzxx) }; } // detail typedef detail::fmpz_factorxx_delayed fmpz_factorxx; template inline typename mp::enable_if, traits::fits_into_slong >, fmpz_factorxx>::type factor(const Fmpz& f) { fmpz_factorxx res; res.set_factor(f); return res; } namespace rules { namespace rdetail { typedef make_ltuple::type>::type fmpz_factor_rt; template struct signed_or_fmpz : mp::or_, traits::fits_into_slong > { }; } // rdetail FLINT_DEFINE_THREEARY_EXPR_COND3(factor_trial_range_op, rdetail::fmpz_factor_rt, rdetail::signed_or_fmpz, traits::is_unsigned_integer, traits::is_unsigned_integer, to.template get<0>() = to.template get<1>().set_factor_trial_range( e1, e2, e3)) FLINT_DEFINE_UNARY_EXPR_(expand_op, fmpzxx, fmpz_factorxx, fmpz_factor_expand(to._fmpz(), from._data())) FLINT_DEFINE_UNARY_EXPR_(expand_iterative_op, fmpzxx, fmpz_factorxx, fmpz_factor_expand_iterative(to._fmpz(), from._data())) FLINT_DEFINE_UNARY_EXPR_(expand_multiexp_op, fmpzxx, fmpz_factorxx, fmpz_factor_expand_multiexp(to._fmpz(), from._data())) } // rules template inline typename mp::enable_if, fmpz_factorxx>::type factor_pp1(const Fmpz& f, ulong B1, ulong B2_sqrt, ulong c) { fmpz_factorxx res; res.set_factor_pp1(f, B1, B2_sqrt, c); return res; } inline void print(const fmpz_factorxx& f) { f.print(); } } // flint #endif