@@ -153,6 +153,7 @@ public struct Int128
153153 {
154154 return tst (this .data);
155155 }
156+ } // @safe pure nothrow @nogc
156157
157158 /* * Support binary arithmetic operators + - * / % & | ^ << >> >>>
158159 * Params:
@@ -190,21 +191,49 @@ public struct Int128
190191 }
191192
192193 // / ditto
193- Int128 opBinary (string op)( long op2) const
194- if (op == " +" || op == " -" ||
194+ Int128 opBinary (string op, Int)( const Int op2) const
195+ if (( op == " +" || op == " -" ||
195196 op == " *" || op == " /" || op == " %" ||
196- op == " &" || op == " |" || op == " ^" )
197+ op == " &" || op == " |" || op == " ^" ) &&
198+ is (Int : long ) && __traits(isIntegral, Int))
197199 {
198- return mixin (" this " ~ op ~ " Int128(0, op2)" );
200+ static if (__traits(isUnsigned, Int))
201+ return mixin (" this " ~ op ~ " Int128(0, op2)" );
202+ else
203+ return mixin (" this " ~ op ~ " Int128((cast(long) op2) >> 63 , op2)" );
199204 }
200205
201206 // / ditto
202- Int128 opBinaryRight (string op)( long op2) const
203- if (op == " +" || op == " -" ||
207+ Int128 opBinary (string op, IntLike)( auto ref IntLike op2) const
208+ if (( op == " +" || op == " -" ||
204209 op == " *" || op == " /" || op == " %" ||
205- op == " &" || op == " |" || op == " ^" )
210+ op == " &" || op == " |" || op == " ^" ) &&
211+ is (IntLike : long ) && ! __traits(isIntegral, IntLike))
206212 {
207- mixin (" return Int128(0, op2) " ~ op ~ " this;" );
213+ return opBinary! (op)(__traits(getMember, op2, __traits(getAliasThis, IntLike)[0 ]));
214+ }
215+
216+ // / ditto
217+ Int128 opBinaryRight (string op, Int)(const Int op2) const
218+ if ((op == " +" || op == " -" ||
219+ op == " *" || op == " /" || op == " %" ||
220+ op == " &" || op == " |" || op == " ^" ) &&
221+ is (Int : long ) && __traits(isIntegral, Int))
222+ {
223+ static if (__traits(isUnsigned, Int))
224+ mixin (" return Int128(0, op2) " ~ op ~ " this;" );
225+ else
226+ mixin (" return Int128((cast(long) op2) >> 63, op2) " ~ op ~ " this;" );
227+ }
228+
229+ // / ditto
230+ Int128 opBinaryRight (string op, IntLike)(auto ref IntLike op2) const
231+ if ((op == " +" || op == " -" ||
232+ op == " *" || op == " /" || op == " %" ||
233+ op == " &" || op == " |" || op == " ^" ) &&
234+ is (IntLike : long ) && ! __traits(isIntegral, IntLike))
235+ {
236+ return opBinaryRight! (op)(__traits(getMember, op2, __traits(getAliasThis, IntLike)[0 ]));
208237 }
209238
210239 // / ditto
@@ -244,16 +273,16 @@ public struct Int128
244273 }
245274
246275 // / ditto
247- ref Int128 opOpAssign (string op)( long op2)
248- if (op == " +" || op == " -" ||
276+ ref Int128 opOpAssign (string op, Int)( auto ref Int op2)
277+ if (( op == " +" || op == " -" ||
249278 op == " *" || op == " /" || op == " %" ||
250279 op == " &" || op == " |" || op == " ^" ||
251280 op == " <<" || op == " >>" || op == " >>>" )
281+ && is (Int : long ))
252282 {
253283 mixin (" this = this " ~ op ~ " op2;" );
254284 return this ;
255285 }
256- } // @safe pure nothrow @nogc
257286
258287 /* * support arithmentic comparison operators < <= > >=
259288 * Params: op2 = right hand operand
@@ -411,4 +440,29 @@ unittest
411440 auto w = Wrapped! ulong (ulong .max);
412441 w.count++ ; // avoid invalid D-Scanner message that w could have been declared const
413442 assert (c < w);
443+
444+ const zero = Int128(0L );
445+ const one = Int128(1L );
446+ const neg_one = Int128(- 1L );
447+ const neg_two = Int128(- 2L );
448+ // Correct result with ulong.max:
449+ assert (zero + ulong .max == ulong .max);
450+ assert (one * ulong .max == ulong .max);
451+ assert ((neg_one & ulong .max) == ulong .max);
452+ assert ((zero | ulong .max) == ulong .max);
453+ assert ((zero ^ ulong .max) == ulong .max);
454+ // Correct result with negative arguments:
455+ assert (zero + - 1L == - 1L );
456+ assert (neg_two * - 3L == 6L );
457+ assert (neg_two / - 2L == 1L );
458+ assert (neg_two % - 2L == 0L );
459+ assert ((neg_one & - 1L ) == - 1L );
460+ assert ((zero | - 1L ) == - 1L );
461+ assert ((zero ^ - 1L ) == - 1L );
462+ // Ensure alias this still works.
463+ {
464+ Int128 a = zero;
465+ assert ((a ^= w) == ulong .max);
466+ }
467+ assert ((Wrapped! long (- 1L ) + zero) == - 1L );
414468}
0 commit comments