Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.sys.acorn.programmer > #2042 > unrolled thread
| Started by | Richard Porter <dontusethis@address.uk.invalid> |
|---|---|
| First post | 2012-08-09 18:06 +0100 |
| Last post | 2012-08-13 16:19 +0100 |
| Articles | 11 — 7 participants |
Back to article view | Back to comp.sys.acorn.programmer
Unsigned integer comparison in Basic V Richard Porter <dontusethis@address.uk.invalid> - 2012-08-09 18:06 +0100
Re: Unsigned integer comparison in Basic V Martin Bazley <martin.bazley@blueyonder.co.uk> - 2012-08-09 23:56 +0100
Re: Unsigned integer comparison in Basic V Richard Porter <dontusethis@address.uk.invalid> - 2012-08-10 12:12 +0100
Re: Unsigned integer comparison in Basic V "Ste (news)" <steve@revi11.plus.com> - 2012-08-10 14:10 +0100
Re: Unsigned integer comparison in Basic V Jeremy Nicoll - news posts <jn.nntp.scrap007@wingsandbeaks.org.uk> - 2012-08-10 14:58 +0100
Re: Unsigned integer comparison in Basic V "Ste (news)" <steve@revi11.plus.com> - 2012-08-13 16:14 +0100
Re: Unsigned integer comparison in Basic V Steve Drain <steve@kappa.me.uk> - 2012-08-10 16:11 +0100
Re: Unsigned integer comparison in?Basic V Justin Fletcher <gerph@gerph.org> - 2012-08-10 15:25 +0100
Re: Unsigned integer comparison in Basic V jgh@arcade.demon.co.uk - 2012-08-10 15:49 -0700
Re: Unsigned integer comparison in Basic V Martin Bazley <martin.bazley@blueyonder.co.uk> - 2012-08-11 19:44 +0100
Re: Unsigned integer comparison in Basic V Richard Porter <dontusethis@address.uk.invalid> - 2012-08-13 16:19 +0100
| From | Richard Porter <dontusethis@address.uk.invalid> |
|---|---|
| Date | 2012-08-09 18:06 +0100 |
| Subject | Unsigned integer comparison in Basic V |
| Message-ID | <9d64a2bc52.news@user.minijem.plus.com> |
In the latest update to SiteMatch I needed to compare timestamps which are 40-bit integers held in two words. Unfortunately comparing the bottom word went wrong because it was treated as being signed. As a result I had to write a little function to do an unsigned comparison which involved testing whether each integer was less than zero or not. I was wondering if anyone has a neater solution to this problem, which has no doubt been encountered many times. -- Richard Porter rich@ / www. richardporter.me.uk "You can't have Windows without pains."
[toc] | [next] | [standalone]
| From | Martin Bazley <martin.bazley@blueyonder.co.uk> |
|---|---|
| Date | 2012-08-09 23:56 +0100 |
| Message-ID | <2e75c2bc52.martin@blueyonder.co.uk> |
| In reply to | #2042 |
The following bytes were arranged on 9 Aug 2012 by Richard Porter : > In the latest update to SiteMatch I needed to compare timestamps which > are 40-bit integers held in two words. Unfortunately comparing the > bottom word went wrong because it was treated as being signed. As a > result I had to write a little function to do an unsigned comparison > which involved testing whether each integer was less than zero or not. > > I was wondering if anyone has a neater solution to this problem, which > has no doubt been encountered many times. BASIC doesn't have unsigned integers, and this is extremely annoying. (What, for example, will happen when the file size limit is increased from 2GB to 4GB in the near future?) The way I would probably have done it is with an assembler routine such as the following: codelimit%=64 DIM code% codelimit%-1 FOR pass%=8 TO 10 STEP 2 P%=code%:L%=code%+codelimit% [OPT pass% .unsigned_le% CMP R0,R1 MOV R0,#0 MVNLS R0,#0 MOV PC,R14 .unsigned_lt% CMP R0,R1 MOV R0,#0 MVNLO R0,#0 MOV PC,R14 .unsigned_ge% CMP R0,R1 MOV R0,#0 MVNHS R0,#0 MOV PC,R14 .unsigned_gt% CMP R0,R1 MOV R0,#0 MVNHI R0,#0 MOV PC,R14 ] NEXT ...And then, to make it a bit nicer, you could have veneers like these: DEF FNunsigned_le(A%,B%)=USR(unsigned_le%) DEF FNunsigned_lt(A%,B%)=USR(unsigned_lt%) DEF FNunsigned_ge(A%,B%)=USR(unsigned_ge%) DEF FNunsigned_gt(A%,B%)=USR(unsigned_gt%) So, instead of writing "IF filesize1%<filesize2%", you'd write "IF FNunsigned_lt(filesize1%,filesize2%)". A bit unwieldy, I know, but that's BASIC for you. Generally speaking, mathematical operations with a large number of bits are easier to do in assembler, which has features like unsigned comparisons and the carry flag to help you. By the way, if you want to compare two numbers of more than 32 bits each (such as, say, 40-bit datestamps), you could try the following (completely untested!) extension: .unsigned_lt64% CMP R1,R3 CMPEQ R0,R2 MOV R0,#0 MVNLO R0,#0 MOV PC,R14 DEF FNunsigned_lt64(A%,B%,C%,D%)=USR(unsigned_lt64%) IF FNunsigned_lt64(lowbits1%,highbits1%,lowbits2%,highbits2%)... -- __<^>__ / _ _ \ It is written that Geeks shall inherit the Earth. ( ( |_| ) ) \_> <_/ ======================= Martin Bazley ==========================
[toc] | [prev] | [next] | [standalone]
| From | Richard Porter <dontusethis@address.uk.invalid> |
|---|---|
| Date | 2012-08-10 12:12 +0100 |
| Message-ID | <cfd705bd52.news@user.minijem.plus.com> |
| In reply to | #2044 |
The date being 9 Aug 2012, Martin Bazley <martin.bazley@blueyonder.co.uk> decided to write: > By the way, if you want to compare two numbers of more than 32 bits each > (such as, say, 40-bit datestamps), you could try the following > (completely untested!) extension: > .unsigned_lt64% > CMP R1,R3 > CMPEQ R0,R2 > MOV R0,#0 > MVNLO R0,#0 > MOV PC,R14 > DEF FNunsigned_lt64(A%,B%,C%,D%)=USR(unsigned_lt64%) > IF FNunsigned_lt64(lowbits1%,highbits1%,lowbits2%,highbits2%)... Thanks. Yes, if I'm going to do it in assembler then I might as well do the whole 40-bit comparison in one go. Cheers, -- Richard Porter rich@ / www. richardporter.me.uk "You can't have Windows without pains."
[toc] | [prev] | [next] | [standalone]
| From | "Ste (news)" <steve@revi11.plus.com> |
|---|---|
| Date | 2012-08-10 14:10 +0100 |
| Message-ID | <52bd10a2f3steve@revi11.plus.com> |
| In reply to | #2045 |
In article <cfd705bd52.news@user.minijem.plus.com>,
Richard Porter <dontusethis@address.uk.invalid> wrote:
> Thanks. Yes, if I'm going to do it in assembler then I might as well do
> the whole 40-bit comparison in one go.
Or, with !Routines from www.7thsoftware.co.uk/software.htm
LIBRARY "<Routines$Linker>"
PROC`library("maths.int64")
REM Unsigned 64 bit comparison
CASE SGN FN`ucmp64(lo_t0%,hi_t1%, lo_t1%,hi_t1%) OF
WHEN -1
REM t0 < t1
WHEN +1
REM t0 > t1
OTHERWISE
REM t0 = t1
ENDCASE
where lo_ is the least-significant word (bottom 32 bits) and hi_ the most
significant (top 32 bits).
Ta,
Steve
--
Steve Revill @ Home
Note: All opinions expressed herein are my own.
[toc] | [prev] | [next] | [standalone]
| From | Jeremy Nicoll - news posts <jn.nntp.scrap007@wingsandbeaks.org.uk> |
|---|---|
| Date | 2012-08-10 14:58 +0100 |
| Message-ID | <mpro.m8jlhs007kw0f02oo@wingsandbeaks.org.uk.invalid> |
| In reply to | #2046 |
"Ste (news)" <steve@revi11.plus.com> wrote: > REM Unsigned 64 bit comparison > CASE SGN FN`ucmp64(lo_t0%,hi_t1%, lo_t1%,hi_t1%) OF Should that be hi_t0% ? -- Jeremy C B Nicoll - my opinions are my own. Email sent to my from-address will be deleted. Instead, please reply to newsreplyaaa@wingsandbeaks.org.uk replacing "aaa" by "284".
[toc] | [prev] | [next] | [standalone]
| From | "Ste (news)" <steve@revi11.plus.com> |
|---|---|
| Date | 2012-08-13 16:14 +0100 |
| Message-ID | <52bea7821asteve@revi11.plus.com> |
| In reply to | #2050 |
In article <mpro.m8jlhs007kw0f02oo@wingsandbeaks.org.uk.invalid>, Jeremy Nicoll - news posts <jn.nntp.scrap007@wingsandbeaks.org.uk> wrote: > "Ste (news)" <steve@revi11.plus.com> wrote: > > REM Unsigned 64 bit comparison > > CASE SGN FN`ucmp64(lo_t0%,hi_t1%, lo_t1%,hi_t1%) OF > > Should that be hi_t0% ? Yes. It wouldn't be usenet if I'd got my example right... ;) Steve -- Steve Revill @ Home Note: All opinions expressed herein are my own.
[toc] | [prev] | [next] | [standalone]
| From | Steve Drain <steve@kappa.me.uk> |
|---|---|
| Date | 2012-08-10 16:11 +0100 |
| Message-ID | <Rx9Vr.738315$gC5.518647@fx10.am4> |
| In reply to | #2046 |
Ste (news) wrote: > Richard Porter wrote: >> Thanks. Yes, if I'm going to do it in assembler then I might as well do >> the whole 40-bit comparison in one go. > Or, with !Routines from www.7thsoftware.co.uk/software.htm I did announce a long integer library back in December: http://www.kappa.me.uk/longs.htm This creates long integers using normal integer variables and can do most operations on them, including comparisons. The functionality will eventually get included in Basalt, but it might be worth a look. Steve
[toc] | [prev] | [next] | [standalone]
| From | Justin Fletcher <gerph@gerph.org> |
|---|---|
| Date | 2012-08-10 15:25 +0100 |
| Subject | Re: Unsigned integer comparison in?Basic V |
| Message-ID | <alpine.DEB.1.10.1208101436530.6010@buttercup.gerph.org> |
| In reply to | #2045 |
On Fri, 10 Aug 2012, Richard Porter wrote:
> The date being 9 Aug 2012, Martin Bazley
> <martin.bazley@blueyonder.co.uk> decided to write:
>
>> By the way, if you want to compare two numbers of more than 32 bits each
>> (such as, say, 40-bit datestamps), you could try the following
>> (completely untested!) extension:
>
>> .unsigned_lt64%
>> CMP R1,R3
>> CMPEQ R0,R2
>> MOV R0,#0
>> MVNLO R0,#0
>> MOV PC,R14
>
>> DEF FNunsigned_lt64(A%,B%,C%,D%)=USR(unsigned_lt64%)
>
>> IF FNunsigned_lt64(lowbits1%,highbits1%,lowbits2%,highbits2%)...
>
> Thanks. Yes, if I'm going to do it in assembler then I might as well
> do the whole 40-bit comparison in one go.
But not like that - that function may return with VS and would therefore
trigger an error.
Personaly, I'd not be passing the values around in pairs of integers, but
as pointers to a block of memory that contained them, as that's easier
to manipulate. And then you can avoid using assembler at all. Dropping to
assembler to solve a problem is probably only sensible once you've got a
working algorithm already - it's a form of premature optimisation to
start writing assembler when you don't need to:
REM Compare two 40bit values, little endian.
REM v1p% pointer to first of 5 bytes in value
REM v2p% pointer to second of 5 bytes in value
REM returns -ve if v1p% < v2p%
REM +ve if v1p% > v2p%
REM 0 if v1p% = v2p%
DEF FNcompare40bit(v1p%, v2p%)
LOCAL o%
o%=v1p%?4 - v2p%?4:IF o%<>0 THEN=o%
o%=v1p%?3 - v2p%?3:IF o%<>0 THEN=o%
o%=v1p%?2 - v2p%?2:IF o%<>0 THEN=o%
o%=v1p%?1 - v2p%?1:IF o%<>0 THEN=o%
o%=v1p%?0 - v2p%?0
=o%
It might not be as fast, but it's easy to read and debug.
And has the bonus of not requiring any understanding of BASIC or the
calling conventions for assembler routines, at the expense of using
indirection operators - they're not that hard though.
--
Gerph <http://gerph.org/>
... I was confused, and I live it all out to find
That I'm not the only person with these things in mind
[toc] | [prev] | [next] | [standalone]
| From | jgh@arcade.demon.co.uk |
|---|---|
| Date | 2012-08-10 15:49 -0700 |
| Message-ID | <32103cbc-f143-4d45-8204-3f0de6ee1616@googlegroups.com> |
| In reply to | #2044 |
Martin Bazley wrote: > By the way, if you want to compare two numbers of more than 32 bits each > (such as, say, 40-bit datestamps), you could try the following > (completely untested!) extension: As they're 40-bit they're going to be in memory anyway, so just deal with them in memory (untested): int40a%=address of 40-bit integer A int40b%=address of 40-bit integer B DEFFNcmp40(int40a%, int40b%) IF int40a%!1 > int40b%!1 THEN =1 IF int40a%!1 = int40b%!1 THEN IF int40a%?0 = int40b%?0 THEN =0 =-1 Similarly for any other size of integer DEFFNcmp64(int64a%, int64b%) IF int64a%!4 > int64b%!4 THEN =1 IF int64a%!4 = int64b%!4 THEN IF int64a%!0 = int64b%!0 THEN =0 =-1 JGH
[toc] | [prev] | [next] | [standalone]
| From | Martin Bazley <martin.bazley@blueyonder.co.uk> |
|---|---|
| Date | 2012-08-11 19:44 +0100 |
| Message-ID | <c30eb3bd52.martin@blueyonder.co.uk> |
| In reply to | #2062 |
The following bytes were arranged on 10 Aug 2012 by jgh@arcade.demon.co.uk: > Martin Bazley wrote: > > By the way, if you want to compare two numbers of more than 32 bits each > > (such as, say, 40-bit datestamps), you could try the following > > (completely untested!) extension: > > As they're 40-bit they're going to be in memory anyway, so just > deal with them in memory (untested): Not necessarily; the usual case is reading load and exec addresses via OS_File, where the datestamp is returned in two separate registers (one of which also contains the filetype). From a purely academic viewpoint it's faster not to have to save them to memory and then load them back again, although since the OP is using BASIC I don't suppose he's too worried about that. -- __<^>__ "Did you know that polar bears stay white all year round? ...The / _ _ \ white colour makes them less visible to the seals and penguins ( ( |_| ) ) they hunt." - Nelson Thornes AQA-endorsed GCSE science textbook \_> <_/ ======================= Martin Bazley ==========================
[toc] | [prev] | [next] | [standalone]
| From | Richard Porter <dontusethis@address.uk.invalid> |
|---|---|
| Date | 2012-08-13 16:19 +0100 |
| Message-ID | <f4fda7be52.news@user.minijem.plus.com> |
| In reply to | #2062 |
The date being 10 Aug 2012, jgh@arcade.demon.co.uk decided to write: > Martin Bazley wrote: >> By the way, if you want to compare two numbers of more than 32 bits each >> (such as, say, 40-bit datestamps), you could try the following >> (completely untested!) extension: > As they're 40-bit they're going to be in memory anyway, so just > deal with them in memory (untested): > int40a%=address of 40-bit integer A > int40b%=address of 40-bit integer B > DEFFNcmp40(int40a%, int40b%) > IF int40a%!1 > int40b%!1 THEN =1 > IF int40a%!1 = int40b%!1 THEN IF int40a%?0 = int40b%?0 THEN =0 > =-1 I don't think that quite does what I want. I need to return TRUE if 40-bit integer A is greater than 40-bit integer B, otherwise FALSE. If the top bytes are different than they determine the result; if they are equal then it is necessary to compare the bottom 4 bytes which I think should be int40a%!4 and int40b%!4. If only one of the integers is negative (as BASIC sees them) then the result needs to be inverted (the negative one must be the greater), otherwise a straight comparison works. As regards Martin's point, although both stamps came from OS_File in a buffer, at this point they are stored in a 2-dimensional integer array including the file type. Anyway I have decided to stick with the BASIC solution though I was tempted by the libraries 'routines' or 'longs' which I'd forgotten all about. Thanks for the suggestions. -- Richard Porter rich@ / www. richardporter.me.uk "You can't have Windows without pains."
[toc] | [prev] | [standalone]
Back to top | Article view | comp.sys.acorn.programmer
csiph-web