Skip to content

Commit

Permalink
[[stash]]
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomaqa committed Nov 7, 2024
1 parent e8eb84b commit a986a8a
Show file tree
Hide file tree
Showing 38 changed files with 988 additions and 307 deletions.
1 change: 1 addition & 0 deletions .clang-files
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
./src/cnfizers/Tseitin.h

./src/common/numbers/Integer.h
./src/common/numbers/Number.cc
./src/common/numbers/Number.h
./src/common/numbers/Real.h
./src/common/ApiException.h
Expand Down
3 changes: 3 additions & 0 deletions src/common/numbers/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
target_sources(common
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/FastInteger.cc"
"${CMAKE_CURRENT_LIST_DIR}/FastRational.cc"
"${CMAKE_CURRENT_LIST_DIR}/Integer.h"
"${CMAKE_CURRENT_LIST_DIR}/Number.cc"
"${CMAKE_CURRENT_LIST_DIR}/Number.h"
"${CMAKE_CURRENT_LIST_DIR}/Real.h"
PRIVATE
Expand All @@ -11,6 +13,7 @@ PRIVATE
install(FILES
${CMAKE_CURRENT_LIST_DIR}/Integer.h
${CMAKE_CURRENT_LIST_DIR}/Number.h
${CMAKE_CURRENT_LIST_DIR}/FastInteger.h
${CMAKE_CURRENT_LIST_DIR}/FastRational.h
${CMAKE_CURRENT_LIST_DIR}/Real.h
${CMAKE_CURRENT_LIST_DIR}/NumberUtils.h
Expand Down
88 changes: 88 additions & 0 deletions src/common/numbers/FastInteger.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include "FastInteger.h"

namespace opensmt {
FastInteger::FastInteger(const char* str, const int base) : FastRational(str, base) {
assert(isIntegerValue());
}

FastInteger gcd(FastInteger const & a, FastInteger const & b)
{
assert(a.isIntegerValue() and b.isIntegerValue());
if (a.wordPartValid() && b.wordPartValid()) {
// Refers to FastRational.h:gcd
return FastInteger(gcd(a.num, b.num));
}
else {
a.ensure_mpq_valid();
b.ensure_mpq_valid();
mpz_gcd(FastInteger::mpz(), mpq_numref(a.mpq), mpq_numref(b.mpq));
return FastInteger(FastInteger::mpz());
}
}

FastInteger lcm(FastInteger const & a, FastInteger const & b)
{
assert(a.isIntegerValue() and b.isIntegerValue());
if (a.wordPartValid() && b.wordPartValid()) {
// Refers to FastRational.h:lcm
return lcm(a.num, b.num);
}
else {
a.ensure_mpq_valid();
b.ensure_mpq_valid();
mpz_lcm(FastInteger::mpz(), mpq_numref(a.mpq), mpq_numref(b.mpq));
return FastInteger(FastInteger::mpz());
}
}

// The quotient of n and d using the fast rationals.
// Divide n by d, forming a quotient q.
// Rounds q down towards -infinity, and q will satisfy n = q*d + r for some 0 <= abs(r) <= abs(d)
FastInteger fastint_fdiv_q(FastInteger const & n, FastInteger const & d) {
assert(n.isIntegerValue() && d.isIntegerValue());
if (n.wordPartValid() && d.wordPartValid()) {
word num = n.num;
word den = d.num;
word quo;
if (num == INT_MIN) // The abs is guaranteed to overflow. Otherwise this is always fine
goto overflow;
// After this -INT_MIN+1 <= numerator <= INT_MAX, and therefore the result always fits into a word.
quo = num / den;
if (num % den != 0 && ((num < 0 && den >=0) || (den < 0 && num >= 0))) // The result should be negative
quo--; // INT_MAX-1 >= quo >= -INT_MIN

return quo;
}
overflow:
n.ensure_mpq_valid();
d.ensure_mpq_valid();
mpz_fdiv_q(FastInteger::mpz(), mpq_numref(n.mpq), mpq_numref(d.mpq));
return FastInteger(FastInteger::mpz());
}

//void mpz_divexact (mpz_ptr, mpz_srcptr, mpz_srcptr);
FastInteger divexact(FastInteger const & n, FastInteger const & d) {
assert(d != 0);
assert(n.isIntegerValue() && d.isIntegerValue());
if (n.wordPartValid() && d.wordPartValid()) {
word num = n.num;
word den = d.num;
word quo;
if (den != 0){
quo = num / den;
return quo;
}
else {
// Division by zero
assert(false);
return FastInteger(0);
}
} else {
assert(n.mpqPartValid() || d.mpqPartValid());
n.ensure_mpq_valid();
d.ensure_mpq_valid();
mpz_divexact(FastInteger::mpz(), mpq_numref(n.mpq), mpq_numref(d.mpq));
return FastInteger(FastInteger::mpz());
}
}
}
116 changes: 116 additions & 0 deletions src/common/numbers/FastInteger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//
// Created by Tomas Kolarik in 08/2024.
//

#ifndef OPENSMT_FAST_INTEGER_H
#define OPENSMT_FAST_INTEGER_H

#include "FastRational.h"

#include <concepts>

namespace opensmt {
// TODO: inefficient, rational representation & uses mpq instead of mpz
class FastInteger : public FastRational {
public:
using FastRational::FastRational;
explicit FastInteger(FastRational rat) : FastRational(std::move(rat)) { assert(isIntegerValue()); }
explicit FastInteger(char const *, int const base = 10);
FastInteger & operator=(FastRational const & other) {
assert(this != &other);
assert(other.isIntegerValue());
FastRational::operator=(other);
return *this;
}
FastInteger & operator=(FastRational && other) {
assert(other.isIntegerValue());
FastRational::operator=(std::move(other));
return *this;
}
FastInteger & operator=(std::integral auto i) { return operator=(FastInteger(i)); }

FastInteger ceil() const noexcept { return *this; }
FastInteger floor() const noexcept { return *this; }

FastInteger operator-() const { return static_cast<FastInteger &&>(FastRational::operator-()); }
FastInteger operator+(FastInteger const & b) const {
return static_cast<FastInteger &&>(FastRational::operator+(b));
}
FastInteger operator-(FastInteger const & b) const {
return static_cast<FastInteger &&>(FastRational::operator-(b));
}
FastInteger operator*(FastInteger const & b) const {
return static_cast<FastInteger &&>(FastRational::operator*(b));
}
FastInteger & operator+=(FastInteger const & b) {
FastRational::operator+=(b);
return *this;
}
FastInteger & operator-=(FastInteger const & b) {
FastRational::operator-=(b);
return *this;
}
FastInteger & operator*=(FastInteger const & b) {
FastRational::operator*=(b);
return *this;
}
FastInteger & operator+=(std::integral auto i) { return operator+=(FastInteger(i)); }
FastInteger & operator-=(std::integral auto i) { return operator-=(FastInteger(i)); }
FastInteger & operator*=(std::integral auto i) { return operator*=(FastInteger(i)); }
FastRational & operator+=(FastRational const &) = delete;
FastRational & operator-=(FastRational const &) = delete;
FastRational & operator*=(FastRational const &) = delete;

FastRational operator/(FastInteger const & b) const { return FastRational::operator/(b); }
void operator/=(FastInteger const &) = delete;
FastRational & operator/=(FastRational const &) = delete;

// The return value will have the sign of d
FastInteger operator%(FastInteger const & d) const {
assert(isIntegerValue() && d.isIntegerValue());
if (wordPartValid() && d.wordPartValid()) {
uword w = absVal(num % d.num); // Largest value is absVal(INT_MAX % INT_MIN) = INT_MAX
return (word)(d.num > 0 ? w : -w); // No overflow since 0 <= w <= INT_MAX
}
FastRational r = operator/(d);
auto i = FastInteger(r.floor());
return operator-(i * d);
}
FastInteger & operator%=(FastInteger const & d) {
//+ it would be more efficient the other way around
return operator=(operator%(d));
}

private:
FastInteger(std::integral auto, std::integral auto) = delete;

using FastRational::get_d;
using FastRational::get_den;
using FastRational::get_num;
//- using FastRational::tryGetNumDen;

friend FastInteger gcd(FastInteger const &, FastInteger const &);
friend FastInteger lcm(FastInteger const &, FastInteger const &);
friend FastInteger fastint_fdiv_q(FastInteger const &, FastInteger const &);
friend FastInteger divexact(FastInteger const &, FastInteger const &);
};

static_assert(!std::integral<FastInteger>);

// The result could not fit into integer -> FastInteger
template<std::integral integer>
FastInteger lcm(integer a, integer b) {
if (a == 0) return 0;
if (b == 0) return 0;
FastRational rat = (b > a) ? FastRational(b / gcd(a, b)) * a : FastRational(a / gcd(a, b)) * b;
assert(rat.isIntegerValue());
return static_cast<FastInteger&&>(rat);
}

FastInteger gcd(FastInteger const &, FastInteger const &);
FastInteger lcm(FastInteger const &, FastInteger const &);
FastInteger fastint_fdiv_q(FastInteger const & n, FastInteger const & d);
FastInteger divexact(FastInteger const & n, FastInteger const & d);
} // namespace opensmt

#endif // OPENSMT_FAST_INTEGER_H
92 changes: 7 additions & 85 deletions src/common/numbers/FastRational.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Copyright (c) 2008, 2009 Centre national de la recherche scientifique (CNRS)
*/

#include "FastRational.h"
#include "FastInteger.h"

#include <sstream>
#include <algorithm>
Expand Down Expand Up @@ -105,103 +106,24 @@ void FastRational::print_(std::ostream & out) const
}
}

std::string FastRational::get_str() const
std::string FastRational::toString() const
{
std::ostringstream os;
print_(os);
return os.str();
}

FastRational gcd(FastRational const & a, FastRational const & b)
{
assert(a.isInteger() and b.isInteger());
if (a.wordPartValid() && b.wordPartValid()) {
return FastRational(gcd(a.num, b.num));
}
else {
a.ensure_mpq_valid();
b.ensure_mpq_valid();
mpz_gcd(FastRational::mpz(), mpq_numref(a.mpq), mpq_numref(b.mpq));
return FastRational(FastRational::mpz());
}
}

FastRational lcm(FastRational const & a, FastRational const & b)
{
assert(a.isInteger() and b.isInteger());
if (a.wordPartValid() && b.wordPartValid()) {
return lcm(a.num, b.num);
}
else {
a.ensure_mpq_valid();
b.ensure_mpq_valid();
mpz_lcm(FastRational::mpz(), mpq_numref(a.mpq), mpq_numref(b.mpq));
return FastRational(FastRational::mpz());
}
}

FastRational fastrat_round_to_int(const FastRational& n) {
FastRational res = n + FastRational(1, 2);
return fastrat_fdiv_q(res.get_num(), res.get_den());
}

// The quotient of n and d using the fast rationals.
// Divide n by d, forming a quotient q.
// Rounds q down towards -infinity, and q will satisfy n = q*d + r for some 0 <= abs(r) <= abs(d)
FastRational fastrat_fdiv_q(FastRational const & n, FastRational const & d) {
assert(n.isInteger() && d.isInteger());
if (n.wordPartValid() && d.wordPartValid()) {
word num = n.num;
word den = d.num;
word quo;
if (num == INT_MIN) // The abs is guaranteed to overflow. Otherwise this is always fine
goto overflow;
// After this -INT_MIN+1 <= numerator <= INT_MAX, and therefore the result always fits into a word.
quo = num / den;
if (num % den != 0 && ((num < 0 && den >=0) || (den < 0 && num >= 0))) // The result should be negative
quo--; // INT_MAX-1 >= quo >= -INT_MIN

return quo;
}
overflow:
n.ensure_mpq_valid();
d.ensure_mpq_valid();
mpz_fdiv_q(FastRational::mpz(), mpq_numref(n.mpq), mpq_numref(d.mpq));
return FastRational(FastRational::mpz());
}

//void mpz_divexact (mpz_ptr, mpz_srcptr, mpz_srcptr);
FastRational divexact(FastRational const & n, FastRational const & d) {
assert(d != 0);
assert(n.isInteger() && d.isInteger());
if (n.wordPartValid() && d.wordPartValid()) {
word num = n.num;
word den = d.num;
word quo;
if (den != 0){
quo = num / den;
return quo;
}
else {
// Division by zero
assert(false);
return FastRational(0);
}
} else {
assert(n.mpqPartValid() || d.mpqPartValid());
n.ensure_mpq_valid();
d.ensure_mpq_valid();
mpz_divexact(FastRational::mpz(), mpq_numref(n.mpq), mpq_numref(d.mpq));
return FastRational(FastRational::mpz());
}
return fastint_fdiv_q(static_cast<FastInteger&&>(res.get_num()), static_cast<FastInteger&&>(res.get_den()));
}

// Given as input the sequence Reals, return the smallest number m such that for each r in Reals, r*m is an integer
FastRational get_multiplicand(const std::vector<FastRational>& reals)
{
std::vector<FastRational> dens;
for (const auto & r : reals) {
if (!r.isInteger()) {
if (!r.isIntegerValue()) {
dens.push_back(r.get_den());
}
}
Expand All @@ -219,7 +141,7 @@ FastRational get_multiplicand(const std::vector<FastRational>& reals)
char *buf_new;

for (int j = 0; j < dens.size(); j++) {
asprintf(&buf_new, "%s%s%s", buf, dens[j].get_str().c_str(),
asprintf(&buf_new, "%s%s%s", buf, dens[j].toString().c_str(),
j == dens.size() - 1 ? "" : ", ");
free(buf);
buf = buf_new;
Expand All @@ -234,7 +156,7 @@ FastRational get_multiplicand(const std::vector<FastRational>& reals)
else {
// We filter in place the integers in dens. The last two are guaranteed to be ;
int k = 0;
FastRational m = lcm(dens[dens.size()-1], dens[dens.size()-2]);
FastRational m = lcm(static_cast<FastInteger&>(dens[dens.size()-1]), static_cast<FastInteger&>(dens[dens.size()-2]));
mult *= m;
for (size_t j = 0; j < dens.size()-2; j++) {
FastRational n = (m/dens[j]).get_den();
Expand All @@ -245,7 +167,7 @@ FastRational get_multiplicand(const std::vector<FastRational>& reals)
}
}
#ifdef PRINTALOT
printf("Multiplicand is %s\n", mult.get_str().c_str());
printf("Multiplicand is %s\n", mult.toString().c_str());
#endif
return mult;
}
Expand Down
Loading

0 comments on commit a986a8a

Please sign in to comment.