1 /*
2 Copyright (C) 2013 Tom Bachmann
3
4 This file is part of FLINT.
5
6 FLINT is free software: you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version. See <http://www.gnu.org/licenses/>.
10 */
11
12 #ifndef FMPZ_FACTORXX_H
13 #define FMPZ_FACTORXX_H
14
15 #include "fmpz_factor.h"
16 #include "fmpz_vec.h"
17
18 #include "flintxx/ltuple.h"
19
20 // TODO codegen
21 // TODO factor_pp1 multiple return values
22
23 namespace flint {
24 FLINT_DEFINE_THREEARY(factor_trial_range)
FLINT_DEFINE_UNOP(expand)25 FLINT_DEFINE_UNOP(expand)
26 FLINT_DEFINE_UNOP(expand_iterative)
27 FLINT_DEFINE_UNOP(expand_multiexp)
28
29 namespace detail {
30 template<class Delay>
31 class fmpz_factorxx_delayed
32 {
33 private:
34 fmpz_factor_t inner;
35
36 void copy_init(const fmpz_factorxx_delayed& o)
37 {
38 _fmpz_factor_fit_length(inner, o.inner->num);
39 _fmpz_factor_set_length(inner, o.inner->num);
40 inner->sign = o.inner->sign;
41 for(slong i = 0;i < o.inner->num;++i)
42 {
43 fmpz_set(inner->p + i, o.inner->p + i);
44 inner->exp[i] = o.inner->exp[i];
45 }
46 }
47
48 public:
49 fmpz_factorxx_delayed() {fmpz_factor_init(inner);}
50 ~fmpz_factorxx_delayed() {fmpz_factor_clear(inner);}
51
52 fmpz_factorxx_delayed(const fmpz_factorxx_delayed& o)
53 {
54 fmpz_factor_init(inner);
55 copy_init(o);
56 }
57
58 fmpz_factorxx_delayed& operator=(const fmpz_factorxx_delayed& o)
59 {
60 copy_init(o);
61 return *this;
62 }
63
64 bool operator==(const fmpz_factorxx_delayed& o)
65 {
66 if(o.sign() != sign() || o.size() != size())
67 return false;
68 for(ulong i = 0;i < size();++i)
69 if(p(i) != o.p(i) || exp(i) != o.exp(i))
70 return false;
71 return true;
72 }
73
74 ulong size() const {return inner->num;}
75 ulong exp(slong i) const {return inner->exp[i];}
76 ulong& exp(slong i) {return inner->exp[i];}
77 fmpzxx_srcref p(slong i) const {return fmpzxx_srcref::make(inner->p + i);}
78 fmpzxx_ref p(slong i) {return fmpzxx_ref::make(inner->p + i);}
79 int sign() const {return inner->sign;}
80 int& sign() {return inner->sign;}
81
82 fmpz_factor_t& _data() {return inner;}
83 const fmpz_factor_t& _data() const {return inner;}
84
85 void print() const {fmpz_factor_print(inner);}
86
87 template<class Fmpz>
88 typename mp::enable_if<traits::is_fmpzxx<Fmpz> >::type
89 set_factor(const Fmpz& f)
90 {
91 fmpz_factor(_data(), f.evaluate()._fmpz());
92 }
93
94 template<class T>
95 typename mp::enable_if<traits::fits_into_slong<T> >::type
96 set_factor(T t)
97 {
98 fmpz_factor_si(_data(), t);
99 }
100
101 template<class Fmpz>
102 typename mp::enable_if<traits::is_fmpzxx<Fmpz>, bool>::type
103 set_factor_trial_range(const Fmpz& f, ulong start, ulong nprimes)
104 {
105 return fmpz_factor_trial_range(_data(), f.evaluate()._fmpz(),
106 start, nprimes);
107 }
108
109 template<class Fmpz>
110 typename mp::enable_if<traits::is_fmpzxx<Fmpz>, bool>::type
111 set_factor_pp1(const Fmpz& f, ulong B1, ulong B2_sqrt, ulong c)
112 {
113 return fmpz_factor_pp1(_data(), f.evaluate()._fmpz(),
114 B1, B2_sqrt, c);
115 }
116
117 #define FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(funcname, Class, rtype) \
118 FLINT_UNOP_BUILD_RETTYPE(funcname, rtype, Class) \
119 funcname() const {return flint::funcname(*this);}
120
121 FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(expand, fmpz_factorxx_delayed, fmpzxx)
122 FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(expand_iterative, fmpz_factorxx_delayed, fmpzxx)
123 FLINTXX_DEFINE_MEMBER_UNOP_EXTRA(expand_multiexp, fmpz_factorxx_delayed, fmpzxx)
124 };
125 } // detail
126 typedef detail::fmpz_factorxx_delayed<void> fmpz_factorxx;
127
128 template<class Fmpz>
129 inline typename mp::enable_if<mp::or_<
130 traits::is_fmpzxx<Fmpz>, traits::fits_into_slong<Fmpz> >,
factor(const Fmpz & f)131 fmpz_factorxx>::type factor(const Fmpz& f)
132 {
133 fmpz_factorxx res;
134 res.set_factor(f);
135 return res;
136 }
137
138 namespace rules {
139 namespace rdetail {
140 typedef make_ltuple<mp::make_tuple<bool, fmpz_factorxx>::type>::type
141 fmpz_factor_rt;
142
143 template<class T> struct signed_or_fmpz
144 : mp::or_<FMPZXX_COND_S<T>, traits::fits_into_slong<T> > { };
145 } // rdetail
146 FLINT_DEFINE_THREEARY_EXPR_COND3(factor_trial_range_op, rdetail::fmpz_factor_rt,
147 rdetail::signed_or_fmpz,
148 traits::is_unsigned_integer, traits::is_unsigned_integer,
149 to.template get<0>() = to.template get<1>().set_factor_trial_range(
150 e1, e2, e3))
151
152 FLINT_DEFINE_UNARY_EXPR_(expand_op, fmpzxx, fmpz_factorxx,
153 fmpz_factor_expand(to._fmpz(), from._data()))
154 FLINT_DEFINE_UNARY_EXPR_(expand_iterative_op, fmpzxx, fmpz_factorxx,
155 fmpz_factor_expand_iterative(to._fmpz(), from._data()))
156 FLINT_DEFINE_UNARY_EXPR_(expand_multiexp_op, fmpzxx, fmpz_factorxx,
157 fmpz_factor_expand_multiexp(to._fmpz(), from._data()))
158 } // rules
159
160 template<class Fmpz>
161 inline typename mp::enable_if<traits::is_fmpzxx<Fmpz>, fmpz_factorxx>::type
factor_pp1(const Fmpz & f,ulong B1,ulong B2_sqrt,ulong c)162 factor_pp1(const Fmpz& f, ulong B1, ulong B2_sqrt, ulong c)
163 {
164 fmpz_factorxx res;
165 res.set_factor_pp1(f, B1, B2_sqrt, c);
166 return res;
167 }
168
print(const fmpz_factorxx & f)169 inline void print(const fmpz_factorxx& f)
170 {
171 f.print();
172 }
173 } // flint
174
175 #endif
176