249 lines
6.4 KiB
C++
249 lines
6.4 KiB
C++
/*=============================================================================
|
|
|
|
This file is part of FLINT.
|
|
|
|
FLINT is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
FLINT is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with FLINT; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
=============================================================================*/
|
|
/******************************************************************************
|
|
|
|
Copyright (C) 2013 Tom Bachmann
|
|
|
|
******************************************************************************/
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
#include "fmpqxx.h"
|
|
#include "fmpz_vecxx.h"
|
|
|
|
#include "flintxx/test/helpers.h"
|
|
|
|
using namespace flint;
|
|
|
|
void
|
|
test_init()
|
|
{
|
|
fmpqxx a, b = fmpqxx::frac(6, fmpzxx(10)),
|
|
c = fmpqxx::frac((unsigned short)6, 10u);
|
|
|
|
tassert(a.num() == 0 && a.den() == 1);
|
|
tassert(b.num() == 3 && b.den() == 5);
|
|
tassert(c.num() == 3 && c.den() == 5);
|
|
|
|
a.num() = -2;
|
|
a.den() = 4;
|
|
tassert(!a.is_canonical());
|
|
a.canonicalise();
|
|
tassert(a.num() == -1 && a.den() == 2);
|
|
|
|
tassert(fmpqxx::frac("4", 2) == fmpqxx::integer(-fmpzxx(-2)));
|
|
|
|
tassert(fmpqxx::zero().is_zero() && fmpqxx::one().is_one());
|
|
}
|
|
|
|
void
|
|
test_assignment()
|
|
{
|
|
fmpqxx a;
|
|
fmpqxx b = fmpqxx::frac("100000000000000000000", "100000000000000000001");
|
|
fmpqxx c(b);
|
|
a = b;
|
|
tassert(a == b && c == b);
|
|
tassert(a.num()._fmpz()[0] != b.num()._fmpz()[0]);
|
|
tassert(a.den()._fmpz()[0] != b.den()._fmpz()[0]);
|
|
tassert(c.num()._fmpz()[0] != b.num()._fmpz()[0]);
|
|
tassert(c.den()._fmpz()[0] != b.den()._fmpz()[0]);
|
|
|
|
a = 7;
|
|
tassert(a.num() == 7 && a.den() == 1);
|
|
a = (unsigned short)8;
|
|
tassert(a.num() == 8 && a.den() == 1);
|
|
}
|
|
|
|
void
|
|
test_conversion()
|
|
{
|
|
fmpqxx a = fmpqxx::frac(3, 5);
|
|
tassert(a.to_string() == "3/5");
|
|
tassert(a.to_string(5) == "3/10");
|
|
|
|
std::ostringstream oss;
|
|
oss << a;
|
|
tassert(oss.str() == "3/5");
|
|
|
|
tassert((a + a).num() == 6);
|
|
tassert((a * a).den() == 25);
|
|
}
|
|
|
|
void test_order()
|
|
{
|
|
fmpqxx a(0, 1u), b(1, 1u);
|
|
tassert(a < b);
|
|
tassert(a <= a);
|
|
tassert(b > a);
|
|
tassert(b >= b);
|
|
tassert(a == a);
|
|
tassert(a != b);
|
|
}
|
|
|
|
void
|
|
test_arithmetic()
|
|
{
|
|
fmpqxx a(3, 5u), b(2, 7u);
|
|
fmpzxx c(2);
|
|
|
|
tassert(a + b == fmpqxx::frac(3*7 + 2*5, 35u));
|
|
tassert(a * b == fmpqxx::frac(6, 35u));
|
|
tassert(a - b == fmpqxx::frac(3*7 - 5*2, 35u));
|
|
tassert(a / b == fmpqxx::frac(3*7, 10u));
|
|
|
|
tassert((a+a) * (c+c) == fmpqxx::frac(24, 5u));
|
|
tassert(c * a == fmpqxx::frac(6, 5u));
|
|
tassert(a / c == fmpqxx::frac(3, 10u));
|
|
|
|
tassert(-a == fmpqxx::frac(-3, 5u));
|
|
|
|
tassert(((a << 5) >> 4) == fmpzxx(2)*a);
|
|
}
|
|
|
|
// Won't compile if the expression is not done using addmul
|
|
template<class T>
|
|
bool is_ternary(const T&)
|
|
{
|
|
return T::ev_traits_t::temp_rule_t::TERNARY_OP_MARKER + 1;
|
|
}
|
|
|
|
// test stuff which we should get automatically - addmul, references etc
|
|
void
|
|
test_extras()
|
|
{
|
|
fmpqxx a(3, 5u), b(2, 7u), c(3, 1u);
|
|
tassert(is_ternary((a+a) - b*c));
|
|
tassert(is_ternary(b*c + (a+a)));
|
|
tassert((a+a) - b*c == fmpqxx::frac(6*7 - 5*6, 5u*7u));
|
|
tassert(b*c + (a+a) == fmpqxx::frac(6*7 + 5*6, 5u*7u));
|
|
|
|
fmpqxx_ref ar(a);
|
|
fmpqxx_srcref asr(a);
|
|
tassert(a == ar && ar == asr);
|
|
ar = 3;
|
|
tassert(a == c && asr == c);
|
|
|
|
tassert((-a) + a == fmpqxx::frac(0, 0u));
|
|
|
|
tassert(a.pow(3) == pow(a, 3));
|
|
tassert(a.height() == height(a));
|
|
}
|
|
|
|
void
|
|
test_functions()
|
|
{
|
|
fmpqxx a(-3, 5u);
|
|
|
|
// test lazy functions
|
|
tassert(abs(a) == -a);
|
|
tassert(height(a) == 5);
|
|
tassert(a % fmpzxx(7) == 5);
|
|
assert_exception((a % fmpzxx(5)).evaluate());
|
|
|
|
// test immediate functions
|
|
tassert(height_bits(a) == 3);
|
|
tassert((inv(a)*a).is_one());
|
|
tassert(sgn(a) == -1 && sgn(-a) == 1 && sgn(fmpqxx::frac(0, 0u)) == 0);
|
|
|
|
// test member functions
|
|
const fmpqxx zero(0, 0u), one(1, 1u);
|
|
tassert(zero.is_zero() && !zero.is_one());
|
|
tassert(!one.is_zero() && one.is_one());
|
|
tassert(pow(a, -3) == inv(a*a*a));
|
|
tassert(zero.next_minimal().next_minimal().next_minimal() == fmpqxx::frac(2, 1u));
|
|
tassert(zero.next_signed_minimal().next_signed_minimal() == fmpqxx::frac(-1, 1u));
|
|
tassert(zero.next_calkin_wilf().next_calkin_wilf() == fmpqxx::frac(1, 2u));
|
|
tassert(zero.next_signed_calkin_wilf().next_signed_calkin_wilf()
|
|
== fmpqxx::frac(-1, 1u));
|
|
|
|
// test static member functions
|
|
frandxx rand;
|
|
tassert(abs(fmpqxx::randbits(rand, 5).den()) <= 31);
|
|
// NB: rand stuff comes from a single macro, no need for further testing
|
|
tassert(a == fmpqxx::reconstruct(
|
|
a % fmpzxx(41), fmpzxx(41), fmpzxx(3), fmpzxx(5)));
|
|
assert_exception(fmpqxx::reconstruct(
|
|
a % fmpzxx(7), fmpzxx(7), fmpzxx(1), fmpzxx(1)).evaluate());
|
|
tassert(a == fmpqxx::reconstruct(a % fmpzxx(71), fmpzxx(71)));
|
|
assert_exception(fmpqxx::reconstruct(a % fmpzxx(7), fmpzxx(7)).evaluate());
|
|
|
|
// test partial fractions
|
|
fmpz_vecxx v(5);
|
|
fmpqxx tmp(7, 5u);
|
|
fmpqxx rem;
|
|
tassert(tmp == fmpqxx::from_cfrac(v, get_cfrac(v, rem, tmp)));
|
|
tassert(rem.is_zero());
|
|
tassert(3 <= tmp.cfrac_bound());
|
|
|
|
// test swap
|
|
a = 1;
|
|
fmpqxx b(zero);
|
|
swap(a, b);
|
|
tassert(a.is_zero() && b.is_one());
|
|
|
|
tassert_fprint(fmpqxx::frac(7, 29), "7/29");
|
|
}
|
|
|
|
void
|
|
test_vector()
|
|
{
|
|
fmpq_vecxx v1(10), v2(10), v3(1);
|
|
tassert(v1 == v2);
|
|
tassert(v1 != v3);
|
|
v1[0] = fmpqxx::frac(1, 1u);
|
|
tassert(v1 != v2);
|
|
v2[0] = v1[0];
|
|
tassert(v1 == v2);
|
|
}
|
|
|
|
void
|
|
test_unified_access()
|
|
{
|
|
fmpqxx a = fmpqxx::frac(1, 2);
|
|
const fmpqxx& b = a;
|
|
tassert(b.num() == 1);
|
|
const fmpqxx_ref c(a);
|
|
c.num() = 3;
|
|
tassert(c.num() == 3);
|
|
}
|
|
|
|
int
|
|
main()
|
|
{
|
|
std::cout << "fmpqxx....";
|
|
|
|
test_init();
|
|
test_assignment();
|
|
test_conversion();
|
|
test_order();
|
|
test_arithmetic();
|
|
test_functions();
|
|
test_extras();
|
|
test_vector();
|
|
test_unified_access();
|
|
|
|
std::cout << "PASS" << std::endl;
|
|
return 0;
|
|
}
|
|
|