3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-28 11:25:51 +00:00

separate into self-contained mod interval

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2021-05-11 11:22:55 -07:00
parent 04c0db75bf
commit 62b7719d5a
8 changed files with 193 additions and 150 deletions

View file

@ -0,0 +1,67 @@
/*++
Copyright (c) 2014 Microsoft Corporation
Module Name:
mod_interval.h
Abstract:
Intervals over fixed precision modular arithmetic
Author:
Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
--*/
#pragma once
template<typename Numeral>
struct pp {
Numeral n;
pp(Numeral const& n):n(n) {}
};
template<typename Numeral>
inline std::ostream& operator<<(std::ostream& out, pp<Numeral> const& p) {
if ((0 - p.n) < p.n)
return out << "-" << (0 - p.n);
return out << p.n;
}
template<typename Numeral>
struct mod_interval {
bool emp { false };
Numeral lo { 0 };
Numeral hi { 0 };
mod_interval() {}
mod_interval(Numeral const& l, Numeral const& h): lo(l), hi(h) {}
static mod_interval free() { return mod_interval(0, 0); }
static mod_interval empty() { mod_interval i(0, 0); i.emp = true; return i; }
bool is_free() const { return !emp && lo == hi; }
bool is_empty() const { return emp; }
bool contains(Numeral const& n) const;
mod_interval operator&(mod_interval const& other) const;
mod_interval operator+(mod_interval const& other) const;
mod_interval operator-(mod_interval const& other) const;
mod_interval operator*(mod_interval const& other) const;
mod_interval operator-() const;
mod_interval operator*(Numeral const& n) const;
mod_interval operator+(Numeral const& n) const { return mod_interval(lo + n, hi + n); }
mod_interval operator-(Numeral const& n) const { return mod_interval(lo - n, hi - n); }
mod_interval& operator+=(mod_interval const& other) { *this = *this + other; return *this; }
std::ostream& display(std::ostream& out) const {
if (is_empty()) return out << "empty";
if (is_free()) return out << "free";
return out << "[" << pp(lo) << ", " << pp(hi) << "[";
}
};
template<typename Numeral>
inline std::ostream& operator<<(std::ostream& out, mod_interval<Numeral> const& i) {
return i.display(out);
}

View file

@ -0,0 +1,111 @@
/*++
Copyright (c) 2014 Microsoft Corporation
Module Name:
mod_interval_def.h
Abstract:
Intervals over fixed precision modular arithmetic
Author:
Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
--*/
#pragma once
#include "math/interval/mod_interval.h"
template<typename Numeral>
bool mod_interval<Numeral>::contains(Numeral const& n) const {
if (is_empty())
return false;
if (is_free())
return true;
if (lo < hi)
return lo <= n && n < hi;
else
return lo <= n || n < hi;
}
template<typename Numeral>
mod_interval<Numeral> mod_interval<Numeral>::operator+(mod_interval<Numeral> const& other) const {
if (is_empty())
return *this;
if (other.is_empty())
return other;
if (is_free())
return *this;
if (other.is_free())
return other;
Numeral sz = (hi - lo) + (other.hi - other.lo);
if (sz < (hi - lo))
return mod_interval::free();
return mod_interval(lo + other.lo, hi + other.hi);
}
template<typename Numeral>
mod_interval<Numeral> mod_interval<Numeral>::operator-(mod_interval<Numeral> const& other) const {
return *this + (-other);
}
template<typename Numeral>
mod_interval<Numeral> mod_interval<Numeral>::operator-() const {
if (is_empty())
return *this;
if (is_free())
return *this;
return mod_interval(1 - hi, 1 - lo);
}
template<typename Numeral>
mod_interval<Numeral> mod_interval<Numeral>::operator*(Numeral const& n) const {
if (is_empty())
return *this;
if (n == 0)
return mod_interval(0, 1);
if (n == 1)
return *this;
if (is_free())
return *this;
Numeral sz = hi - lo;
if (0 - n < n) {
Numeral mn = 0 - n;
Numeral mz = mn * sz;
if (mz / mn != sz)
return mod_interval::free();
return mod_interval((hi - 1) * n, n * lo + 1);
}
else {
Numeral mz = n * sz;
if (mz / n != sz)
return mod_interval::free();
return mod_interval(n * lo, n * (hi - 1) + 1);
}
}
template<typename Numeral>
mod_interval<Numeral> mod_interval<Numeral>::operator&(mod_interval const& other) const {
Numeral l, h;
if (is_free() || other.is_empty())
return other;
if (other.is_free() || is_empty())
return *this;
if (contains(other.lo))
l = other.lo;
else if (other.contains(lo))
l = lo;
else
return mod_interval::empty();
if (contains(other.hi - 1))
h = other.hi;
else if (other.contains(hi - 1))
h = hi;
else
return mod_interval::empty();
return mod_interval(l, h);
}