summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-05-08 21:09:52 +0200
committerEugen Wissner <belka@caraus.de>2017-05-08 21:09:52 +0200
commit06620dc5df6aacd1cbfeb60ba942c849203ad891 (patch)
treeffbe6c3bcca9131705dc02613ee09274fe5fe097
parent708d95db494ca38409bebf054a3134138eb63b6e (diff)
downloadtanya-06620dc5df6aacd1cbfeb60ba942c849203ad891.tar.gz
math.mp.Integer: Return two's complement length
-rw-r--r--source/tanya/math/mp.d56
1 files changed, 54 insertions, 2 deletions
diff --git a/source/tanya/math/mp.d b/source/tanya/math/mp.d
index e55829c..6e0c5ca 100644
--- a/source/tanya/math/mp.d
+++ b/source/tanya/math/mp.d
@@ -178,12 +178,64 @@ struct Integer
allocator.resize(this.rep, 0);
}
+ static private const short[16] bitCounts = [
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+ ];
+
+ // Counts the number of LSBs before the first non-zero bit.
+ private ptrdiff_t countLSBs() const pure nothrow @safe @nogc
+ {
+ if (this.size == 0)
+ {
+ return 0;
+ }
+
+ ptrdiff_t bits;
+ for (bits = 0; (bits < this.size) && (this.rep[bits] == 0); ++bits)
+ {
+ }
+ digit nonZero = this.rep[bits];
+ bits *= digitBitCount;
+
+ /* now scan this digit until a 1 is found */
+ if ((nonZero & 0x01) == 0)
+ {
+ digit bitCountsPos;
+ do
+ {
+ bitCountsPos = nonZero & 0x0f;
+ bits += bitCounts[bitCountsPos];
+ nonZero >>= 4;
+ }
+ while (bitCountsPos == 0);
+ }
+ return bits;
+ }
+
/**
- * Returns: Integer byte length.
+ * Returns: Number of bytes in the two's complement representation.
*/
@property size_t length() const pure nothrow @safe @nogc
{
- return (countBits() + 7) / 8; // Round up.
+ if (this.sign)
+ {
+ const bitCount = countBits();
+ auto length = bitCount + (8 - (bitCount & 0x07));
+
+ if (((countLSBs() + 1) == bitCount) && ((bitCount & 0x07) == 0))
+ {
+ --length;
+ }
+ return length / 8;
+ }
+ else if (this.size == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return (countBits() / 8) + 1;
+ }
}
/**