hi, i'm on a late night coding spree again, and i found i had to make a function that turns two values in the byte range to an integer, producing on bit level what would have been the unsigned integer but looks signed to QB. err.. yeah, can't describe it very well right now, but i think you can tell from the code what i mean.
Code:
DEFINT A-Z
FUNCTION word (hibyte, lowbyte)
IF (hibyte AND 128) THEN
word = -(256 * ((128 - hibyte) AND 127)) + lowbyte
ELSE
word = (256 * hibyte) OR lowbyte
END IF
END FUNCTION
That's what my tired brain came up with. Please, if you know a faster way of doing it, post it. I tried another method - POKEing the hibyte - but that's slower, at least on somewhat modern CPUs that can perform those calculations fast. Oh yeah, and I'm talking about PureQB ways of doing it, of course.
Quote:hi, i'm on a late night coding spree again, and i found i had to make a function that turns two values in the byte range to an integer, producing on bit level what would have been the unsigned integer but looks signed to QB. err.. yeah, can't describe it very well right now, but i think you can tell from the code what i mean.
Code:
DEFINT A-Z
FUNCTION word (hibyte, lowbyte)
IF (hibyte AND 128) THEN
word = -(256 * ((128 - hibyte) AND 127)) + lowbyte
ELSE
word = (256 * hibyte) OR lowbyte
END IF
END FUNCTION
That's what my tired brain came up with. Please, if you know a faster way of doing it, post it. I tried another method - POKEing the hibyte - but that's slower, at least on somewhat modern CPUs that can perform those calculations fast. Oh yeah, and I'm talking about PureQB ways of doing it, of course.
Hey...I did something similar some time back. I was turning text strings into arrays of 32-bit integers. eg, I would take the first 4 bytes of the string and use them as the first 32-bit integer in the array...the next 4-bytes would make the second integer...etc.
Code:
SUB passtolongint (a$, passarray&())
DIM textarray(1 TO LEN(a$) \ 4) AS STRING * 4
FOR x = 1 TO LEN(a$) \ 4 'splits a$ into 4 byte chunks
textarray(x) = MID$(a$, 1 + ((x - 1) * 4), 4) 'the (1 + ((x - 1) * 4) is is to make the string posistioner go 1, 5, 9, etc.
NEXT x
FOR p = 1 TO LEN(a$) \ 4 'p is which 4-byte chunk
FOR x = 1 TO 4 'x is which digit
digit$ = MID$(textarray(p), x, 1)
digit = ASC(digit$)
IF x = 1 THEN 'this deals with the fact that the binarys are represented as signed integer (4byte, 32 bit)
IF digit > 127 THEN 'if greater than 128, call it negative and make num smaller than 128
sign = -1
digit = digit - 128
ELSE sign = 1
END IF
END IF
bytevalue& = digit * (256 ^ (4 - x)) 'converts base 256 place
passarray&(p) = passarray&(p) + bytevalue& 'adds base to present value
NEXT x
passarray&(p) = sign * passarray&(p) 'signs the number
NEXT p
END SUB
This code uses some really unfortunate names try substituting the following:
passtolongint stringToLongArray
a$ inputString$
textarray fourBytes
digit$ aByte$
digit aByte
Anyway...I don't think any of this helps you, because we both used basically the same logic...
Looking at your code, it occurs to me...why not change the lines:
IF (hibyte AND 128) THEN
word = -(256 * ((128 - hibyte) AND 127)) + lowbyte
to
IF (hibyte AND 128) THEN
word = (-256 * (hibyte AND 127)) + lowbyte
Not sure if this is faster, but it also works:
Code:
word = CVI(CHR$(lowbyte) + CHR$(hibyte))
This is shorter than the original, and doesn't use strings. But Plasma's is probably faster because there's no IF in his.
[syntax="qbasic"]word = (hiByte * 256& + lowByte) AND &H7FFF&
IF hiByte AND &H80 THEN word = word OR &H8000[/syntax]
Quote:This is shorter than the original, and doesn't use strings. But Plasma's is probably faster because there's no IF in his.
[syntax="qbasic"]word = (hiByte * 256& + lowByte) AND &H7FFF&
IF hiByte AND &H80 THEN word = word OR &H8000[/syntax]
You can rewrite this without if:
[syntax="qbasic"]word = (hiByte * 256& + lowByte) AND &H7FFF&
word = word OR (((hiByte AND &H80) \ (2 ^ 7)) * (2& ^ 15))[/syntax]
Didn't test though
(should work theorethically)
Code:
'
'BYTES to INTEGER
'
lo = I AND &HFF
IF I < 0 THEN
hi = ((I AND &H7F00) \ &H100) + &H80
ELSE
hi=(I AND &H7F00) \ &H100
END IF
'
'
Code:
'
'INTEGER to BYTES
'
IF hi > &H7F THEN
I = lo + (hi - &H100) * &H100
ELSE
I = lo + hi * &H100
END IF
'
'
Those rotuines used a signed integer, but if you need unsigned
integers just convert it.
Very fast, and pure QB
Nemesis
*blink, blink* *justwokeup*
great, thanks guys, i'm gonna speed-test them in a minute!
Edit:
OK.. eww, i found an error in mine, it gives wrong results when hibyte = 128
corrected version:
Code:
FUNCTION word (hibyte, lowbyte)
IF (hibyte AND 128) THEN
IF hibyte = 128 THEN
word = &H8000 OR lowbyte
ELSE
word = -(256 * ((128 - hibyte) AND 127)) + lowbyte
END IF
ELSE
word = (256 * hibyte) OR lowbyte
END IF
END FUNCTION
I used a slightly modified version of Nemesis's for testing:
Code:
FUNCTION word.nemesis (hibyte, lowbyte)
IF (hibyte AND 128) THEN
word.nemesis = lowbyte + (hibyte - 256) * 256
ELSE
word.nemesis = lowbyte + hibyte * 256
END IF
END FUNCTION
The results I got.. *drumroll*
#1 Nemesis
#2 myself
#3 Sterling
#4 Plasma
Those apply to both interpreted and compiled. Oh, and on a Celeron 1GHz. Maybe Plasma's would be faster on a 286, dunno.
Without testing I would've assumed Sterling's method to be faster than mine, but the use of longs apparently drags it down quite a bit.
All routines had to perform exactly the same calculations, and those involved all cases of hibyte (>128, =128, <128). The ranking is based on several runs.
Btw, @Mango: (b AND 127) != ((128 - b) AND 127)
Btw, how about this?
[syntax="qbasic"]
'//////////////////////////////////////////////
'Only do this part once
DIM word AS INTEGER
DEF SEG = VARSEG(word)
offs% = VARPTR(word)
'/////////////////////////////////////////////
'This can be done multiple times
POKE offs%, loByte
POKE offs% + 1, hiByte
'//////////////////////////////////////////////[/syntax]
Should work theorethically and should be really fast (perhaps even faster than anything that's posted here)
Quote:Should work theorethically and should be really fast (perhaps even faster than anything that's posted here)
Argh, I don't feel like running the tests again
I'll just stick with Nemesis's version. Besides, I think for the lowbyte part it would be faster to just write
Like Neo said:
[syntax="qbasic"]
DIM SHARED IntSeg As Integer, IntOffs As Integer
Variable% = 0
IntSeg = VarSeg(Variable%)
IntOffs = VarPtr(Variable%)
addHiLo 1, 1
Print Variable%
addHiLo 0, 1
Print Variable%
SUB addHiLo(hiByte, loByte)
DEF SEG = IntSeg
POKE IntOffs, loByte
POKE IntOffs + 1, hiByte
END SUB[/syntax]