Surprising indirection behaviour

2»

Comments

  • Soruk
    edited February 3
            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());
            }
    
  • Soruk wrote: »
    That's the code for printing a number right-justified.
    That code is beautifully elegant - much more so than mine - so I looked more closely into why mine is so messy. The reason turns out to be because of the way Acorn does exponent padding. Consider the following code:
    @%=&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.
  • Soruk
    edited February 4
    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.
  • Soruk wrote: »
    ARM BASIC VI allows an extra space for the exponent as it supports exponents up to 1.7976E308.
    There's no 'perfect' solution when you extend the range of exponents beyond E-38 by the introduction of 64-bit doubles. There are two things you might do:
    1. 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.
    2. 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.
    I don't have any strong feeling as to which of these imperfect alternatives is 'better', but on balance I prefer (1) because I always put compatibility with existing programs first. Anyway, since my BASICs support exponents from E−4932 to E4932 I would have to allow yet another character if I adopted option (2). ;)

    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?
  • 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.
  • Soruk wrote: »
    Upstream V1.20.1 gives unfiltered output from the C library
    Wow, that must be an almost unique example of Brandy not being compatible with ARM BASIC; I wonder how that happened? The fact that all my BASICs copy Sophie's in this regard must mean that this particular feature was well-known, although I had subsequently forgotten about it.
  • 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.
  • Soruk
    edited February 5
    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 left :D
  • Soruk wrote: »
    they're not releases
    I know they're not officially 'releases' but the latest release seems to be March 2023 so if one wants anything vaguely up-to-date there isn't any option but to install them. What's your release schedule, is it annual? That seems too infrequent to me.

    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 usual (by which I mean non-Acorn) approach to tabulating E-format numbers is to left justify them, with the proviso that positive numbers and zero have a leading space as a place-holder for the minus sign if required. Indeed sprintf has this as a built-in mode (use a space as the flag character).

    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.
    That's the assumption I make. Although I've never implemented it, ARM BASIC 5 (and I assume Matrix Brandy) supports setting @% to a string value (e.g. @%=&quot;F8.4") so one would also have to consider how any such option was represented in that form.

    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
    
  • 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.