Algorithms

Returns true and a value inside a unsigned long long if the conversion is possible (usign this algorithm), otherwise returns false.


Declaration

template<unsigned long long base, class It>
bool to_int(It first, It last, unsigned long long& r);

Sample

         {1}     -> 1
            10

         {0}     -> 0
            10

   {0, 0, 0}     -> 0
            10

{0, 0, 1, 2}     -> 12
            10

   {1, 1, 1}     -> 111
            10

Sample

void to_int_test()
{
  using namespace std;

  int a[] = {0, 1, 0, 0};
  unsigned long long res = 0;
  assert(to_int<10>(begin(a), end(a), res) == true);
  assert(res == 10);

  //18446744073709551615 + 1
  int b[] = {1 + 5, 1, 6, 1, 5, 5, 9, 0, 7, 3, 7, 0, 4, 4, 7, 6, 4, 4, 8 , 1};

  res = 0;
  assert(to_int<10>(begin(b), end(b), res) == false);
  assert(res == 0);

  
  int c[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  res = 0;
  assert(to_int<10>(begin(c), end(c), res) == true);
  assert(res == 0);
}

Implementation


bool UnsignedUnsignedSum(unsigned long long x, unsigned long long y)
{
    return y <= LLONG_MAX  - x;
}

bool UnsignedUnsignedMulti(unsigned long long x, unsigned long long y)
{
    if (x == 0 || x == 1)
    {
        return true;
    }

    return y <= LLONG_MAX / x;
}

template<unsigned long long base, class It>
bool to_int(It first, It last, unsigned long long& r)
{
    static_assert(base > 1, "base must be > 1");

    last = sig_digit_end(first, last);

    unsigned long long rb = 1;
    r = 0; //out

    for (; first != last; first++)
    {
        unsigned long long dig = *first;
        if (!UnsignedUnsignedMulti(rb, dig) || !UnsignedUnsignedSum(r, rb * dig))
        {
            r = 0;//overflow
            return false;
        }

        r = r + rb * dig;

        if (!UnsignedUnsignedMulti(rb, base))
        {
            r = 0;//overflow
            return false;
        }

        rb = rb * base;
    }

    return true;
}