Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions changelog/std-bigint-getDigit.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
`getDigit` Was Added To `std.bigint`

$(REF getDigit, std, algorithm, BigInt) gives the `ulongs` or `uints`
that make up the underlying representation of the `BigInt`.

-----
import std.bigint;

auto a = BigInt("1000");
assert(a.getDigit(0) == 1000);

auto b = BigInt("2_000_000_000_000_000_000_000_000_000");
assert(b.getDigit(0) == 4584946418820579328);
assert(b.getDigit(1) == 108420217);
-----
47 changes: 47 additions & 0 deletions std/bigint.d
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,53 @@ public:
assert(aa[BigInt(456)] == "def");
}

/**
* Gets the nth number in the underlying representation that makes up the whole
* `BigInt`.
*
* Params:
* T = the type to view the underlying representation as
* n = The nth number to retrieve. Must be less than $(LREF ulongLength) or
* $(LREF uintLength) with respect to `T`.
* Returns:
* The nth `ulong` in the representation of this `BigInt`.
*/
T getDigit(T = ulong)(size_t n) const
if (is(T == ulong) || is(T == uint))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd think ushort and ubyte would also be useful, but can be added later.

{
static if (is(T == ulong))
{
assert(n < ulongLength(), "getDigit index out of bounds");
return data.peekUlong(n);
}
else
{
assert(n < uintLength(), "getDigit index out of bounds");
return data.peekUint(n);
}
}

///
@system pure unittest
{
auto a = BigInt("1000");
assert(a.ulongLength() == 1);
assert(a.getDigit(0) == 1000);

assert(a.uintLength() == 1);
assert(a.getDigit!uint(0) == 1000);

auto b = BigInt("2_000_000_000_000_000_000_000_000_000");
assert(b.ulongLength() == 2);
assert(b.getDigit(0) == 4584946418820579328);
assert(b.getDigit(1) == 108420217);

assert(b.uintLength() == 3);
assert(b.getDigit!uint(0) == 3489660928);
assert(b.getDigit!uint(1) == 1067516025);
assert(b.getDigit!uint(2) == 108420217);
}

private:
void negate() @safe pure nothrow @nogc
{
Expand Down
7 changes: 4 additions & 3 deletions std/internal/math/biguintcore.d
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public:
}

// The value at (cast(ulong[]) data)[n]
ulong peekUlong(int n) pure nothrow const @safe @nogc
ulong peekUlong(size_t n) pure nothrow const @safe @nogc
{
static if (BigDigit.sizeof == int.sizeof)
{
Expand All @@ -156,7 +156,8 @@ public:
return data[n];
}
}
uint peekUint(int n) pure nothrow const @safe @nogc

uint peekUint(size_t n) pure nothrow const @safe @nogc
{
static if (BigDigit.sizeof == int.sizeof)
{
Expand All @@ -168,7 +169,7 @@ public:
return (n & 1) ? cast(uint)(x >> 32) : cast(uint) x;
}
}
public:

///
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this removed because the following method wasn't intended to be public? Also, does this change somehow relate to this PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Public is already set a couple of lines above. It's pretty redundant and I don't think it's a problem to include such small things if they are trivial.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough.

Though I'm starting to agree with @andralex that private should be attached per declaration rather than wholesale, for better context when reading the code. But that's for another day.

void opAssign(Tulong)(Tulong u) pure nothrow @safe if (is (Tulong == ulong))
{
Expand Down