diff --git a/include/mcl/window_method.hpp b/include/mcl/window_method.hpp index cb4fad3..64ff869 100644 --- a/include/mcl/window_method.hpp +++ b/include/mcl/window_method.hpp @@ -23,35 +23,33 @@ struct ArrayIterator { , bitSize(bitSize) , w(w) , pos(0) - , mask((w == TbitSize ? 0 : (T(1) << w)) - 1) + , mask(makeMask(w)) { assert(w <= TbitSize); } + T makeMask(size_t w) const + { + return (w == TbitSize) ? ~T(0) : (T(1) << w) - 1; + } bool hasNext() const { return bitSize > 0; } T getNext() { - if (w == TbitSize) { - bitSize -= w; - return *x++; + if (bitSize < w) { + w = bitSize; + mask = makeMask(w); } - if (pos + w < TbitSize) { - T v = (*x >> pos) & mask; - pos += w; - if (bitSize < w) { - bitSize = 0; + if (pos + w <= TbitSize) { + T v = x[0] >> pos; + if (pos + w < TbitSize) { + pos += w; + v &= mask; } else { - bitSize -= w; + pos = 0; + x++; } + bitSize -= w; return v; } - if (pos + bitSize <= TbitSize) { - assert(bitSize <= w); - T v = *x >> pos; - assert((v >> bitSize) == 0); - bitSize = 0; - return v & mask; - } - assert(pos > 0); T v = (x[0] >> pos) | (x[1] << (TbitSize - pos)); v &= mask; pos = (pos + w) - TbitSize; diff --git a/test/window_method_test.cpp b/test/window_method_test.cpp index 1b0f702..437ad55 100644 --- a/test/window_method_test.cpp +++ b/test/window_method_test.cpp @@ -6,21 +6,24 @@ CYBOZU_TEST_AUTO(ArrayIterator) { - const uint32_t in[2] = { 0x12345678, 0xabcdef89 }; - const size_t bitSize = 64; - for (size_t w = 1; w <= 32; w++) { - const uint32_t mask = uint32_t((uint64_t(1) << w) - 1); - mpz_class x; - mcl::gmp::setArray(x, in, 2); - mcl::fp::ArrayIterator ai(in, bitSize, w); - size_t n = (bitSize + w - 1) / w; - for (size_t j = 0; j < n; j++) { - CYBOZU_TEST_ASSERT(ai.hasNext()); - uint32_t v = ai.getNext(); - CYBOZU_TEST_EQUAL(x & mask, v); - x >>= w; + const uint32_t in[] = { 0x12345678, 0xabcdef89, 0xaabbccdd }; + for (size_t bitSize = 1; bitSize <= 64; bitSize++) { + for (size_t w = 1; w <= 32; w++) { + + const uint32_t mask = uint32_t((uint64_t(1) << w) - 1); + mpz_class x; + mcl::gmp::setArray(x, in, CYBOZU_NUM_OF_ARRAY(in)); + x &= (mpz_class(1) << bitSize) - 1; + mcl::fp::ArrayIterator ai(in, bitSize, w); + size_t n = (bitSize + w - 1) / w; + for (size_t j = 0; j < n; j++) { + CYBOZU_TEST_ASSERT(ai.hasNext()); + uint32_t v = ai.getNext(); + CYBOZU_TEST_EQUAL(x & mask, v); + x >>= w; + } + CYBOZU_TEST_ASSERT(!ai.hasNext()); } - CYBOZU_TEST_ASSERT(!ai.hasNext()); } }