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 <https://www.gnu.org/licenses/>.
10 */
11
12 #include <iostream>
13 #include <sstream>
14 #include <string>
15
16 #include "padicxx.h"
17 #include "flintxx/test/helpers.h"
18
19 using namespace flint;
20
21 void
test_init()22 test_init()
23 {
24 padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE);
25 tassert(ctx.get_p() == 5);
26
27 padicxx a(ctx, 20);
28 tassert(a.prec() == 20);
29
30 padicxx c(a);
31 tassert(a == c);
32
33 padicxx b(ctx, 30);
34 tassert((a + b).prec() == 30);
35
36 tassert((a + b).create_temporary().prec() == 30);
37 padicxx d((a + b).create_temporary());
38 tassert(d.prec() == 30);
39
40 padicxx e(a + b);
41 tassert(e.prec() == 30);
42
43 tassert(padicxx::zero(ctx).is_zero() && padicxx::zero(ctx, 25).is_zero());
44 tassert(padicxx::one(ctx).is_one() && padicxx::one(ctx, 25).is_one());
45
46 a.prec() = 25;
47 tassert(a.prec() == 25);
48 a.val() = 17;
49 tassert(a.val() == 17);
50
51 padicxx zero = padicxx::zero(ctx);
52 tassert(zero.unit() == 0);
53 tassert((zero + zero).unit() == 0);
54 tassert((zero + zero).val() == 0);
55 }
56
57 void
test_assignment()58 test_assignment()
59 {
60 padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE);
61 padicxx a(ctx, 20), b(ctx, 20);
62 fmpzxx c(17); fmpqxx d(17, 1u);
63
64 a = 17; tassert(a != b);
65 b = 17; tassert(a == b);
66 b = 0; tassert(a != b);
67 b = UWORD(17); tassert(a == b);
68 b = 0; b = c; tassert(a == b);
69 b = 0; b = fmpzxx_ref(c); tassert(a == b);
70 b = 0; b = fmpzxx_srcref(c); tassert(a == b);
71 b = 0; b = d; tassert(a == b);
72 }
73
74 void
test_conversion()75 test_conversion()
76 {
77 padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE);
78 padicxx_ctx ctx2(fmpzxx(5), 10, 20, PADIC_VAL_UNIT);
79
80 padicxx a(ctx), b(ctx2);
81 a = 15; b = 15;
82 tassert(a.to_string() == "15");
83 tassert(b.to_string() == "3*5");
84
85 tassert(a.to<fmpzxx>() == 15);
86 tassert(a.to<fmpqxx>() == fmpqxx(15, 1u));
87
88 std::ostringstream oss;
89 oss << a << ' ' << b;
90 tassert(oss.str() == "15 3*5");
91 }
92
93 template<class T>
make_padic(const T & t,slong prec=PADIC_DEFAULT_PREC)94 padicxx make_padic(const T& t, slong prec = PADIC_DEFAULT_PREC)
95 {
96 static padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE);
97 return padicxx::from_QQ(t, ctx, prec);
98 }
99 template<class T, class U>
fuzzy_equals(const T & t,const U & u)100 bool fuzzy_equals(const T& t, const U& u)
101 {
102 slong prec = std::min(t.prec(), u.prec()) - 5;
103 padicxx a(t.estimate_ctx(), prec); a = t;
104 padicxx b(t.estimate_ctx(), prec); b = u;
105 return a == b;
106 }
107 void
test_arithmetic()108 test_arithmetic()
109 {
110 fmpqxx af(17, 25u), bf(5, 27u);
111 padicxx a(make_padic(af));
112 padicxx b(make_padic(bf));
113
114 tassert(fuzzy_equals(a + b, make_padic(af + bf)));
115 tassert(fuzzy_equals(a * b, make_padic(af * bf)));
116 tassert(fuzzy_equals(a / b, make_padic(af / bf)));
117 tassert(fuzzy_equals(a - b, make_padic(af - bf)));
118 tassert(fuzzy_equals(a << 2, make_padic(af * fmpzxx(25))));
119 tassert(fuzzy_equals(a >> 2, make_padic(af / fmpzxx(25))));
120 tassert(-a == make_padic(-af));
121 }
122
123 void
test_functions()124 test_functions()
125 {
126 padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE);
127
128 padicxx a(make_padic(fmpqxx(14, 25u)));
129 tassert(fuzzy_equals(a, pow(sqrt(a), 2)));
130
131 assert_exception(sqrt(make_padic(fmpqxx(2, 1u))).evaluate());
132
133 fmpqxx cf(14*5, 1u);
134 padicxx c = make_padic(fmpqxx(14*5, 1u));
135 tassert(fuzzy_equals(log(exp(c)), c));
136 tassert(exp(c) == exp_rectangular(c) && exp(c) == exp_balanced(c));
137 c = exp(c);
138 tassert(log(c) == log_satoh(c) && log(c) == log_balanced(c)
139 && log(c) == log_rectangular(c));
140
141 padicxx b(make_padic(fmpqxx(14, 17u)));
142 tassert((inv(b)*b).is_one());
143
144 padicxx two(make_padic(fmpqxx(2, 1u)));
145 padicxx tl(teichmuller(two));
146 tassert(pow(tl, 4).is_one() && (tl - two).val() > 0);
147
148 // TODO test reduce
149
150 // test padic_val_fac functions
151 tassert(padic_val_fac(fmpzxx(26), fmpzxx(5)) == 6);
152 tassert(padic_val_fac(26u, fmpzxx(5)) == 6);
153
154 // test randomisation
155 frandxx rand;
156 tassert(padicxx::randtest(rand, ctx, 5).val() < 5
157 && padicxx::randtest(rand, ctx, 5).val() >= -1);
158 tassert(padicxx::randtest(rand, ctx, -5).val() < -5
159 && padicxx::randtest(rand, ctx, -5).val() >= -6);
160 tassert(!padicxx::randtest_not_zero(rand, ctx, 5).is_zero());
161 tassert(padicxx::randtest_int(rand, ctx, -5).is_zero());
162
163 padicxx ap(a), bp(b);
164 swap(a, b);
165 tassert(a == bp && b == ap);
166
167 // test members (just a sample, since from macros)
168 tassert(b.inv() == inv(b));
169 tassert(b.pow(7) == pow(b, 7));
170 }
171
172 // test stuff which we should get automatically - references etc
173 void
test_extras()174 test_extras()
175 {
176 padicxx a(make_padic(fmpqxx(3, 5u)));
177 padicxx b(make_padic(fmpqxx(3, 1u)));
178
179 padicxx_ref ar(a);
180 padicxx_srcref asr(a);
181 tassert(a == ar && ar == asr);
182 ar = 3;
183 tassert(a == b && asr == b);
184
185 tassert(ar + asr == a + a);
186 tassert(padicxx(ar) == ar);
187 tassert(padicxx(asr) == ar);
188 }
189
190 void
test_prec()191 test_prec()
192 {
193 padicxx_ctx ctx(fmpzxx(5), 10, 20, PADIC_TERSE);
194 padicxx a(ctx, 5), b(ctx, 7);
195 padicxx_ref ar(a);
196 padicxx_srcref br(b);
197
198 tassert((a + a).prec() == 5);
199 tassert((a + ar).prec() == 5);
200 tassert((a + b).prec() == 7);
201 tassert((a + br).prec() == 7);
202 tassert((a.toN(15) + br.toN(10)).prec() == 15);
203 }
204
205 void
test_printing()206 test_printing()
207 {
208 tassert_fprint(make_padic(0), "0");
209 }
210
211 int
main()212 main()
213 {
214 std::cout << "padicxx....";
215
216 test_init();
217 test_assignment();
218 test_conversion();
219 test_arithmetic();
220 test_functions();
221 test_extras();
222 test_prec();
223 test_printing();
224
225 std::cout << "PASS" << std::endl;
226 return 0;
227 }
228