saxbophone / arby

Arbitrary precision arithmetic in C++, even at compile-time
https://saxbophone.com/arby/
Mozilla Public License 2.0
8 stars 1 forks source link

compile-time pack() / unpack() methods for digits #63

Open saxbophone opened 2 years ago

saxbophone commented 2 years ago
Purpose:

Allow "packing" the dynamic digits of an arby::Uint or codlili::List generated at compile-time into a std::array that will persist the destruction of said Uint object.

This can then be used to "preserve" a Uint generated at compile-time into a std::array, then "resurrect" said object into a new run-time Uint for further use, circumventing the issue that memory "allocated" at compile-time can't be passed to runtime ;)

Something like the following:

// not sure whether needs to be static or not
static consteval auto pack(const Object& object); // where Object is either Uint or List, to be decided later
template <typename T, std::size_t SIZE> // NOTE: for Uint, we know that T is always StorageType
static Object unpack(std::array<const T, SIZE> compile_time_data); // to const or not to const? we don't need to modify it...

We'll need to use a helper method for the pack() method to derive the size of the std::array at compile-time into a deduced type, hence auto.

saxbophone commented 2 years ago

After briefly experimenting with this, I'm not that sure this is doable. It's worth a bit of further exploration before giving up, though.

saxbophone commented 2 years ago

Note: this is analogous to encode/decode as bytes, except we don't care about portability across different environments —these functions are intended to be used for transfer of arby values within the same program, without needing an arby object to marshal them around.

saxbophone commented 1 year ago

Rough working example of generating digits at compile-time:

#include <arby/Nat.hpp>

using namespace com::saxbophone::arby;

constexpr std::size_t size_of_multipliation(std::uintmax_t a, std::uintmax_t b) {
    return (Nat(a) * Nat(b)).digit_length();
}

#include <array>

template <std::uintmax_t a, std::uintmax_t b>
constexpr std::array<Nat::StorageType, size_of_multipliation(a, b)> multiply() {
    Nat product = Nat(a) * Nat(b);
    std::array<Nat::StorageType, size_of_multipliation(a, b)> digits;
    std::size_t i = 0;
    for (auto digit : product.digits()) {
        digits[i] = digit;
        i++;
    }
    return digits;
}

#include <iostream>

int main() {
    constexpr auto digits = multiply<3294794728947982, 38998723498324>();
    for (auto dig : digits) {
        std::cout << dig << " ";
    }
    std::cout << std::endl;
}