diff --git a/include/data/encoding/halves.hpp b/include/data/encoding/halves.hpp index 2facdffb..86411bea 100644 --- a/include/data/encoding/halves.hpp +++ b/include/data/encoding/halves.hpp @@ -173,17 +173,22 @@ namespace data::encoding { }; template - typename twice::type combine(half greater, half lesser) { + typename twice::type inline combine(half greater, half lesser) { return ((typename twice::type)(greater) << count_digits::value * 8) + lesser; }; template - typename twice::type multiply(half a, half b, half r) { + typename twice::type inline multiply(half a, half b, half r) { return (typename twice::type)(a) * (typename twice::type)(b) + (typename twice::type)(r); }; template - typename twice::type add(half a, half b, half r) { + typename twice::type inline subtract(half a, half b, half r) { + return (typename twice::type)(a) - b + r; + }; + + template + typename twice::type inline add(half a, half b, half r) { return (typename twice::type)(a) + b + r; }; diff --git a/include/data/encoding/words.hpp b/include/data/encoding/words.hpp index 18ab220f..c0986f0b 100644 --- a/include/data/encoding/words.hpp +++ b/include/data/encoding/words.hpp @@ -163,13 +163,51 @@ namespace data::arithmetic { template requires std::input_iterator && std::output_iterator && std::sentinel_for digit minus(sen z, ita a, itb b, itb i) { - throw method::unimplemented{"arithmetic::minus"}; + using two_digits = typename encoding::twice::type; + + digit remainder = 0; + + while (i != z) { + two_digits result = encoding::subtract(*a, *b, remainder); + remainder = encoding::greater_half(result); + *i = encoding::lesser_half(result); + i++; + a++; + b++; + } + + return remainder; } template requires std::input_iterator && std::output_iterator && std::sentinel_for digit times(sen z, ita a, itb b, itb i) { - throw method::unimplemented{"arithmetic::minus"}; + using two_digits = typename encoding::twice::type; + + digit remainder = 0; + auto ab = a; + while (i != z) { + auto ax = ab; + auto bx = b; + + two_digits result = remainder; + + while (true) { + result += two_digits(*ax) * two_digits(*bx); + + if (ax == a) break; + ax++; + bx--; + } + + remainder = encoding::greater_half(result); + *i = encoding::lesser_half(result); + i++; + a++; + b++; + } + + return remainder; } // bit shift operations are defined in terms of big-endian numbers. diff --git a/include/data/tools/rb_map.hpp b/include/data/tools/rb_map.hpp index 379c2219..39030f1a 100644 --- a/include/data/tools/rb_map.hpp +++ b/include/data/tools/rb_map.hpp @@ -41,7 +41,16 @@ namespace data::tool { rb_map remove(const K& k) const; rb_map remove(const entry& e) const; - bool valid() const; + bool valid() const { + try { + milewski::okasaki::forEach(Map, [](const K &k, const V &v) -> void { + if (!data::valid(k) || !data::valid(v)) throw 0; + }); + } catch (int) { + return false; + } + return true; + } bool empty() const; size_t size() const;