📄 mmmuldiv.pas
字号:
{========================================================================}
{= (c) 1995-98 SwiftSoft Ronald Dittrich =}
{========================================================================}
{= All Rights Reserved =}
{========================================================================}
{= D 01099 Dresden = Fax.: +49 (0)351-8037944 =}
{= Loewenstr.7a = info@swiftsoft.de =}
{========================================================================}
{= Actual versions on http://www.swiftsoft.de/mmtools.html =}
{========================================================================}
{= This code is for reference purposes only and may not be copied or =}
{= distributed in any format electronic or otherwise except one copy =}
{= for backup purposes. =}
{= =}
{= No Delphi Component Kit or Component individually or in a collection=}
{= subclassed or otherwise from the code in this unit, or associated =}
{= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
{= without express permission from SwiftSoft. =}
{= =}
{= For more licence informations please refer to the associated =}
{= HelpFile. =}
{========================================================================}
{= $Date: 16.09.98 - 16:13:29 $ =}
{========================================================================}
Unit MMMulDiv;
{$I COMPILER.INC}
interface
{$IFNDEF DELPHI4}
uses MMUtils;
{$ENDIF}
function MulDiv32(a, b, c: Longint): Longint;
function MulDiv32RN(a, b, c: Longint): Longint;
function MulDivRN(a, b, c: Longint): Longint;
function MulDivRU(a, b, c: Longint): Longint;
function MulDivRD(a, b, c: Longint): Longint;
function DivMod32(Dividend: Longint; Divisor: Word;
Var _Div, _Mod: Word): Word;
function Sal(value: Longint; Shift: Byte): Longint;
function Sar(value: Longint; Shift: Byte): Longint;
function RangeScale(Val, SrcMin, SrcMax, DstMin, DstMax: Longint): Longint;
function RangeScaleRN(Val, SrcMin, SrcMax, DstMin, DstMax: Longint): Longint;
function RangeScaleF(Val, SrcMin, SrcMax, DstMin, DstMax: Double): Double;
{$IFDEF WIN32}
function MulCompare(a,b,c,d: Longint): Boolean;
{$ENDIF}
function MulDiv64(a, b, c: int64): int64;
implementation
{************************************************************************}
{ function MulDiv32(a,b,c: Longint): Longint = (a * b) / c *}
{************************************************************************}
function MulDiv32(a, b, c: Longint): Longint; assembler;
asm
{$IFDEF WIN32}
imul edx
idiv ecx
{$ELSE}
db 66h
mov ax, word ptr a { mov eax, a }
db 66h
mov bx, word ptr b { mov ebx, b }
db 66h
mov cx, word ptr c { mov ecx, c }
db 66h
imul bx { imul ebx }
db 66h
idiv cx { idiv ecx }
db 66h
db 0Fh
db 0A4h
db 0C2h
db 10h { shld edx, eax, 16 }
{$ENDIF}
end;
{************************************************************************}
{ function MulDiv32RN(a,b,c: Longint): Longint = (a * b + c/2) / c *}
{************************************************************************}
function MulDiv32RN(a,b,c: Longint): Longint; assembler;
asm
{$IFDEF WIN32}
imul edx
idiv ecx
xchg eax, edx
push edx
shl eax, 1
cdq
idiv ecx
pop ecx
add eax, ecx
{$ELSE}
db 66h
mov ax, word ptr a { mov eax, a }
db 66h
mov dx, word ptr b { mov edx, b }
db 66h
mov cx, word ptr c { mov ecx, c }
db 66h
imul dx { imul edx }
db 66h
idiv cx { idiv ecx }
db 66h
xchg ax, dx { xchg eax, edx }
db 66h
push dx { push edx }
db 66h
shl ax, 1 { shl eax, 1 }
db 66h
cwd { cdq }
db 66h
idiv cx { idiv ecx }
db 66h
pop cx { pop ecx }
db 66h
add ax, cx { add eax, ecx }
db 66h
db 0Fh
db 0A4h
db 0C2h
db 10h { shld edx, eax, 16 }
{$ENDIF}
end;
{************************************************************************}
{ function MulDivRD(a,b,c: Longint): Longint = (a * b) / c *}
{************************************************************************}
function MulDivRD(a,b,c: Longint): Longint; assembler;
asm
{$IFDEF WIN32}
mul edx
div ecx
{$ELSE}
db 66h
mov ax, word ptr a { mov eax, a }
db 66h
mov bx, word ptr b { mov ebx, b }
db 66h
mov cx, word ptr c { mov ecx, c }
db 66h
mul bx { mul ebx }
db 66h
div cx { div ecx }
db 66h
db 00Fh
db 0A4h
db 0C2h
db 10h { shld edx, eax, 16 }
{$ENDIF}
end;
{************************************************************************}
{ function MulDivRN(a,b,c: Longint): Longint = (a * b + c/2) / c *}
{************************************************************************}
function MulDivRN(a,b,c: Longint): Longint; assembler;
asm
{$IFDEF WIN32}
mul edx
push ecx
shr ecx, 1
add eax, ecx
adc edx, 0
pop ecx
div ecx
{$ELSE}
db 66h
mov ax, word ptr a { mov eax, a }
db 66h
mov bx, word ptr b { mov ebx, b }
db 66h
mov cx, word ptr c { mov ecx, c }
db 66h
mul bx { mul ebx }
db 66h
mov bx, cx { mov ebx,ecx }
db 66h
sar bx, 1 { sar ebx,1 }
db 66h
add ax, bx { add eax,ebx }
db 66h
adc dx, 0 { adc edx,0 }
db 66h
div cx { div ecx }
db 66h
db 0Fh
db 0A4h
db 0C2h
db 10h { shld edx, eax, 16 }
{$ENDIF}
end;
{************************************************************************}
{ function MulDivRU(a,b,c: Longint): Longint = (a * b + c-1) / c *}
{************************************************************************}
function MulDivRU(a,b,c: Longint): Longint; assembler;
asm
{$IFDEF WIN32}
mul edx
dec ecx
add eax, ecx
adc edx, 0
inc ecx
div ecx
{$ELSE}
db 66h
mov ax, word ptr a { mov eax, a }
db 66h
mov bx, word ptr b { mov ebx, b }
db 66h
mov cx, word ptr c { mov ecx, c }
db 66h
mul bx { mul ebx }
db 66h
mov bx, cx { mov ebx,ecx }
db 66h
dec bx { dec ebx }
db 66h
add ax, bx { add eax,ebx }
db 66h
adc dx, 0 { adc edx,0 }
db 66h
div cx { div ecx }
db 66h
db 0Fh
db 0A4h
db 0C2h
db 10h { shld edx, eax, 16 }
{$ENDIF}
end;
{************************************************************************}
{= function DivMod32(a,b,c,d): c := (a / b) d := (a mod b) *) =}
{************************************************************************}
function DivMod32(Dividend: Longint; Divisor: Word;
Var _Div, _Mod: Word): Word; assembler;
asm
{$IFDEF WIN32}
push ebx
mov ebx, edx
mov edx, eax
shr edx, 16
div bx
mov ebx, _Mod
mov [ecx], ax
mov [ebx], dx
pop ebx
{$ELSE}
mov ax, Dividend.Word[0]
mov dx, Dividend.Word[2]
div Divisor
les di, _Div
mov es:[di], ax
les di, _Mod
mov es:[di], dx
{$ENDIF}
end;
function Sal(Value: Longint;Shift: Byte): Longint; assembler;
asm
{$IFDEF WIN32}
mov cl, dl
sal eax, cl
{$ELSE}
db 66h
mov ax, word ptr Value { mov eax, a }
mov cl, Shift
db 66h
sal ax, cl
db 66h
db 0Fh
db 0A4h
db 0C2h
db 10h { shld edx, eax, 16 }
{$ENDIF}
end;
function Sar(Value: Longint; Shift: Byte): Longint; assembler;
asm
{$IFDEF WIN32}
mov cl, dl
sar eax, cl
{$ELSE}
db 66h
mov ax, word ptr Value { mov eax, a }
mov cl, Shift
db 66h
sar ax, cl
db 66h
db 0Fh
db 0A4h
db 0C2h
db 10h { shld edx, eax, 16 }
{$ENDIF}
end;
{ -------------------------------------------------------------------------- }
{ Result := (DstMax*(Val-SrcMin) + DstMin*(SrcMax-Val)) div (SrcMax-SrcMin); }
{ -------------------------------------------------------------------------- }
function RangeScale(Val, SrcMin, SrcMax, DstMin, DstMax : Longint): Longint; assembler;
asm
{$IFDEF WIN32}
push ebx
push edi
mov ebx, ecx
sub ebx, edx { ebx = SrcMax-SrcMin }
sub ecx, eax { ecx = SrcMax-Val }
sub eax, edx { eax = Val-SrcMin }
imul DstMax { edx:eax = first product }
xchg eax, ecx { ecx = low dword, eax = SrcMax-Val }
mov edi, edx { save high dword }
imul DstMin { second multiplication }
add eax, ecx { 64 bit addition }
adc edx, edi
idiv ebx { div (SrcMax-SrcMin) }
pop edi
pop ebx
{$ELSE}
db 66h
mov cx, word ptr SrcMax
db 66h
mov bx, cx
db 66h
sub bx, word ptr SrcMin { ebx = SrcMax-SrcMin }
db 66h
mov ax, word ptr Val { eax = Val }
db 66h
sub cx, ax { ecx = SrcMax-Val }
db 66h
sub ax, word ptr SrcMin { eax = Val-SrcMin }
db 66h
imul word ptr DstMax { edx:eax = first product }
db 66h
xchg ax, cx { ecx = low dword, eax = SrcMax-Val }
db 66h
mov di, dx { save high dword }
db 66h
imul word ptr DstMin { second multiplication }
db 66h
add ax, cx { 64 bit addition }
db 66h
adc dx, di
db 66h
idiv bx { div (SrcMax-SrcMin) }
db 66h
db 0Fh
db 0A4h
db 0C2h
db 10h { shld edx, eax, 16 }
{$ENDIF}
end;
{ -------------------------------------------------------------------------- }
{ Result := (DstMax*(Val-SrcMin) + DstMin*(SrcMax-Val)) div (SrcMax-SrcMin); }
{ -------------------------------------------------------------------------- }
function RangeScaleRN(Val, SrcMin, SrcMax, DstMin, DstMax: Longint): Longint;
var
ValF: Double;
begin
ValF := Val;
Result := Round((DstMax*(ValF-SrcMin) + DstMin*(SrcMax-ValF)) / (SrcMax-SrcMin));
end;
{ -------------------------------------------------------------------------- }
{ Result := (DstMax*(Val-SrcMin) + DstMin*(SrcMax-Val)) div (SrcMax-SrcMin); }
{ -------------------------------------------------------------------------- }
function RangeScaleF(Val, SrcMin, SrcMax, DstMin, DstMax: Double): Double;
begin
Result := (DstMax*(Val-SrcMin) + DstMin*(SrcMax-Val)) / (SrcMax-SrcMin);
end;
{$IFDEF WIN32}
{ -------------------------------------------------------------------------- }
function MulCompare(a,b,c,d: Longint): Boolean;
var
R: Boolean;
begin
asm
mov eax, a
mov edx, b
imul edx
push eax
push edx
mov eax, c
mov edx, d
imul edx
pop ecx
xor ecx, edx
jnz @@exit
pop ecx
xor ecx, eax
jnz @@exit
mov R, True
jmp @@exit2
@@exit:
mov R, False
@@exit2:
end;
Result := R;
end;
{$ENDIF}
{-------------------------------------------------------------------------- }
function MulDiv64(a, b, c: int64): int64;
{$IFDEF DELPHI4}
var
temp: extended;
begin
temp := a;
Result := Trunc((temp*b)/c);
{$ELSE}
begin
Result := (a*b)/c;
{$ENDIF}
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -