1 /***************************************************************************************************
2  * 
3  * Supplementary integer math functions.
4  * 
5  * Authors:
6  *   $(LINK2 mailto:Marco.Leise@gmx.de, Marco Leise)
7  * 
8  * Copyright:
9  *   © 2015 $(LINK2 mailto:Marco.Leise@gmx.de, Marco Leise)
10  * 
11  * License:
12  *   $(LINK2 http://www.gnu.org/licenses/gpl-3.0, GNU General Public License 3.0)
13  * 
14  **************************************************************************************************/
15 module fast.intmath;
16 
17 import fast.helpers;
18 
19 
20 version (LDC)
21 {
22 	@safe @nogc pure nothrow
23 	ulong mulu(ulong x, ulong y, ref bool overflow)
24 	{
25 		import ldc.intrinsics;
26 		auto res = llvm_umul_with_overflow(x, y);
27 		overflow = res.overflow;
28 		return res.result;
29 	}
30 }
31 else static if (isPosix && isGDC && (isAMD64 || isX86))
32 {
33 	@nogc pure nothrow
34 	ulong mulu(ulong x, ulong y, ref bool overflow)
35 	{
36 		version (GNU)
37 		{
38 			ulong lo;
39 			version (X86) asm { "
40 					cmp $0, 4+%2
41 					je 1f
42 					cmp $0, 4%3
43 					je 1f
44 					movb $1, %1
45 					1:
46 					mov 4+%2, %%eax
47 					mull %3
48 					jno 2f
49 					movb $1, %1
50 					2:
51 					mov %%eax, %%ecx
52 					mov %2, %%eax
53 					mull 4%3
54 					jno 3f
55 					movb $1, %1
56 					3:
57 					add %%eax, %%ecx
58 					jno 4f
59 					movb $1, %1
60 					4:
61 					mov %2, %%eax
62 					mull %3
63 					add %%ecx, %%edx
64 					jnc 5f
65 					movb $1, %1
66 					5:
67 					" : "=&A" lo, "+*m" overflow : "m" x, "m" y : "ecx"; }
68 			else asm { "mul %3\njno 1f\nmovb $1, %1\n1:\n" : "=a" lo, "+*m" overflow : "a" x, "r" y : "rdx"; }
69 			return lo;
70 		}
71 	}
72 }
73 else
74 {
75 	// DMD is already faster than my ASM code above, no need to improve. Good job Walter et al.
76 	import core.checkedint;
77 	alias mulu = core.checkedint.mulu;
78 }