BBC BASIC integer arithmetic

Discuss all aspects of programming here. From 8-bit through to modern architectures.
User avatar
Rich Talbot-Watkins
Posts: 1339
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BBC BASIC integer arithmetic

Post by Rich Talbot-Watkins » Tue Sep 04, 2018 1:12 pm

Yeah that's a good thing at least. I don't think the wraparound behaviour is at all useful, to be honest, as it just leads to incorrect results. I can't imagine wanting to write code which relied on it.

User avatar
Richard Russell
Posts: 459
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: BBC BASIC integer arithmetic

Post by Richard Russell » Tue Sep 04, 2018 1:16 pm

Rich Talbot-Watkins wrote:
Tue Sep 04, 2018 12:37 pm
Obviously, promoting to a larger type and wrapping integer results are not mutually compatible.
The usage cases for wrapping put forward by Jonathan were:

Code: Select all

A%=A%+1 : REM to be able to scroll through all 32-bit values without error
address2%=address1%+arbitaryintegeroffset : REM to always give address2% as the appropriate offset from address1%
They are not incompatible with promotion to a larger type. Adding or subtracting two arbitrary signed 32-bit integers can give a result anywhere in the range -2^32 to +2^32-1, which is within the range of numbers that can be represented, precisely, by a 40-bit float. So if you perform the addition, promote to a float if it overflows, and then assign the result to an integer variable, it would be entirely possible to achieve the desired wrap behaviour simply by truncating the result to 32-bits. I don't do that in my BASICs, but I could.
Last edited by Richard Russell on Tue Sep 04, 2018 1:18 pm, edited 1 time in total.

User avatar
Rich Talbot-Watkins
Posts: 1339
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BBC BASIC integer arithmetic

Post by Rich Talbot-Watkins » Tue Sep 04, 2018 1:29 pm

I guess so. It would make the wrapping behaviour require a conversion to float and back to integer, so not as optimal, but I don't think it's really the common case.

Another justification for the wrapping behaviour might be that the ! operator references the memory contents in exactly the same way as an integer variable, and in this instance the wraparound property makes more sense. There's some signed/unsigned ambiguity in this case too (I always remember disliking how EQUD &80000000 was really a negative value according to BBC BASIC).

User avatar
Richard Russell
Posts: 459
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: BBC BASIC integer arithmetic

Post by Richard Russell » Tue Sep 04, 2018 1:45 pm

BigEd wrote:
Tue Sep 04, 2018 1:05 pm
Integers do seem to wrap with addition, but for multiplication I'm getting 'too big'. This seems good to me.
Hmm, I tried this:

Code: Select all

@%=&A0A
PRINT 2147483640 + 20 : REM prints -2147483636
PRINT 43053*49880 + 20 : REM prints 2147483660
The multiplication does not overflow a 32-bit signed integer, so why is promotion to a float apparently happening here? Surely Acorn's BASIC can't always promote to float on a multiplication, however small the result, because that could have a dramatic speed penalty. So what's going on in this case?

User avatar
Richard Russell
Posts: 459
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: BBC BASIC integer arithmetic

Post by Richard Russell » Tue Sep 04, 2018 2:00 pm

Rich Talbot-Watkins wrote:
Tue Sep 04, 2018 1:29 pm
(I always remember disliking how EQUD &80000000 was really a negative value according to BBC BASIC).
That's simply a case of BBC BASIC supporting only signed 32-bit integers (and interestingly only unsigned 8-bit integers, e.g. ?P%). You need a wider range of data types, such as the full range of unsigned and signed integers that C provides, to avoid it.

It gets complicated in my BASICs which support 64-bit integers (BB4W and BBCSDL) and I've had to introduce a new *HEX command to resolve it:

Code: Select all

      @%=&A0A
      *HEX 32
      PRINT &80000000 : REM prints -2147483648
      *HEX 64
      PRINT &80000000 : REM prints 2147483648
but this is drifting off topic.

dominicbeesley
Posts: 625
Joined: Tue Apr 30, 2013 11:16 am
Contact:

Re: BBC BASIC integer arithmetic

Post by dominicbeesley » Tue Sep 04, 2018 2:23 pm

Richard Russell wrote:
Tue Sep 04, 2018 1:45 pm
BigEd wrote:
Tue Sep 04, 2018 1:05 pm
Integers do seem to wrap with addition, but for multiplication I'm getting 'too big'. This seems good to me.
Hmm, I tried this:

Code: Select all

@%=&A0A
PRINT 2147483640 + 20 : REM prints -2147483636
PRINT 43053*49880 + 20 : REM prints 2147483660
The multiplication does not overflow a 32-bit signed integer, so why is promotion to a float apparently happening here? Surely Acorn's BASIC can't always promote to float on a multiplication, however small the result, because that could have a dramatic speed penalty. So what's going on in this case?
IIRC the promotion to a FP multiply takes place at a lower level. I haven't access to my sources right now but I think it's if the magnitude of either operand is > &7FFF (or something like that, I remember it being complicated but boiling down to something like that). So your second example won't overflow but do an FP multiply.

User avatar
Richard Russell
Posts: 459
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: BBC BASIC integer arithmetic

Post by Richard Russell » Tue Sep 04, 2018 2:47 pm

dominicbeesley wrote:
Tue Sep 04, 2018 2:23 pm
IIRC the promotion to a FP multiply takes place at a lower level. I haven't access to my sources right now but I think it's if the magnitude of either operand is > &7FFF
Interesting. Perhaps their only integer multiplication routine is 16-bits * 16-bits giving a 32-bit result. The price paid, of course, is potentially unnecessarily switching to (slow) floating point calculations for the remainder of the expression.

It triggered me to look at the source code of BBC BASIC (Z80), something I rarely do! My integer multiplication routine is 32-bits * 32-bits giving a full 64-bit result. I then examine the 64-bit result to see if it will fit in a 32-bit signed value and if not I convert it to floating point (without the need to do an FP multiplication at all, of course).

User avatar
Rich Talbot-Watkins
Posts: 1339
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BBC BASIC integer arithmetic

Post by Rich Talbot-Watkins » Tue Sep 04, 2018 2:50 pm

Yes, it coerces to float before the multiply, using a quick and dirty method to guess whether it will overflow an integer multiply (meaning that something like 10000000*2 will go via the floating point route even though it doesn't have to).

Code: Select all

LDY iwa+3
CPY iwa+2
BNE &9F20   ; treat as float
LDA iwa+1
ASL A
TYA
ADC #0
BNE &9F20   ; treat as float
; treat as int operand
It's very clever. For it to take the integer route, it has to be a value between &00000000...&00007FFF or &FFFF8000...&FFFFFFFF - anything else will take the slow path. The integer multiply then works with two signed 16 bit numbers to give a signed 32 bit result, hence the need to preserve the sign in bit 15 of the inputs.

The code which performs this check is so much more compact than it would be if it did a more precise and rigorous check.
Last edited by Rich Talbot-Watkins on Tue Sep 04, 2018 2:58 pm, edited 1 time in total.

User avatar
BigEd
Posts: 2060
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: BBC BASIC integer arithmetic

Post by BigEd » Tue Sep 04, 2018 3:39 pm

Interesting - this certainly shows that they thought about what they were doing. It is a bit fast and loose though, especially against today's expectations. Perhaps at the time the expectation was that anyone writing a substantial or important Basic program would be pretty careful. It's still a bit of a disservice not to document this though. Is there any word at all about hex constants acting differently from decimal? Or small multiplications acting differently from large ones?

User avatar
Rich Talbot-Watkins
Posts: 1339
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BBC BASIC integer arithmetic

Post by Rich Talbot-Watkins » Tue Sep 04, 2018 3:40 pm

Richard Russell wrote:
Tue Sep 04, 2018 2:00 pm
That's simply a case of BBC BASIC supporting only signed 32-bit integers (and interestingly only unsigned 8-bit integers, e.g. ?P%). You need a wider range of data types, such as the full range of unsigned and signed integers that C provides, to avoid it.
Yeah, it occurs to me that the integer wrapping behaviour most probably exists in order to permit some vague notion of unsigned integer representation, even if BASIC itself doesn't admit it. It'd be annoying if you had !A%=&7FFFFFFF and weren't allowed to write !A%=!A%+1 even though a machine code routine was viewing !A% as an unsigned 32-bit value.

I think the ? operator is consistent in viewing its domain as unsigned, as BASIC just treats it as an integer (hence the BASIC 2 bug which corrupted the stack when passing PROC parameters with the ? operator).

User avatar
Rich Talbot-Watkins
Posts: 1339
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BBC BASIC integer arithmetic

Post by Rich Talbot-Watkins » Tue Sep 04, 2018 3:44 pm

BigEd wrote:
Tue Sep 04, 2018 3:39 pm
Interesting - this certainly shows that they thought about what they were doing. It is a bit fast and loose though, especially against today's expectations. Perhaps at the time the expectation was that anyone writing a substantial or important Basic program would be pretty careful. It's still a bit of a disservice not to document this though. Is there any word at all about hex constants acting differently from decimal? Or small multiplications acting differently from large ones?
Honestly, the BASIC code is so clever and well-written, full of little tricks like this to improve performance (perhaps at the expense of rigour).

I think the only time a hex constant will act differently to its decimal equivalent is &80000000 / -2147483648, as already mentioned. Multiplications will always be performed as (and return) integers if the operands are integers between -32768 and 32767. It shouldn't make a difference how the literal is written in this case.

User avatar
Richard Russell
Posts: 459
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: BBC BASIC integer arithmetic

Post by Richard Russell » Tue Sep 04, 2018 3:46 pm

Rich Talbot-Watkins wrote:
Tue Sep 04, 2018 2:50 pm
It's very clever.
Having only a 16-bit integer multiply routine seems a significant limitation to me. As I explained, BBC BASIC (Z80) performs a full multiplication of two 32 bit numbers to give a 64-bit result. It never has to resort to a floating-point multiplication at all if both inputs are integers; either the result is usable directly as a 32-bit integer, if it is in range, or it gets normalised to a float by a simple shift-right (and increment the exponent) loop.

User avatar
Richard Russell
Posts: 459
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: BBC BASIC integer arithmetic

Post by Richard Russell » Tue Sep 04, 2018 3:53 pm

Rich Talbot-Watkins wrote:
Tue Sep 04, 2018 3:44 pm
Honestly, the BASIC code is so clever and well-written, full of little tricks like this to improve performance (perhaps at the expense of rigour).
Acorn's BASICs are fast, I'll give you that, but if the price paid for that speed is the sort of anomaly discussed in this thread I'm afraid I'll have to part company with you over "well-written". :evil:

User avatar
Rich Talbot-Watkins
Posts: 1339
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BBC BASIC integer arithmetic

Post by Rich Talbot-Watkins » Tue Sep 04, 2018 4:01 pm

Richard Russell wrote:
Tue Sep 04, 2018 3:46 pm
Rich Talbot-Watkins wrote:
Tue Sep 04, 2018 2:50 pm
It's very clever.
Having only a 16-bit integer multiply routine seems a significant limitation to me. As I explained, BBC BASIC (Z80) performs a full multiplication of two 32 bit numbers to give a 64-bit result. It never has to resort to a floating-point multiplication at all if both inputs are integers; either the result is usable directly as a 32-bit integer, if it is in range, or it gets normalised to a float by a simple shift-right (and increment the exponent) loop.
I don't think it's a limitation if the floating point version can still give precise results across the whole integer domain, albeit more slowly. It's a trade off. I think it's quite likely that most integer multiplies (I'm going to dare to suggest maybe over 90% of them) are going to be with two values less than 32768. In which case, it's worth providing an optimised routine which can do this in a quarter of the time that a 32*32=64-bit routine would do it. BBC BASIC is fast because it performed loads of little tricks like this.

Z80 performs 16-bit arithmetic much more quickly, and possibly it was worth a full 32-bit multiply routine in this case. But the complexity is still quadratic, so it'd still be four times faster to do a 16-bit multiply instead, which I still maintain is worthwhile if that's the common case.

User avatar
BigEd
Posts: 2060
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: BBC BASIC integer arithmetic

Post by BigEd » Tue Sep 04, 2018 4:09 pm

Isn't a shortcut for smaller arguments an independent choice from the integer wrapping question?

User avatar
Rich Talbot-Watkins
Posts: 1339
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BBC BASIC integer arithmetic

Post by Rich Talbot-Watkins » Tue Sep 04, 2018 4:16 pm

Richard Russell wrote:
Tue Sep 04, 2018 3:53 pm
Acorn's BASICs are fast, I'll give you that, but if the price paid for that speed is the sort of anomaly discussed in this thread I'm afraid I'll have to part company with you over "well-written". :evil:
At this point, I think it's worth contextualising as well. In the early 80s, BASIC was something of a "toy" language which helped people get into programming, and ran on modest platforms. Serious programs which required more accuracy and rigour would more likely turn to Fortran or another such language. I think Sophie made some good choices in her implementation of BBC BASIC, in that it nearly always does what you expect, but there are clearly certain edge cases. On the other hand, it absolutely flew for a 1981 home computer, which I think is more important.

These days, PCs are more powerful and the priority should be on ensuring that a language delivers a precise specification over implementation shortcuts for performance. I'm sure your BBFW is used by all sorts of people for demanding tasks these days (in fact did you use it for your PAL colour recovery stuff?).

User avatar
Rich Talbot-Watkins
Posts: 1339
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BBC BASIC integer arithmetic

Post by Rich Talbot-Watkins » Tue Sep 04, 2018 4:16 pm

BigEd wrote:
Tue Sep 04, 2018 4:09 pm
Isn't a shortcut for smaller arguments an independent choice from the integer wrapping question?
Yes, it is!

User avatar
Rich Talbot-Watkins
Posts: 1339
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BBC BASIC integer arithmetic

Post by Rich Talbot-Watkins » Tue Sep 04, 2018 4:31 pm

Rich Talbot-Watkins wrote:
Tue Sep 04, 2018 4:16 pm
(in fact did you use it for your PAL colour recovery stuff?).
In one of those weird coincidence things, I can answer my own question, because this video just popped up on my Facebook feed, confirming that you did indeed use BBC BASIC to do it. Amazing work =D>

User avatar
Richard Russell
Posts: 459
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: BBC BASIC integer arithmetic

Post by Richard Russell » Tue Sep 04, 2018 4:35 pm

Rich Talbot-Watkins wrote:
Tue Sep 04, 2018 4:16 pm
In the early 80s, BASIC was something of a "toy" language which helped people get into programming, and ran on modest platforms.
Putting my 1981 BBC hat on, it was one of the principal objectives of BBC BASIC to break this mould! The aim was to achieve a language which was both suitable for the complete beginner and that had the "accuracy and rigour" for 'serious' programs. I think the BBC and Acorn, in collaboration, largely achieved that objective and some of Sophie's more wacky early ideas (which might well have made BBC BASIC even faster!) were vetoed. The 'quirks' that we have been discussing were never revealed to the BBC (to be fair we probably never asked, and were better off not knowing!).
I'm sure your BBFW is used by all sorts of people for demanding tasks these days (in fact did you use it for your PAL colour recovery stuff?).
Indeed, and more recently for the 'software' implementation of the BBC's Free-D camera tracking application, which demands real-time performance and reliability suitable for live TV studio production (still used every day I think). But Acorn's BASICs have been used for some pretty impressive and professional tasks too.

User avatar
Rich Talbot-Watkins
Posts: 1339
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: BBC BASIC integer arithmetic

Post by Rich Talbot-Watkins » Tue Sep 04, 2018 4:42 pm

Richard Russell wrote:
Tue Sep 04, 2018 4:35 pm
Putting my 1981 BBC hat on, it was one of the principal objectives of BBC BASIC to break this mould! The aim was to achieve a language which was both suitable for the complete beginner and that had the "accuracy and rigour" for 'serious' programs. I think the BBC and Acorn, in collaboration, largely achieved that objective and some of Sophie's more wacky early ideas (which might well have made BBC BASIC even faster!) were vetoed. The 'quirks' that we have been discussing were never revealed to the BBC (to be fair we probably never asked, and were better off not knowing!).
That's interesting. Curious to know if you remember what sort of things were vetoed. And on that theme, as an insider back then, do you know what led to BBC BASIC eschewing the standard PEEK and POKE in favour of its fantastic indirection operators? Was that Acorn's or the BBC's idea? In fact, how much input did the BBC have in shaping the syntax and features of BBC BASIC?

User avatar
Richard Russell
Posts: 459
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: BBC BASIC integer arithmetic

Post by Richard Russell » Tue Sep 04, 2018 5:06 pm

Rich Talbot-Watkins wrote:
Tue Sep 04, 2018 4:42 pm
That's interesting. Curious to know if you remember what sort of things were vetoed.
I think in pretty much every case they were features of Atom BASIC that Sophie wanted to retain, but that were sufficiently different from the de-facto 'standard' Microsoft BASIC that they were unacceptable to the BBC. The only ones I specifically remember (not that these would necessarily have impacted on speed) were the use of semicolon rather than colon as the statement delimiter, and PRINT defaulting to not outputting a CRLF unless specifically requested.
And on that theme, as an insider back then, do you know what led to BBC BASIC eschewing the standard PEEK and POKE in favour of its fantastic indirection operators? Was that Acorn's or the BBC's idea?
Definitely Acorn's. Atom BASIC has them (or something similar) doesn't it?
In fact, how much input did the BBC have in shaping the syntax and features of BBC BASIC?
That's been discussed to death before (on this forum, and probably elsewhere) so I'm not inclined to drift that much off-topic. You can read the original BBC Specification, to which Acorn and the other companies asked to tender responded. I suppose the BBC's main contribution, at that early stage at least, was the requirement for a 'structured' BASIC (not requiring GOTO) and 'long' variable names.

User avatar
Richard Russell
Posts: 459
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: BBC BASIC integer arithmetic

Post by Richard Russell » Wed Sep 05, 2018 10:18 pm

BigEd wrote:
Tue Sep 04, 2018 4:09 pm
Isn't a shortcut for smaller arguments an independent choice from the integer wrapping question?
Actually, having thought about it some more, I don't think they are "independent". The major, potential, problem with the way Acorn's expression evaluator works is the possibility of a 32-bit integer 'wrap' happening, silently, part way through a complex expression. In that event, it could give rise to a completely incorrect result without any of the operands (or the expected answer) having a magnitude sufficiently large to alert the programmer to the possibility.

So the question arises: how likely is it for a 'wrap' situation to arise part way through a complex expression? If integer multiplication had worked like mine, i.e. multiplying two integers together did not cause promotion to a float (so long as the result in in range for 32-bits), then the answer is 'quite likely'. An expression like (a * b + c) / d could wrap at the '+ c' stage even if all the variables are relatively small: all it needs is for a * b to give a value close to the 32-bit limit.

But because of the shortcut taken by Acorn in the working of the integer multiply (i.e. that it promotes to float if either of the operands is more than 16 bits magnitude) the likelihood of a wrap is reduced. Now, if a * b gives a value near to the 32-bit limit, either a or b (or both) must be greater than the magnitude that forces promotion to a float, and the wrap doesn't occur!

So, probably through luck rather than design, it seems the 'multiplication' behaviour has the effect of masking the 'wrap' behaviour, and it's quite likely only for this reason that the latter wasn't identified as a serious weakness long ago.
Last edited by Richard Russell on Wed Sep 05, 2018 10:23 pm, edited 1 time in total.

User avatar
BigEd
Posts: 2060
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: BBC BASIC integer arithmetic

Post by BigEd » Thu Sep 06, 2018 3:27 am

Richard Russell wrote:
Wed Sep 05, 2018 10:18 pm
So, probably through luck rather than design, it seems the 'multiplication' behaviour has the effect of masking the 'wrap' behaviour, and it's quite likely only for this reason that the latter wasn't identified as a serious weakness long ago.
An interesting thought!

Post Reply