Re: MI MB: Call dll with a 4Bytes float instead of 8Bytes float?

2000-02-10 Thread Bill Thoen

This is a difficult and messy problem, but I can offer some
ideas. First, there's lots of web pages that explain the details
of floating point numbers. Microsoft has a pretty good one:
http://support.microsoft.com/support/kb/articles/q42/9/80.asp,
but there are many others.

This trick uses the method of fooling the software into placing
floating point bit patterns into an integer and then you access
the bits and bytes of the parts in MapBasic by using integer
division and the mod function. 

So pass your 'Value' variable to your DLL as an MI integer. Since
you are passing it a 4-byte chunk of memory (which is what an
integer is as far as the computer knows), your DLL will
cheerfully accept it and fill it as a 4-byte Single. When it
comes back, you want to convert its bit pattern into an MI float
by interpreting the bits as they are packed in the f.p. format. A
VB Single (an IEEE 32-bit floating point number) has this bit
pattern for its 32 bits:
s  fff 

Here s is the sign (1 = negative),  is the exponent
biased by 127 (so you can have exponents in the range of -126 to
127; -128 and -127 are reserved to indicate special conditions)
and then the last 23 bits are the fractional part of the
mantissa. Also, in IEEE f.p. numbers the highest bit of mantissa
is dropped, and the exponent adjusted accordingly, so in reality
there are 24 bits of mantissa with the high one (which is
implied) always set to 1, and you have to add it back in. So when
your integer returns, the bits need to be taken out into three
numbers; the sign (either -1 or +1), an exponent (a signed value
between -126 and 127) and the mantissa (you can use an MI
integer). Then to construct your float value, add the missing 1
back into the mantissa (which is considered to start with the
decimal point) and the formula is just: sign * (1.mantissa) ^
(exponent - 127).

To break out the bits in an integer, you just use the integer
divide and mod functions like so (assuming n is your integer):

bit0 = (n \ 2^0) mod 2
bit1 = (n \ 2^1) mod 2
bit2 = (n \ 2^2) mod 2
bit3 = (n \ 2^3) mod 2
...
bit31 = (n \ 2^31) mod 2

To build a 32-bit number from bits it's:
n = bit31 * 2^31 + bit30 * 2^30 + ... + bit1 * 2^0 

Here's an example. Say your integer number for Value comes back
as 1097544499. 
in hexadecimal notation that's:
41 6B 33 33

Converting to bits and matching up to IEEE bit format yields:

s  fff 
0 1010 1101011 0011001100110011

So the number will be positive (s = 0), it's exponent is
130-127=3. Prefixing the missing 1 to the high bit place of the
mantissa we have (note the binary decimal point):
1.110101100110011001100110

Raise this to the 3rd power (in binary, you just shift the
decimal point to the right), and arrange the bits into byte
sizes, you get:
1110. 10110011 00110011 0011

converting to decimal, you get 
14. + 179/256 + 51/256^2 + 48/256^3 = 14.7

You can verify this with the following teeny-weeny VB program
(which might give you another hint at a way to convert numbers):

Private Sub Form_Load()
Dim f As Single
Dim i As Long
Me.Show
f = 14.7
Open "c:\tmp\test.bin" For Binary Access Read Write As #1
Put #1, 1, f
Get #1, 1, i
Close #f
Text1 = Str$(i) 'This value is 1097544499
End Sub

- Bill Thoen

Franck Martin wrote:
> 
> In MapBasic I declare the following external function :
> 
> Declare Function getnodevalue Lib "SomeoneDll.dll" (ByVal Index As Integer,
> ByVal Code As Integer, Value As Float) As Integer
> 
> and define the following constant
> 
> Define EN_PRESSURE 7
> 
> when I call the Function with
> 
> myopen = getnodevalue( nodeindex, EN_PRESSURE, pressure)
> 
> It returns wrong values.
> 
> The same code works perfectly in Visual Basic except the dll is declared:
> Declare Function getnodevalue Lib "SomeoneDll.dll" (ByVal Index As Integer,
> ByVal Code As Integer, Value As Single) As Integer
> 
> I suppose that the problem comes from the fact that in MapBasic the type
> "float" is coded with 8 Bytes while a type "Single" is coded in 4 Bytes.
> 
> I do not know how to change the type of the variable Value in Mapinfo to
> pass a 4Bytes coded float.
> 
> Any body knows?
> 
> Please reply directly...
> 
> Franck Martin
> Network and Database Development Officer
> SOPAC South Pacific Applied Geoscience Commission
> Fiji
> E-mail: [EMAIL PROTECTED] 
> Web site: www.sopac.org.fj 
> 
> --
> To unsubscribe from this list, send e-mail to [EMAIL PROTECTED] and put
> "unsubscribe MAPINFO-L" in the message body, or contact [EMAIL PROTECTED]
--
To unsubscribe from this list, send e-mail to [EMAIL PROTECTED] and put
"unsubscribe MAPINFO-L" in the message body, or contact [EMAIL PROTECTED]



MI MB: Call dll with a 4Bytes float instead of 8Bytes float?

2000-02-09 Thread Franck Martin

In MapBasic I declare the following external function :

Declare Function getnodevalue Lib "SomeoneDll.dll" (ByVal Index As Integer,
ByVal Code As Integer, Value As Float) As Integer

and define the following constant

Define EN_PRESSURE 7

when I call the Function with

myopen = getnodevalue( nodeindex, EN_PRESSURE, pressure)

It returns wrong values. 

The same code works perfectly in Visual Basic except the dll is declared:
Declare Function getnodevalue Lib "SomeoneDll.dll" (ByVal Index As Integer,
ByVal Code As Integer, Value As Single) As Integer

I suppose that the problem comes from the fact that in MapBasic the type
"float" is coded with 8 Bytes while a type "Single" is coded in 4 Bytes.

I do not know how to change the type of the variable Value in Mapinfo to
pass a 4Bytes coded float.

Any body knows?

Please reply directly...

Franck Martin
Network and Database Development Officer
SOPAC South Pacific Applied Geoscience Commission
Fiji
E-mail: [EMAIL PROTECTED]  
Web site: www.sopac.org.fj  

--
To unsubscribe from this list, send e-mail to [EMAIL PROTECTED] and put
"unsubscribe MAPINFO-L" in the message body, or contact [EMAIL PROTECTED]