MMMulDiv.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:13k
- {========================================================================}
- {= (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.