Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
99e9c1b
commit 11c1ad6
Showing
4 changed files
with
283 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,279 @@ | ||
// Written in the D programming language | ||
/** | ||
* Implements a signed 128 bit integer type. | ||
* | ||
Author: Walter Bright | ||
Copyright: Copyright (c) 2022, D Language Foundation | ||
License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0) | ||
Source: $(PHOBOSSRC std/int128.d) | ||
*/ | ||
module std.int128; | ||
|
||
private import core.int128; | ||
|
||
|
||
/*********************************** | ||
* 128 bit signed integer type. | ||
*/ | ||
|
||
public struct Int128 | ||
{ | ||
@safe pure nothrow @nogc: | ||
|
||
Cent data; | ||
|
||
/**************** | ||
* Construct an `Int128` from a `long` value. | ||
* The upper 64 bits are formed by sign extension. | ||
* Params: | ||
* lo = signed lower 64 bits | ||
*/ | ||
this(long lo) | ||
{ | ||
data.lo = lo; | ||
data.hi = lo < 0 ? ~0L : 0; | ||
} | ||
|
||
/**************** | ||
* Construct an `Int128` from a `long` value. | ||
* Params: | ||
* hi = upper 64 bits | ||
* lo = lower 64 bits | ||
*/ | ||
this(long hi, long lo) | ||
{ | ||
data.hi = hi; | ||
data.lo = lo; | ||
} | ||
|
||
this(Cent data) | ||
{ | ||
this.data = data; | ||
} | ||
|
||
bool opEquals(long lo) const | ||
{ | ||
return data.hi == 0 && data.lo == lo; | ||
} | ||
|
||
bool opEquals(Int128 op2) const | ||
{ | ||
return data.hi == op2.data.hi && data.lo == op2.data.lo; | ||
} | ||
|
||
// +Int128 | ||
Int128 opUnary(string op)() const | ||
if (op == "+") | ||
{ | ||
return this; | ||
} | ||
|
||
// -Int128 | ||
Int128 opUnary(string op)() const | ||
if (op == "-") | ||
{ | ||
return Int128(neg(this.data)); | ||
} | ||
|
||
// ~Int128 | ||
Int128 opUnary(string op)() const | ||
if (op == "~") | ||
{ | ||
return Int128(com(this.data)); | ||
} | ||
|
||
// cast(T)Int128 | ||
bool opCast(T : bool)() const | ||
{ | ||
return tst(this.data); | ||
} | ||
|
||
// Int128 + Int128 | ||
Int128 opBinary(string op)(Int128 op2) const | ||
if (op == "+" || op == "-" || | ||
op == "*" || op == "/" || op == "%" || | ||
op == "&" || op == "|" || op == "^") | ||
{ | ||
if (op == "+") | ||
return Int128(add(this.data, op2.data)); | ||
else if (op == "-") | ||
return Int128(sub(this.data, op2.data)); | ||
else if (op == "*") | ||
return Int128(mul(this.data, op2.data)); | ||
else if (op == "/") | ||
return Int128(div(this.data, op2.data)); | ||
else if (op == "%") | ||
{ | ||
Cent modulus; | ||
divmod(this.data, op2.data, modulus); | ||
return Int128(modulus); | ||
} | ||
else if (op == "&") | ||
return Int128(and(this.data, op2.data)); | ||
else if (op == "|") | ||
return Int128(or(this.data, op2.data)); | ||
else if (op == "^") | ||
return Int128(xor(this.data, op2.data)); | ||
else | ||
assert(0); | ||
} | ||
|
||
// Int128 + long | ||
Int128 opBinary(string op)(long lo) const | ||
if (op == "+" || op == "-" || | ||
op == "*" || op == "/" || op == "%" || | ||
op == "&" || op == "|" || op == "^") | ||
{ | ||
return mixin("this " ~ op ~ " Int128(0, lo)"); | ||
} | ||
|
||
// long + Int128 | ||
Int128 opBinaryRight(string op)(long lo) const | ||
if (op == "+" || op == "-" || | ||
op == "*" || op == "/" || op == "%" || | ||
op == "&" || op == "|" || op == "^") | ||
{ | ||
mixin("return Int128(0, lo) " ~ op ~ " this;"); | ||
} | ||
|
||
// Int128 << uint | ||
Int128 opBinary(string op)(long n) const | ||
if (op == "<<") | ||
{ | ||
return Int128(shl(this.data, cast(uint)n)); | ||
} | ||
|
||
// Int128 >> uint | ||
Int128 opBinary(string op)(long n) const | ||
if (op == ">>") | ||
{ | ||
return Int128(sar(this.data, cast(uint)n)); | ||
} | ||
|
||
// Int128 >>> uint | ||
Int128 opBinary(string op)(long n) const | ||
if (op == ">>>") | ||
{ | ||
return Int128(shr(this.data, cast(uint)n)); | ||
} | ||
|
||
ref Int128 opOpAssign(string op)(Int128 op2) | ||
if (op == "+" || op == "-" || | ||
op == "*" || op == "/" || op == "%" || | ||
op == "&" || op == "|" || op == "^" || | ||
op == "<<" || op == ">>" || op == ">>>") | ||
{ | ||
mixin("this = this " ~ op ~ " op2;"); | ||
return this; | ||
} | ||
|
||
ref Int128 opOpAssign(string op)(long op2) | ||
if (op == "+" || op == "-" || | ||
op == "*" || op == "/" || op == "%" || | ||
op == "&" || op == "|" || op == "^" || | ||
op == "<<" || op == ">>" || op == ">>>") | ||
{ | ||
mixin("this = this " ~ op ~ " op2;"); | ||
return this; | ||
} | ||
|
||
int opCmp(Int128 op2) | ||
{ | ||
return this == op2 ? 0 : gt(this.data, op2.data) * 2 - 1; | ||
} | ||
|
||
int opCmp(long op2) | ||
{ | ||
return opCmp(Int128(0, op2)); | ||
} | ||
|
||
enum min = Int128(long.min, 0); /// minimum value | ||
enum max = Int128(long.max, ulong.max); /// maximum value | ||
} | ||
|
||
/********************************************* Tests ************************************/ | ||
|
||
version (unittest) | ||
{ | ||
import core.stdc.stdio; | ||
|
||
void print(Int128 c) | ||
{ | ||
printf("%lld, %lld\n", c.data.hi, c.data.lo); | ||
} | ||
|
||
void printx(Int128 c) | ||
{ | ||
printf("%llx, %llx\n", c.data.hi, c.data.lo); | ||
} | ||
} | ||
|
||
unittest | ||
{ | ||
Int128 c = Int128(5, 6); | ||
assert(c == c); | ||
assert(c == +c); | ||
assert(c == - -c); | ||
assert(~c == Int128(~5, ~6)); | ||
assert(!!c); | ||
assert(!Int128()); | ||
|
||
assert(c + Int128(10, 20) == Int128(15, 26)); | ||
assert(c - Int128(1, 2) == Int128(4, 4)); | ||
assert(c * Int128(100, 2) == Int128(610, 12)); | ||
assert(c / Int128(3, 2) == Int128(0, 1)); | ||
assert(c % Int128(3, 2) == Int128(2, 4)); | ||
assert((c & Int128(3, 2)) == Int128(1, 2)); | ||
assert((c | Int128(3, 2)) == Int128(7, 6)); | ||
assert((c ^ Int128(3, 2)) == Int128(6, 4)); | ||
|
||
assert(c + 15 == Int128(5, 21)); | ||
assert(c - 15 == Int128(4, -9)); | ||
assert(c * 15 == Int128(75, 90)); | ||
assert(c / 15 == Int128(0, 6148914691236517205)); | ||
assert(c % 15 == Int128(0, 11)); | ||
assert((c & 15) == Int128(0, 6)); | ||
assert((c | 15) == Int128(5, 15)); | ||
assert((c ^ 15) == Int128(5, 9)); | ||
|
||
assert(15 + c == Int128(5, 21)); | ||
assert(15 - c == Int128(-5, 9)); | ||
assert(15 * c == Int128(75, 90)); | ||
assert(15 / c == Int128(0, 0)); | ||
assert(15 % c == Int128(0, 15)); | ||
assert((15 & c) == Int128(0, 6)); | ||
assert((15 | c) == Int128(5, 15)); | ||
assert((15 ^ c) == Int128(5, 9)); | ||
|
||
assert(c << 1 == Int128(10, 12)); | ||
assert(-c >> 1 == Int128(-3, 9223372036854775805)); | ||
assert(-c >>> 1 == Int128(9223372036854775805, 9223372036854775805)); | ||
|
||
assert((c += 1) == Int128(5, 7)); | ||
assert((c -= 1) == Int128(5, 6)); | ||
assert((c += Int128(0, 1)) == Int128(5, 7)); | ||
assert((c -= Int128(0, 1)) == Int128(5, 6)); | ||
assert((c *= 2) == Int128(10, 12)); | ||
assert((c /= 2) == Int128(5, 6)); | ||
assert((c %= 2) == Int128()); | ||
c += Int128(5, 6); | ||
assert((c *= Int128(10, 20)) == Int128(160, 120)); | ||
assert((c /= Int128(10, 20)) == Int128(0, 15)); | ||
c += Int128(72, 0); | ||
assert((c %= Int128(10, 20)) == Int128(1, -125)); | ||
assert((c &= Int128(3, 20)) == Int128(1, 0)); | ||
assert((c |= Int128(8, 2)) == Int128(9, 2)); | ||
assert((c ^= Int128(8, 2)) == Int128(1, 0)); | ||
c |= Int128(10, 5); | ||
assert((c <<= 1) == Int128(11 * 2, 5 * 2)); | ||
assert((c >>>= 1) == Int128(11, 5)); | ||
c = Int128(long.min, long.min); | ||
assert((c >>= 1) == Int128(long.min >> 1, cast(ulong)long.min >> 1)); | ||
|
||
assert(-Int128.min == Int128.min); | ||
assert(Int128.max + 1 == Int128.min); | ||
|
||
c = Int128(5, 6); | ||
assert(c < Int128(6, 5)); | ||
assert(c > 10); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -145,6 +145,7 @@ SRC_STD_3d= \ | |
std\typecons.d | ||
|
||
SRC_STD_4= \ | ||
std\int128.d \ | ||
std\uuid.d | ||
|
||
SRC_STD_6a=std\variant.d | ||
|