Skip to content

Commit

Permalink
add std.int128
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Apr 3, 2022
1 parent 99e9c1b commit 11c1ad6
Show file tree
Hide file tree
Showing 4 changed files with 283 additions and 1 deletion.
2 changes: 1 addition & 1 deletion posix.mak
Expand Up @@ -210,7 +210,7 @@ STD_PACKAGES = std $(addprefix std/,\

PACKAGE_std = array ascii base64 bigint bitmanip checkedint compiler complex concurrency \
conv csv demangle encoding exception file \
functional getopt json mathspecial meta mmfile numeric \
functional getopt int128 json mathspecial meta mmfile numeric \
outbuffer package parallelism path process random signals socket stdint \
stdio string sumtype system traits typecons \
uri utf uuid variant xml zip zlib
Expand Down
279 changes: 279 additions & 0 deletions std/int128.d
@@ -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);
}
2 changes: 2 additions & 0 deletions win32.mak
Expand Up @@ -139,6 +139,7 @@ SRC_STD_3a= \
std\concurrency.d

SRC_STD_4= \
std\int128.d \
std\uuid.d

SRC_STD_6= \
Expand Down Expand Up @@ -457,6 +458,7 @@ cov : $(SRC_TO_COMPILE) $(LIB)
$(DMD) -conf= -cov=ctfe -cov=89 $(UDFLAGS) -main -run std\utf.d
$(DMD) -conf= -cov=ctfe -cov=93 $(UDFLAGS) -main -run std\csv.d
$(DMD) -conf= -cov=ctfe -cov=95 $(UDFLAGS) -main -run std\complex.d
$(DMD) -conf= -cov=ctfe -cov=95 $(UDFLAGS) -main -run std\int128.d
$(DMD) -conf= -cov=ctfe -cov=70 $(UDFLAGS) -main -run std\numeric.d
$(DMD) -conf= -cov=ctfe -cov=94 $(UDFLAGS) -main -run std\bigint.d
$(DMD) -conf= -cov=ctfe -cov=95 $(UDFLAGS) -main -run std\bitmanip.d
Expand Down
1 change: 1 addition & 0 deletions win64.mak
Expand Up @@ -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
Expand Down

0 comments on commit 11c1ad6

Please sign in to comment.