Skip to main content
GameDev.net gamedev.net
🔒 Locked

Simulating LARGE_INTEGER in VB?

Started by Promit Jun 15, 2002 at 10:12 PM 4 replies 2.5k views
Original Post
Promit
Promit
In order to add High res timing to a VB app, I declared this struct: Public Type LARGE_INTEGER Low As Long High As Long End Type Greater Than/Less than functions were pretty easy to write for it. Can someone show me how to write +/- and * and / operations for it? I could probably figure it out myself, but I''m feeling a bit lazy and don''t want to reinvent the wheel. If you want to provide the functions in C++, that''s fine, jsut dont cheat me and go:
  
LARGE_INTEGER Mul( LARGE_INTEGER a, LARGE_INTEGER b )
{
    return LARGE_INTEGER( (__int64)a * (__int64)b );
}
  
____________________________________________________________ Direct3D vs. OpenGL
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
RoTTer
RoTTer
If speed is not an issue, do it bit-wisely (!?).
If speed is an issue, then I dont know, there must be some methods around...

I dont know VB, but I understood your problem. Not sure if VB supports bitwise operations, but if it does, just add both numbers ("Low" part) bitwisely (do it N times if you want to do a product) and then if there is carry, add 1 to the "High" part, and sum the "High" parts. If there is carry there, then you got to the max of your number, then do whatever you want (set it to zero, dunno).

Cya,
-RoTTer
Shannon Barber
Shannon Barber
quote:
Original post by RoTTer
Not sure if VB supports bitwise operations, but if it does,

Only if +, -, * and / count as bitwise operators (it''s painful in VB).


function Add_VLI(ByRef VLI a, ByRef VLI b) as VLI
Dim result as VLI

result.Low = a.Low + b.Low
result.High = a.High + b.High

if result.Low < a.Low or result.Low < b.Low then
''An overflow occured
result.High = result.High + 1
end if

if result.High < a.High or result.High < b.High then
''A true overflow occured
Raise Crappy_VB_Overflow_Exception
end

end function


All for want of the carry flag (which you can''t even access in any standard C++ nor C).
That code ought to be 2 op codes, add the lower DWORDs, and then adc the higher DWORDs.

I''d like to see an optimizing compiler come up with that!

Magmai Kai Holmlor

"Oh, like you''ve never written buggy code" - Lee

[Look for information | GDNet Start Here | GDNet Search Tool | GDNet FAQ | MSDN RTF[L] | SGI STL Docs | STFW | Asking Smart Questions ]

[Free C++ Libraries | Boost | ACE | Loki | MTL | Blitz++ | wxWindows| Spriit(xBNF)]
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Bad Monkey
Bad Monkey
Just to save you the time and effort, here''s a timer class I wrote a few years ago for VB. Everyone feel free to use/alter/make virgin sacrifices to it:


  
Private Type LargeInteger
LowPart As Long
HighPart As Long
End Type

Private Declare Function QueryPerformanceFrequency Lib "kernel32" (freq As LargeInteger) As Long
Private Declare Function QueryPerformanceCounter Lib "kernel32" (count As LargeInteger) As Long
''--------------------------

Private m_dblLastTime As Double
Private m_lngFreqLow As Long
Private m_lngFreqHigh As Long
Private m_blnSupported As Boolean


Private Sub Class_Initialize()
Dim l_64iBigInt As LargeInteger
Dim l_lngCounterLow As Long, l_lngCounterHigh As Long

m_blnSupported = False

If (QueryPerformanceFrequency(l_64iBigInt)) Then
m_blnSupported = True
m_lngFreqLow = l_64iBigInt.LowPart
m_lngFreqHigh = l_64iBigInt.HighPart

''init time also...
If (QueryPerformanceCounter(l_64iBigInt)) Then
l_lngCounterLow = l_64iBigInt.LowPart
l_lngCounterHigh = l_64iBigInt.HighPart

m_dblLastTime = l_lngCounterLow + (l_lngCounterHigh * (2 ^ 32))
m_dblLastTime = m_dblLastTime / (m_lngFreqLow + (m_lngFreqHigh * (2 ^ 32)))
End If

End If

End Sub

Public Function IsSupported() As Boolean
IsSupported = m_blnSupported
End Function


Public Function GetTime() As Double
Dim l_64iCounter As LargeInteger
Dim l_lngCounterLow As Long, l_lngCounterHigh As Long
Dim l_dblTime As Double
l_dblTime = -1#

If (Not m_blnSupported) Then Exit Function

If (QueryPerformanceCounter(l_64iCounter)) Then
l_lngCounterLow = l_64iCounter.LowPart
l_lngCounterHigh = l_64iCounter.HighPart

l_dblTime = l_lngCounterLow + (l_lngCounterHigh * (2 ^ 32))
l_dblTime = l_dblTime / (m_lngFreqLow + (m_lngFreqHigh * (2 ^ 32)))

''save for later use...
m_dblLastTime = l_dblTime
End If

GetTime = l_dblTime
End Function


Public Function TimeSinceLastQuery() As Double
Dim l_64iCounter As LargeInteger
Dim l_lngCounterLow As Long, l_lngCounterHigh As Long
Dim l_dblTime As Double, l_dblDiff As Double
l_dblDiff = -1#

If (Not m_blnSupported) Then Exit Function

If (QueryPerformanceCounter(l_64iCounter)) Then
l_lngCounterLow = l_64iCounter.LowPart
l_lngCounterHigh = l_64iCounter.HighPart

l_dblTime = l_lngCounterLow + (l_lngCounterHigh * (2 ^ 32))
l_dblTime = l_dblTime / (m_lngFreqLow + (m_lngFreqHigh * (2 ^ 32)))

l_dblDiff = l_dblTime - m_dblLastTime

''save for later use...
m_dblLastTime = l_dblTime

End If

TimeSinceLastQuery = l_dblDiff
End Function
IndirectX
IndirectX
Why not write a C dll that will use __int64''s?
---visit #directxdev on afternet <- not just for directx, despite the name
ragonastick
ragonastick
Bad Monkey - that code there uses a double to store the time. This will stuff things up once the numbers get big as a double is 64bit floating point and a LARGE_INTEGER is 64 bit integer. Since there is not a 1:1 corellation, it will not have enough resolution.

Writing * and / operators is a bit trickier. Not impossible, but, I would like to know if you actually need them.

This code is fine, except you must turn off Integer bounds checking for it to work properly (and compile your code)

function Add_VLI(ByRef VLI a, ByRef VLI b) as VLI
Dim result as VLI
result.Low = a.Low + b.Low
result.High = a.High + b.High

if result.Low < a.Low or result.Low < b.Low then ''An overflow occured
result.High = result.High + 1
end if
if result.High < a.High or result.High < b.High then ''A true overflow occured
Raise Crappy_VB_Overflow_Exception
end if
end function

One more thing - I think I have seen people use the Currency type for these things. This is how it is described:

quote:

Currency variables are stored as 64-bit (8-byte) numbers in an integer format, scaled by 10,000 to give a fixed-point number with 15 digits to the left of the decimal point and 4 digits to the right. This representation provides a range of -922,337,203,685,477.5808 to 922,337,203,685,477.5807. Thetype-declaration character for Currency is the at sign (@).



From that, what you can do is use CopyMemory to copy across a LARGE_INTEGER to a Currency. Then you can add and subtract as normal. For multiplication and division, you need to then scale it also by 10 000 so that the scaling done by VB is cancelled out. Yes, this is inefficient (dividing by 10 000 so you can then multiply by 10 000 as well as a dll call to just copy the data to the currency type), but you might even find it faster than other hacks - speed test them.

Trying is the first step towards failure.
Trying is the first step towards failure.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.