smartOp.binary

Perform the binary (two-argument) integer operation specified by op.

Key differences from the standard binary operators:

  • +, -, *, /, and % return a signed type if the result could be negative, unless both inputs are unsigned.
  • +, -, *, and / are checked for overflow.
  • / and % are checked for divide-by-zero, and will never generate an FPE.
  • <<, >>, and >>> are well-defined for all possible values of right. Large shifts return the same result as shifting by 1 right times in a row. (But, much faster because no actual loop is used.)


Note also:

  • The shift operators are not checked for overflow and should not be used for multiplication, division, or exponentiation. Instead, use mulPow2() and divPow2(), which internally use the bitshifts for speed, but check for overflow and correctly handle negative values.
  • Likewise, modPow2() should be used for remainders instead of &.
  • ^^ and ^^= will remain disabled in favour of pow until DMD issues 15288 and 15412 are fixed.


Like the standard equivalents, the assignment operators (+=, -=, *=, etc.) take left by ref and will overwrite it with the result of the operation.

  1. auto binary(const N left, const M right)
    template smartOp(IntFlagPolicy policy)
    binary
    @safe
    (
    string op
    N
    M
    )
    (
    const N left
    ,
    const M right
    )
    if (
    isFixedPoint!N &&
    isFixedPoint!M
    &&
    op.among!("+", "-", "*", "/", "%", "^^", "<<", ">>", ">>>", "&", "|", "^")
    )
  2. N binary(return ref N left, const M right)

Examples

1 import checkedint.sticky : smartOp; // use IntFlagPolicy.sticky
2 
3 ulong a = 18_446_744_073_709_551_615uL;
4 long b =      -6_744_073_709_551_615L;
5 auto c = smartOp.binary!"+"(a, b);
6 static assert(isSigned!(typeof(c)));
7 assert(IntFlags.local.clear() == IntFlag.posOver);
8 
9 assert(smartOp.binary!"+="(a, b) == 18_440_000_000_000_000_000uL);
10 assert(a == 18_440_000_000_000_000_000uL);
11 
12 uint d = 25u;
13 int e = 32;
14 auto f = smartOp.binary!"-"(d, e);
15 static assert(isSigned!(typeof(f)));
16 assert(f == -7);
17 
18 smartOp.binary!"-="(d, e);
19 assert(IntFlags.local.clear() == IntFlag.negOver);
20 
21 uint g = 1u << 31;
22 int h = -1;
23 auto i = smartOp.binary!"*"(g, h);
24 static assert(isSigned!(typeof(i)));
25 assert(i == int.min);
26 
27 smartOp.binary!"*="(g, h);
28 assert(IntFlags.local.clear() == IntFlag.negOver);
29 
30 long j = long.min;
31 ulong k = 1uL << 63;
32 auto m = smartOp.binary!"/"(j, k);
33 static assert(isSigned!(typeof(m)));
34 assert(m == -1);
35 
36 smartOp.binary!"/="(j, -1);
37 assert(IntFlags.local.clear() == IntFlag.posOver);
38 
39 ushort n = 20u;
40 ulong p = ulong.max;
41 auto q = smartOp.binary!"%"(n, p);
42 static assert(is(typeof(q) == ushort));
43 assert(q == 20u);
44 
45 smartOp.binary!"%="(n, 0);
46 assert(IntFlags.local.clear() == IntFlag.div0);
1 import checkedint.sticky : smartOp; // use IntFlagPolicy.sticky
2 
3 assert(smartOp.binary!"<<"(-0x80, -2) == -0x20);
4 ubyte a = 0x3u;
5 long b = long.max;
6 auto c = smartOp.binary!"<<"(a, b);
7 static assert(is(typeof(c) == ubyte));
8 assert(c == 0u);
9 
10 assert(smartOp.binary!"<<="(a, 7) == 0x80u);
11 assert(a == 0x80u);
12 
13 short d = -0xC;
14 ubyte e = 5u;
15 auto f = smartOp.binary!">>"(d, e);
16 static assert(is(typeof(f) == short));
17 assert(f == -0x1);
18 
19 assert(smartOp.binary!">>="(d, -8) == -0xC00);
20 assert(d == -0xC00);
21 
22 int g = -0x80;
23 ulong h = 2u;
24 auto i = smartOp.binary!">>>"(g, h);
25 static assert(is(typeof(i) == int));
26 assert(i == 0x3FFF_FFE0);
27 
28 assert(smartOp.binary!">>>="(g, 32) == 0);
29 assert(g == 0);
30 
31 ubyte j = 0x6Fu;
32 short k = 0x4076;
33 auto m = smartOp.binary!"&"(j, k);
34 static assert(is(typeof(m) == ushort));
35 assert(m == 0x66u);
36 
37 assert(smartOp.binary!"&="(j, k) == 0x66u);
38 assert(j == 0x66u);
39 
40 byte n = 0x6F;
41 ushort p = 0x4076u;
42 auto q = smartOp.binary!"|"(n, p);
43 static assert(is(typeof(q) == ushort));
44 assert(q == 0x407Fu);
45 
46 assert(smartOp.binary!"|="(n, p) == 0x7F);
47 assert(n == 0x7F);
48 
49 int r = 0x6F;
50 int s = 0x4076;
51 auto t = smartOp.binary!"^"(r, s);
52 static assert(is(typeof(t) == int));
53 assert(t == 0x4019);
54 
55 assert(smartOp.binary!"^="(r, s) == 0x4019);
56 assert(r == 0x4019);
57 
58 assert(!IntFlags.local);

Meta