mirror of https://github.com/adamdruppe/arsd.git
Add UInt32p64 type
This commit is contained in:
parent
52c8b346bb
commit
1ddb1e1e0e
172
pixmappaint.d
172
pixmappaint.d
|
@ -374,6 +374,178 @@ static assert(Pixel.sizeof == uint.sizeof);
|
|||
}
|
||||
}
|
||||
|
||||
/++
|
||||
Unsigned 32-bit integer type with 64-bit precision for intermediate calculations
|
||||
+/
|
||||
struct UInt32p64 {
|
||||
private {
|
||||
ulong _value = 0;
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc:
|
||||
|
||||
///
|
||||
public this(uint initialValue) {
|
||||
_value = (long(initialValue) << 32);
|
||||
}
|
||||
|
||||
private static UInt32p64 make(ulong internal) {
|
||||
auto result = UInt32p64();
|
||||
result._value = internal;
|
||||
return result;
|
||||
}
|
||||
|
||||
///
|
||||
T opCast(T : uint)() const {
|
||||
return (_value >> 32).castTo!uint;
|
||||
}
|
||||
|
||||
///
|
||||
public UInt32p64 round() const {
|
||||
const truncated = (_value & 0xFFFF_FFFF_0000_0000);
|
||||
const delta = _value - truncated;
|
||||
|
||||
// dfmt off
|
||||
const rounded = (delta >= 0x8000_0000)
|
||||
? truncated + 0x1_0000_0000
|
||||
: truncated;
|
||||
// dfmt on
|
||||
|
||||
return UInt32p64.make(rounded);
|
||||
}
|
||||
|
||||
public {
|
||||
///
|
||||
UInt32p64 opBinary(string op : "+")(const uint rhs) const {
|
||||
return UInt32p64.make(_value + (ulong(rhs) << 32));
|
||||
}
|
||||
|
||||
/// ditto
|
||||
UInt32p64 opBinary(string op : "-")(const uint rhs) const {
|
||||
return UInt32p64.make(_value - (ulong(rhs) << 32));
|
||||
}
|
||||
|
||||
/// ditto
|
||||
UInt32p64 opBinary(string op : "*")(const uint rhs) const {
|
||||
return UInt32p64.make(_value * rhs);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
UInt32p64 opBinary(string op : "/")(const uint rhs) const {
|
||||
return UInt32p64.make(_value / rhs);
|
||||
}
|
||||
}
|
||||
|
||||
public {
|
||||
///
|
||||
UInt32p64 opBinaryRight(string op : "+")(const uint lhs) const {
|
||||
return UInt32p64.make((ulong(lhs) << 32) + _value);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
UInt32p64 opBinaryRight(string op : "-")(const uint lhs) const {
|
||||
return UInt32p64.make((ulong(lhs) << 32) - _value);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
UInt32p64 opBinaryRight(string op : "*")(const uint lhs) const {
|
||||
return UInt32p64.make(lhs * _value);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
UInt32p64 opBinaryRight(string op : "/")(const uint) const {
|
||||
static assert(false, "Use `int() / cast(int)(UInt32p64())` instead.");
|
||||
}
|
||||
}
|
||||
|
||||
public {
|
||||
///
|
||||
auto opOpAssign(string op : "+")(const uint rhs) {
|
||||
_value += (ulong(rhs) << 32);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
auto opOpAssign(string op : "-")(const uint rhs) {
|
||||
_value -= (ulong(rhs) << 32);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
auto opOpAssign(string op : "*")(const uint rhs) {
|
||||
_value *= rhs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
auto opOpAssign(string op : "/")(const uint rhs) {
|
||||
_value /= rhs;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest {
|
||||
assert(UInt32p64(uint.max).castTo!uint == uint.max);
|
||||
assert(UInt32p64(uint.min).castTo!uint == uint.min);
|
||||
assert(UInt32p64(1).castTo!uint == 1);
|
||||
assert(UInt32p64(2).castTo!uint == 2);
|
||||
assert(UInt32p64(1_991_007).castTo!uint == 1_991_007);
|
||||
|
||||
assert((UInt32p64(uint.max) / 2).castTo!uint == 2_147_483_647);
|
||||
assert((UInt32p64(uint.max) / 2).round().castTo!uint == 2_147_483_648);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest {
|
||||
UInt32p64 val;
|
||||
|
||||
val = UInt32p64(10);
|
||||
val += 12;
|
||||
assert(val.castTo!uint == 22);
|
||||
|
||||
val = UInt32p64(1024);
|
||||
val -= 24;
|
||||
assert(val.castTo!uint == 1000);
|
||||
val -= 100;
|
||||
assert(val.castTo!uint == 900);
|
||||
val += 5;
|
||||
assert(val.castTo!uint == 905);
|
||||
|
||||
val = UInt32p64(256);
|
||||
val *= 4;
|
||||
assert(val.castTo!uint == (256 * 4));
|
||||
|
||||
val = UInt32p64(2048);
|
||||
val /= 10;
|
||||
val *= 10;
|
||||
assert(val.castTo!uint == 2047);
|
||||
}
|
||||
|
||||
@safe unittest {
|
||||
UInt32p64 val;
|
||||
|
||||
val = UInt32p64(9_000_000);
|
||||
val /= 13;
|
||||
val *= 4;
|
||||
|
||||
// ≈ 2,769,230.8
|
||||
assert(val.castTo!uint == 2_769_230);
|
||||
assert(val.round.castTo!uint == 2_769_231);
|
||||
// assert(uint(9_000_000) / uint(13) * uint(4) == 2_769_228);
|
||||
|
||||
val = UInt32p64(64);
|
||||
val /= 31;
|
||||
val *= 30;
|
||||
val /= 29;
|
||||
val *= 28;
|
||||
|
||||
// ≈ 59.8
|
||||
assert(val.castTo!uint == 59);
|
||||
assert(val.round().castTo!uint == 60);
|
||||
// assert(((((64 / 31) * 30) / 29) * 28) == 56);
|
||||
}
|
||||
|
||||
/++
|
||||
$(I Advanced functionality.)
|
||||
|
||||
|
|
Loading…
Reference in New Issue