www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to muldiv in D?

reply Kagamin <spam here.lot> writes:
Can't find a function for it.
Nov 21 2016
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/21/2016 11:16 AM, Kagamin wrote:
 Can't find a function for it.
Here is a draft adapted from the following page http://stackoverflow.com/questions/14872499/is-there-an-equivalent-to-muldiv-for-linux This draft works for signed types: T mulDiv(T)(T number, T numerator, T denominator) { static if (is (T == long)) { static assert("Sorry, can't support long"); } else static if (is (T == int)) { alias InterimT = long; } else { alias InterimT = int; } InterimT ret = number; ret *= numerator; ret /= denominator; return cast(T)ret; } void main() { int number = int.max / 2; int numerator = 42; int denominator = numerator * 2; const correctResult = int.max / 4; const wrongResult = number * numerator / denominator; assert(mulDiv(number, numerator, denominator) == correctResult); assert(wrongResult != correctResult); } Ali
Nov 21 2016
parent reply Kagamin <spam here.lot> writes:
Yep, I need muldiv for long values on x86-64.
Nov 22 2016
parent rumbu <rumbu rumbu.ro> writes:
On Tuesday, 22 November 2016 at 08:54:36 UTC, Kagamin wrote:
 Yep, I need muldiv for long values on x86-64.
Quick and dirty assembler: version(D_InlineAsm_X86_64): long muldiv(long a, long b, long c) { //windows RCX, RDX, R8 //linux RDI, RSI, RDX version(Windows) { asm { naked; mov RAX, RCX; //RAX = a imul RDX; //RDX:RAX = a * b idiv R8; //RAX = a * b / c ret; } } else version(linux) { asm { naked; mov RAX, RDI; //RAX = a; mov R8, RDX; //R8 = b imul RSI; //RDX:RAX = a * b idiv R8; //RAX = a * b / c ret; } } else static assert(0); }
Nov 22 2016