⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmmuldiv.pas

📁 一套及时通讯的原码
💻 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 + -