Skip to content
Open
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
61 changes: 61 additions & 0 deletions druntime/src/core/int128.d
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,20 @@ Cent neg(Cent c)
return c;
}

/*****************************
* Absolute value
* Note: This is a signed operation.
* Params:
* c = Cent to get absolute value of
* Returns:
* absolute value of c
*/
pure
Cent abs(Cent c)
{
return (cast(I)c.hi < 0) ? neg(c) : c;
}

/*****************************
* Increment
* Params:
Expand Down Expand Up @@ -237,6 +251,9 @@ in (n < Ubits * 2)

/*****************************
* Arithmetic shift right n bits
*
* Note: This is a signed shift (preserves the sign bit).
*
* Params:
* c = Cent to shift
* n = number of bits to shift
Expand Down Expand Up @@ -417,6 +434,7 @@ Cent sub(Cent c1, Cent c2)

/****************************
* Multiply c1 * c2.
* Note: The algorithm is identical for both signed and unsigned multiplication.
* Params:
* c1 = operand 1
* c2 = operand 2
Expand Down Expand Up @@ -721,6 +739,7 @@ U udivmod(Cent c1, U c2, out U modulus)

/****************************
* Signed divide c1 / c2.
* Note: Performs signed division. Use udiv() for unsigned division.
* Params:
* c1 = dividend
* c2 = divisor
Expand Down Expand Up @@ -768,6 +787,38 @@ Cent divmod(Cent c1, Cent c2, out Cent modulus)
return udivmod(c1, c2, modulus);
}

/*****************************
* Unsigned remainder c1 % c2.
* Params:
* c1 = dividend
* c2 = divisor
* Returns:
* remainder c1 % c2
*/
pure
Cent urem(Cent c1, Cent c2)
{
Cent modulus;
udivmod(c1, c2, modulus);
return modulus;
}

/*****************************
* Signed remainder c1 % c2.
* Params:
* c1 = dividend
* c2 = divisor
* Returns:
* remainder c1 % c2
*/
pure
Cent rem(Cent c1, Cent c2)
{
Cent modulus;
divmod(c1, c2, modulus);
return modulus;
}

/****************************
* If c1 > c2 unsigned
* Params:
Expand Down Expand Up @@ -1052,4 +1103,14 @@ unittest
assert(ror(C7_9, 1) == ror1(C7_9));
assert(rol(C7_9, 0) == C7_9);
assert(ror(C7_9, 0) == C7_9);

// Test abs()
assert(abs(Cm10) == C10);
assert(abs(C10) == C10);
assert(abs(C0) == C0);

// Test rem/urem
assert(rem(C10, C3) == C1); // 10 % 3 = 1
assert(urem(C10, C3) == C1);
assert(rem(Cm10, C3) == Cm1); // -10 % 3 = -1
Copy link
Member

@ibuclaw ibuclaw Dec 15, 2025

Choose a reason for hiding this comment

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

Perhaps add check that unsigned mod/remainder matches the % operator?

Suggested change
assert(rem(Cm10, C3) == Cm1); // -10 % 3 = -1
assert(rem(Cm10, C3) == Cm1); // -10 % 3 = -1
assert(urem(Cm10, C3) == C0); // -10U % 3 = 0

}
Loading