dcsimg
Results 1 to 6 of 6

Thread: VB6 - Fast Inverse Sqrt

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    443

    Question VB6 - Fast Inverse Sqrt

    a=1/Sqr(b) is an high time consuming operation.
    This function is intensively used in vector operation, such normalization:
    eg: D=sqr(dx*dx+dy*dy) , dx=dx/d , dy=dy/d


    In C and other languages there's a technique to do this opertation in a fast way called

    fast inverse square root

    Look here and here.
    Code:
    float InvSqrt(float x)
    {
      float xhalf = 0.5f*x;
      int i = *(int*)&x; // get bits for floating value
      i = 0x5f375a86- (i>>1); // gives initial guess y0
      x = *(float*)&i; // convert bits back to float
      x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
      return x;
    }
    Code:
    public static float invSqrt(float x) {
        float xhalf = 0.5f*x;
        int i = Float.floatToIntBits(x);
        i = 0x5f3759df - (i>>1);
        x = Float.intBitsToFloat(i);
        x = x*(1.5f - xhalf*x*x);
        return x;
    }
    Don't know if it could worth to translate these codes to VB6 and if the new (VB6) InvSqrt function could be faster than
    1/Sqr(b).

    Could someone Help about this?
    (Sorry for my english)

  2. #2

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    443

    Re: VB6 - Fast Inverse Sqrt

    I found Solution:

    Code:
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
    
    
    Public Function InvSQR(number As Single) As Single
    Dim I          As Long
    Dim X2         As Single
    Dim Y          As Single
    Const threehalfs As Single = 1.5
    
        Debug.Print Len(I), Len(Y)
    
        X2 = number * 0.5
        Y = number
    
        CopyMemory I, Y, 4
        I = &H5F3759DF - (I \ 2)
        CopyMemory Y, I, 4
    
        Y = Y * (threehalfs - (X2 * Y * Y))
        InvSQR = Y
    End Function
    (at the moment don't know about speed)

  3. #3
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,057

    Re: VB6 - Fast Inverse Sqrt

    Code:
    Private Declare Sub GetMem4 Lib "msvbvm60.dll" (ByVal Ptr As Long, ByRef RetVal As Any)
    
    Public Function InvSQR(ByVal X As Single) As Single
        Dim I As Long, XHalf As Single
    
        XHalf = 0.5! * X
        GetMem4 VarPtr(X), I
        I = &H5F3759DF - (I * 0.5!)
        GetMem4 VarPtr(I), X
        InvSQR = X * (1.5! - XHalf * X * X)
    End Function
    The API call can be optimized by declaring it in a Type Library. Check out Michel Rutten's Visual Basic 6 Virtual Machine Type Library which contains custom GetMem declares.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    443

    Re: VB6 - Fast Inverse Sqrt

    Thank you very much!

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    443

    Re: VB6 - Fast Inverse Sqrt

    Public Function InvSQR(ByVal X As Single) As Single
    please could you find this function for DOUBLE types:

    Public Function InvSQR(ByVal X As Double) As Double

    thanks

  6. #6
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,057

    Re: VB6 - Fast Inverse Sqrt

    I have no idea if this will work, but you could try replacing GetMem4 with GetMem8 and promoting all the Single values and variables in the function in post #3 to Double. Here is GetMem8's declare:

    Code:
    Private Declare Sub GetMem8 Lib "msvbvm60.dll" (ByVal Ptr As Long, ByRef RetVal As Any)
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width