Surprising indirection behaviour
Comments
-
if (hex) { if (matrixflags.hex64) size = sprintf(basicvars.stringwork, "%*llX", fieldwidth, pop_anynum64()); else size = sprintf(basicvars.stringwork, "%*X", fieldwidth, pop_anynum32()); } else { size = sprintf(basicvars.stringwork, rightfmt, fieldwidth, numdigits, pop_anynumfp()); }
That's the code for printing a number right-justified. The left-justified code just uses a slightly different format string - but it is indeed using 64-bit floats to print a decimal number. It shouldb't be too hard to expand the decimal output to handle ints and floats separately.
Update: Fixed...if (hex) { if (matrixflags.hex64) size = sprintf(basicvars.stringwork, "%*llX", fieldwidth, pop_anynum64()); else size = sprintf(basicvars.stringwork, "%*X", fieldwidth, pop_anynum32()); } else { if (resultype == STACK_FLOAT) size = sprintf(basicvars.stringwork, rightfmt, fieldwidth, numdigits, pop_anynumfp()); else size = sprintf(basicvars.stringwork, "%*lld", fieldwidth, pop_anynum64()); }
1 -
That's the code for printing a number right-justified.
@%=&1090E PRINT PI "here"
The various versions of BBC BASIC I have give:3.14159265E0 here < 6502 BASIC 2 3.14159265E0 here < ARM BASIC 5 3.14159265E0 here < BB4W 3.14159265E0 here < BBCSDL (assembler) 3.14159265E0 here < BBCSDL / BBCTTY (C) 3.14159265E0here < Matrix Brandy
The outlier is Matrix Brandy which right-justifies the '3.14159265E0' in the (14 character width) field, whereas all the others left-justify it. Maybe that was a deliberate decision in the interests of code elegance, but it could result in an incompatibility.
0 -
It's not quite so clear-cut. Also printing 1E18 "here":
Try with a different @%...@%=&1040E 3.142E0here - Matrix Brandy 1.000E18here - Matrix Brandy 3.142E0 here - 6502 BASIC 2 1.000E18 here - 6502 BASIC 2 3.142E0 here - BBCTTY 1.000E18 here - BBCTTY 3.142E0 here - ARM BASIC V 1.000E18 here - ARM BASIC V 3.142E0 here - ARM BASIC VI 1.000E18 here - ARM BASIC VI
Apart from Matrix Brandy which indeed blindly right-justifies the output, the others right-justify the E, and left-justifies the exponent after it. ARM BASIC VI allows an extra space for the exponent as it supports exponents up to 1.7976E308.
Edit: Ugh, my wording is awkward. What I'm trying to say is that it right-justifies enough to have the E line up, with the exponent after it with at least one space of padding, so it's padded both at the start and at the end.0 -
ARM BASIC VI allows an extra space for the exponent as it supports exponents up to 1.7976E308.
- If your principal concern is compatibility with existing programs, format exactly the same way as 6502 BASIC 2 and ARM BASIC 5, and accept that in the rare event of the exponent not fitting (1.e. a negative exponent of -100 or larger) the decimal points will not line up.
- If your principal concern is with new programs written specifically for ARM BASIC VI, make provision for one extra exponent character (so the decimal points line up) but in so doing risk breaking the layout of existing programs because the column width is insufficient.
But this is rather peripheral to the main issue that all versions of BBC BASIC are designed to align the decimal points when numbers are tabulated in E format, except Matrix Brandy which doesn't!
I'd be interested to know what 'upstream Brandy' does, because with its almost obsessive desire to be compatible with ARM BASIC 5 I'd be very surprised if it differed. But on the other hand if it used to pad the exponents correctly, why was that changed in Matrix Brandy?
0 - If your principal concern is compatibility with existing programs, format exactly the same way as 6502 BASIC 2 and ARM BASIC 5, and accept that in the rare event of the exponent not fitting (1.e. a negative exponent of -100 or larger) the decimal points will not line up.
-
Upstream V1.20.1 gives unfiltered output from the C library (and one digit too many), thus:
>@%=&1040E >P.PI "here" 3.1416e+00here >P.1E18 "here" 1.0000e+18here >_
Obviously, some time back I massaged the output to more reflect the BBC BASIC format, but obviously I didn't consider the nuances of justifying the output.0 -
Upstream V1.20.1 gives unfiltered output from the C library
0 -
Perhaps Dave Daniels wasn't particularly fussed about that one. I wouldn't know for sure except for what's in the upstream source.
I've checked in some fixes for this, the formatting justification now follows that of BASIC 1-5, and will eat the last space of padding for a 3-digit exponent, rather than the extra space of padding used by BASIC VI. Integer printing is now more nuanced than above, in that it looks at the resulting length of integer string, and if it's longer than the number of digits allowed by @%, will re-render via a float to produce exponent format. I've also therefore extended the maximum number of digits allowed from 17 to 19, as that's the length of 2^62.0 -
I'm taking another look at this - especially the last nightly build (remember, they are development builds and show a snapshot of the state of play, they're not releases) crashes with a negative 3-digit exponent. I've fixed that issue (not yet checked in), but I've also been thinking about the padding.
Would it be possible to extend @% to handle arbitrary padding - yours needs up to 5 character spaces after the E (considering the - sign), if there are two bits spare somewhere so of those, we could have
00 = 3 (BBC default)
01 = 4 (ARM BASIC VI, useful for Matrix Brandy)
10 = 5 (allow for correct alignment of numbers in BBCSDL/BBCTTY)
11 = 6 (future expansion, when/if 128-bit floats become a thing)
My initial thought is the very top two bits of the top byte (the lowest bit is intended for STR$, the others aren't used - though not sure if Acorn BBC BASIC just looks at the whole of the top byte and if that isn't zero, use @% to format STR$ output. Alternatively bits 5 and 6 4 and 5 of the format byte (as only 0, 1 and 7 are used), and thinking more, I'm leaning towards this.
(Edit: You're using bit 6.)
I thought of doing this via a separate twiddle, but it felt like an outlier as all other print formatting (aside from 64-bit hex) is handled by @%.
I welcome your thoughts on this, even if to say I'm losing what little shred of sanity I might have left0 -
they're not releases
My approach is quite different. The only way to get hold of a development (non-release) build is to build it yourself from the sources at GitHub. The only binaries I make available for download are official releases, and they currently happen roughly every two months.Would it be possible to extend @% to handle arbitrary padding - yours needs up to 5 character spaces after the E (considering the - sign)
The whole Acorn exponent-padding business is a kludge to fit in with BBC BASIC's default right-justification of numbers, which makes sense for F-formatting but not for E-formatting. So I feel uneasy about proliferating, indeed enhancing, a formatting that doesn't really make sense when left-justification is a much simpler and more conventional solution.
If one was to extend @% at all I'd be more inclined to add support for the leading space on positive and zero numbers which is a standard sprintf option.though not sure if Acorn BBC BASIC just looks at the whole of the top byte and if that isn't zero, use @% to format STR$ output.
On balance (and you won't be at all surprised to hear this) I would be pretty content to leave things as they are. If you know the exponent will always fit in a 3-character field use the existing standard right-justification option. If not use left-justification with a trivial piece of code to add a leading space when required:@% = &1090F PRINT STRING$(-(n >= 0), " "); n
0 -
I don't really have a release schedule as such, I know in the early days I was releasing often but then there was so much broken that needed fixing it justified it. Now that it's more stable, releases have significantly slowed. Especially after having been burned a couple of time holding off on a release, then putting one together only to discover a bug (or worse, one being reported) within a day of releasing!
But I get your point, the changeset since 1.22.15 is pretty large, and I should release smaller changes more often. Now that I've transferred the relevant changes to PRINT across to STR$ I think I will be putting together a new release in the next few days, or this weekend, with any luck.1