MulDiv
Posted: Wed Aug 28, 2013 3:30 pm
I tried to mimic the MulDiv procedure windows offers since it's not available on OS X.
The only difference is that I used a different error code instead of -1 since -1 can also be a valid result.
Example :
Debug MulDiv(3, 40, 80)
3 * 40 / 80 ==> 2 (1.5 rounded to integer)
The only difference is that I used a different error code instead of -1 since -1 can also be a valid result.
Code: Select all
#MULDIV_ERROR = -2147483648
Procedure MulDiv(Number.l, Numerator.l, Denominator.l)
!mov eax, [p.v_Number]
!mov edx, [p.v_Numerator]
!mov ecx, [p.v_Denominator]
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!push rbx
CompilerElse
!push ebx
CompilerEndIf
; check denominator
!xor ebx, ebx
!test ecx, ecx
!jz mul_div_error; division by zero
!jns mul_div_cont1; positive denominator ?
; no, make denominator positive
!not ebx
!neg ecx
!mul_div_cont1:
; multiply Number and Numerator
!imul edx
!test edx, edx
!jns mul_div_cont2; positive multiply result ?
; no, make multiply result positive
!not ebx
!neg edx
!neg eax
!sbb edx, 0
!mul_div_cont2:
; divide and round
!cmp ecx, edx
!jbe mul_div_error; overflow
!div ecx
!shl edx, 1
!sub edx, ecx
!cmc
!adc eax, 0
!js mul_div_error; overflow
; restore sign to negative if required
!neg ebx
!jz mul_div_cont3
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!neg rax
!mul_div_cont3:
!pop rbx
CompilerElse
!neg eax
!mul_div_cont3:
!pop ebx
CompilerEndIf
ProcedureReturn
!mul_div_error:
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!pop rbx
CompilerElse
!pop ebx
CompilerEndIf
ProcedureReturn #MULDIV_ERROR
EndProcedure
Debug MulDiv(3, 40, 80)
3 * 40 / 80 ==> 2 (1.5 rounded to integer)