Matrix Brandy BASIC VI for console and SDL1.2: V1.22.11 released

for discussion of bbc basic for windows/sdl, brandy and more
Soruk
Posts: 932
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Soruk »

Richard Russell wrote:
Sat Jun 12, 2021 11:07 pm
Soruk wrote:
Sat Jun 12, 2021 8:00 pm
I may have actually sorted the issue by making it return an int64 instead of double when appropriate.
That would be good, but I'm not convinced. Testing the latest 64-bit Windows build (Git commit 37996cf) I'm getting this:

Code: Select all

      SYS "Brandy_Hex64",1
      PRINT ~23^13
      6FEB266931A75C0
but my BASICs (both 32 and 64-bit versions, which use completely different code) reckon the answer is &6FEB266931A75B7. #-o
Good spot. I've tested on a scientific calculator app on my phone, and it gives the same answer as yours, so somewhere something is going a bit awry. I would have thought an 80-bit float had enough precision for this, but seemingly not.

Back to the drawing board... But not tonight.

Edit: Plot thickens. In Linux I get the ...75B7 response - except on the RasPi where I also get the ...75C0 response. This is making me think that the MinGW powl() is faking it and just using the 64-bit pow() even though MinGW appears to support 80-bit long double. So I definitely need an integer power function that will be used if the inputs are ints and the output is in range (the existing call will give me the ballpark to know this.)
Matrix Brandy BASIC VI (work in progress)
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Richard Russell »

Soruk wrote:
Sat Jun 12, 2021 11:28 pm
I would have thought an 80-bit float had enough precision for this, but seemingly not.
An 80-bit float has a 64-bit mantissa so, yes, it can hold a 64-bit integer with full precision. That means (at least it should, and does in my BASICs) that you can freely convert between 64-bit integer and 80-bit float notation without loss. This won't work in Brandy, but it does in mine when running on an x86 CPU (32 or 64-bit):

Code: Select all

      *HEX 64
      a = 23.0 ^ 13.0
      PRINT ~a
      6FEB266931A75B7
Another simple sum, which better exercises the 64-bit integer range, is 13^17. The correct answer, according to my BASICs, is &780C7372621BD74D but Matrix Brandy is saying &780C7372621BDC00. That's about 53-bits of precision which strongly suggests it's still passing through a 64-bit-double bottleneck. :(
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Richard Russell »

Soruk wrote:
Sat Jun 12, 2021 11:28 pm
This is making me think that the MinGW powl() is faking it and just using the 64-bit pow() even though MinGW appears to support 80-bit long double.
Just seen your edit. That can't be true, because I use powl() too for non-integer values and I'm not seeing any loss of precision in Windows (MinGW). For example:

Code: Select all

      @%=&1313
      PRINT PI^PI
      36.46215960720791178
If I force it to truncate the result to a 64-bit double I get 36.46215960720790861 which is significantly less accurate (an online calculator tells me that PI^PI is 36.46215960720791177099...).
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
Soruk
Posts: 932
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Soruk »

Richard Russell wrote:
Sun Jun 13, 2021 12:04 am
Soruk wrote:
Sat Jun 12, 2021 11:28 pm
This is making me think that the MinGW powl() is faking it and just using the 64-bit pow() even though MinGW appears to support 80-bit long double.
Just seen your edit. That can't be true, because I use powl() too for non-integer values and I'm not seeing any loss of precision in Windows (MinGW). For example:

Code: Select all

      @%=&1313
      PRINT PI^PI
      36.46215960720791178
If I force it to truncate the result to a 64-bit double I get 36.46215960720790861 which is significantly less accurate (an online calculator tells me that PI^PI is 36.46215960720791177099...).
I'm now getting thoroughly confused, as my text-mode builds get it right, but my Windows SDL build is getting it wrong - yet there is no code path here that goes anywhere near SDL.

Edit: I've added an integer power function, that will be used if the parameters can be represented exactly as ints (so 23.0 will be recognised as an integer) and the exponent is positive, and if the float80 result is within the range of an int64. Otherwise the float80 result will be returned. Though I'm still mystified as to why powl() seems to be clamped to 64-bit results on the SDL build under Windows, yet the text-mode build gets it right. My only guess is that libSDL-1.2 is overloading the powl() function (or whatever it uses under the lid) with something less desirable. Still, for now, I have it returning the correct answers for all the examples in this thread - including on the Raspberry Pi.
Matrix Brandy BASIC VI (work in progress)
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Richard Russell »

Soruk wrote:
Sun Jun 13, 2021 12:45 am
so 23.0 will be recognised as an integer
Isn't that rather non-standard? In my BASICs (it's also true of Liberty BASIC and I think it's more generally the case, for example in C) adding '.0' is the way of coercing a numeric constant to be a float, so '23' is an integer constant and '23.0' is a float constant. This can be valuable for testing, when you need to force the interpreter to take the float code path, and (in my BASICs at least) it's essential in the SYS statement to force a parameter to be passed as a float rather than an integer.
Though I'm still mystified as to why powl() seems to be clamped to 64-bit results on the SDL build under Windows, yet the text-mode build gets it right.
A 'simple' explanation, but perhaps one you've already ruled out, is that you're not setting the FPU precision bits. My understanding is that specifying a 'long double' type will cause the compiler to emit FPU instructions rather than (say) SSE2 instructions, but it's still your responsibility to ensure that the CPU is appropriately configured for 80-bit precision. If you're not doing that, but relying on the OS to do it for you, it's entirely possible that Windows/SDL is setting your process to 53-bit-mantissa precision but that Linux is setting it to 64-bit-mantissa precision.
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
User avatar
BigEd
Posts: 4234
Joined: Sun Jan 24, 2010 10:24 am
Location: West Country
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by BigEd »

Richard Russell wrote:
Sun Jun 13, 2021 12:04 am
...I use powl() too for non-integer values and I'm not seeing any loss of precision in Windows (MinGW). For example:

Code: Select all

      @%=&1313
      PRINT PI^PI
      36.46215960720791178
If I force it to truncate the result to a 64-bit double I get 36.46215960720790861 which is significantly less accurate (an online calculator tells me that PI^PI is 36.46215960720791177099...).
A highly interesting discussion! And thanks for the integer test cases of 23^13 and 13^17 (both of which should of course come out as odd numbers.) I'm all in favour of using square-and-multiply for exact results in integer powers.

Just a note of caution though, quite possibly already well-understood by those in this conversation. pi^pi from an arbitrary precision calculation is one thing, but the 64 bit precision answer from pi64 ^ pi64, where pi64 is the slightly different number that's pi in 64 bits of precision, is a slightly different number.

That is, if I've done this right,

Code: Select all

        pi^pi ≈ 36.46215960720791177099...
    pi64^pi64 ≈ 36.46215960720791177491... 
which agrees with all but the final digit in the MinGW example.

I don't have a great way to do these sums, but I did find this page which I set to 99 digits and used this expression for pi64:

Code: Select all

    	((0.5+floor((4*atan(1)) * 2^61))/2^61)
which is, I think, the right number. I'd like to be more sure.
(pi as a long double is apparently 3.1415926535897932385128089594...)
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Richard Russell »

BigEd wrote:
Sun Jun 13, 2021 12:29 pm
Just a note of caution though, quite possibly already well-understood by those in this conversation. pi^pi from an arbitrary precision calculation is one thing, but the 64 bit precision answer from pi64 ^ pi64, where pi64 is the slightly different number that's pi in 64 bits of precision, is a slightly different number.
I was aware that there are (at least) four different calculations that you can do in BBC BASIC, if it supports both 64-bit and 80-bit floats:

Code: Select all

      @% = &1313
      pi64# = PI

      result1# = pi64# ^ pi64#
      PRINT result1#
      36.4621596072079015
      
      result2 = pi64# ^ pi64#
      PRINT result2
      36.46215960720790219
      
      result3# = PI ^ PI
      PRINT result3#
      36.46215960720790861
      
      result4 = PI ^ PI
      PRINT result4
      36.46215960720791177
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
Soruk
Posts: 932
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Soruk »

Richard Russell wrote:
Sun Jun 13, 2021 10:28 am
Soruk wrote:
Sun Jun 13, 2021 12:45 am
so 23.0 will be recognised as an integer
Isn't that rather non-standard? In my BASICs (it's also true of Liberty BASIC and I think it's more generally the case, for example in C) adding '.0' is the way of coercing a numeric constant to be a float, so '23' is an integer constant and '23.0' is a float constant. This can be valuable for testing, when you need to force the interpreter to take the float code path, and (in my BASICs at least) it's essential in the SYS statement to force a parameter to be passed as a float rather than an integer.
It is likely non-standard, but the code path has been that all calls to the power capability are loaded as float64s as pow() (and powl()) only take floating point parameters. Therefore to choose an optimised integer path to sidestep inaccuracies on Windows/SDL and RasPi it will use an integer calculator if the parameters can be properly represented as integers and the result will be in range (using powl() to get a ballpark figure).
Though I'm still mystified as to why powl() seems to be clamped to 64-bit results on the SDL build under Windows, yet the text-mode build gets it right.
A 'simple' explanation, but perhaps one you've already ruled out, is that you're not setting the FPU precision bits. My understanding is that specifying a 'long double' type will cause the compiler to emit FPU instructions rather than (say) SSE2 instructions, but it's still your responsibility to ensure that the CPU is appropriately configured for 80-bit precision. If you're not doing that, but relying on the OS to do it for you, it's entirely possible that Windows/SDL is setting your process to 53-bit-mantissa precision but that Linux is setting it to 64-bit-mantissa precision.
It's more baffling than that. Windows/console gets it right, Windows/SDL doesn't!
Matrix Brandy BASIC VI (work in progress)
User avatar
BigEd
Posts: 4234
Joined: Sun Jan 24, 2010 10:24 am
Location: West Country
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.10 released

Post by BigEd »

There are lots of nooks and crannies in the x87. This post talks about Direct 3D changing per-thread settings in a way which affects internal rounding. It's one of a series of technically good posts, but with a little too much spicy attitude for my liking.
D3D9 has a habit of setting the x87 FPU to _PC_24 precision unless you specify D3DCREATE_FPU_PRESERVE. This means that on the thread where you initialized D3D9 you should expect many of your calculations to give different results than on other threads.
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Richard Russell »

Soruk wrote:
Sun Jun 13, 2021 2:17 pm
It's more baffling than that. Windows/console gets it right, Windows/SDL doesn't!
BigEd wrote:
Sun Jun 13, 2021 2:31 pm
There are lots of nooks and crannies in the x87. This post talks about Direct 3D changing per-thread settings
Aren't you both making rather a meal of this? Yes, it's true that you cannot rely on Windows/SDL/Direct3D etc. setting the precision bits how you want them, or leaving them alone after you've set them, so don't! Set them explicitly to the required state before you do any 'long double' calculations. This is how my BASICs have worked ever since I started using 80-bit floats, and I've never noticed any anomalies.
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
Soruk
Posts: 932
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Soruk »

Richard Russell wrote:
Sun Jun 13, 2021 2:48 pm
Soruk wrote:
Sun Jun 13, 2021 2:17 pm
It's more baffling than that. Windows/console gets it right, Windows/SDL doesn't!
BigEd wrote:
Sun Jun 13, 2021 2:31 pm
There are lots of nooks and crannies in the x87. This post talks about Direct 3D changing per-thread settings
Aren't you both making rather a meal of this? Yes, it's true that you cannot rely on Windows/SDL/Direct3D etc. setting the precision bits how you want them, or leaving them alone after you've set them, so don't! Set them explicitly to the required state before you do any 'long double' calculations. This is how my BASICs have worked ever since I started using 80-bit floats, and I've never noticed any anomalies.
I wasn't even aware you could change them, let alone how... #-o
Matrix Brandy BASIC VI (work in progress)
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Richard Russell »

Soruk wrote:
Sun Jun 13, 2021 2:17 pm
Therefore to choose an optimised integer path to sidestep inaccuracies on Windows/SDL and RasPi it will use an integer calculator if the parameters can be properly represented as integers and the result will be in range (using powl() to get a ballpark figure).
But won't that still introduce a 64-bit-double bottleneck in the parameters, making this (pointless, but entirely legal) code fail:

Code: Select all

      SYS "Brandy_Hex64", 1
      a%% = &6789ABCDEF012345
      PRINT ~ a%% ^ 1
I don't see how you can avoid having a 64-bit-integer-clean path both into and out of the raise-to-power operator. Conversion from integer to float in my BASICs happens deep inside the expression evaluator only once it's decided that it's unavoidable.
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Richard Russell »

BigEd wrote:
Sun Jun 13, 2021 12:29 pm
That is, if I've done this right,

Code: Select all

        pi^pi ≈ 36.46215960720791177099...
    pi64^pi64 ≈ 36.46215960720791177491... 
which agrees with all but the final digit in the MinGW example.
I don't think you have done it right. The difference is much greater than that, as I showed in an earlier reply, unless you can convince me that my results are wrong (which might indicate a bug in my BASICs).
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Richard Russell »

Soruk wrote:
Sun Jun 13, 2021 2:51 pm
I wasn't even aware you could change them, let alone how... #-o
I did it from scratch (helped by being an assembly-language programmer at heart, admittedly) but the information is 'out there', for example here.
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
Soruk
Posts: 932
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Soruk »

Richard Russell wrote:
Sun Jun 13, 2021 3:48 pm
Soruk wrote:
Sun Jun 13, 2021 2:51 pm
I wasn't even aware you could change them, let alone how... #-o
I did it from scratch (helped by being an assembly-language programmer at heart, admittedly) but the information is 'out there', for example here.
Thank you, that was extremely helpful.

I've now reworked the code to set this to 0x37F, the power call now pulls from the stack into float80s. As a result, if the parameters are true ints (8, 32, 64) and the floating point result is in range for an int64, it's recalculated using the integer routine so it's accurate on a RasPi. Otherwise, I check if the float80 result is equal to the result cast to int64, if so return it as an int64 else return it cast to a float64.
Matrix Brandy BASIC VI (work in progress)
User avatar
BigEd
Posts: 4234
Joined: Sun Jan 24, 2010 10:24 am
Location: West Country
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.10 released

Post by BigEd »

Sorry Richard, I see I've chosen a poor notation. By pi64 I meant pi with 64 significant bits: what you might prefer to call pi80. So pi64 in your notation is more like a pi53 (or perhaps pi54) in my notation.

Aside from that, I think we're in agreement. I just downloaded the latest console mode BBC Basic to my Intel MacBook, and the results are what we'd both expect:

Code: Select all

>@%=&1313
>PRINT PI^PI
36.46215960720791177
>@%=&1616   
>PRINT PI^PI
36.46215960720791177466
My only remaining puzzlement is that you report getting a very slightly different result with a MinGW build:
Richard Russell wrote:
Sun Jun 13, 2021 12:04 am
... I use powl() too for non-integer values and I'm not seeing any loss of precision in Windows (MinGW). For example:

Code: Select all

      @%=&1313
      PRINT PI^PI
      36.46215960720791178
Soruk
Posts: 932
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Soruk »

Richard Russell wrote:
Sun Jun 13, 2021 3:48 pm
Soruk wrote:
Sun Jun 13, 2021 2:51 pm
I wasn't even aware you could change them, let alone how... #-o
I did it from scratch (helped by being an assembly-language programmer at heart, admittedly) but the information is 'out there', for example here.
I've got it to the point this little test program gives the correct responses on all platforms (except RPi, and on RPi it matches the output of your console build).

Code: Select all

   10 IF INKEY(-256)=77 THEN SYS"Brandy_Hex64",1 ELSE OSCLI"HEX64"
   20 a%% = 2^62
   30 b%% = 2^62 + 512
   40 c%% = 2^62 + 513
   50 PRINT ~a%%: PRINT ~b%%:PRINT ~c%%
   60 PRINT ~23^13
   70 PRINT ~13^17
   80 PRINT ~13.0^17.0
On the RasPi, the last two statements give 780C7372621BD74D and 780C7372621BD800 respectively showing the limitations of running in float64 space.

Edit: Nightly builds updated.
Matrix Brandy BASIC VI (work in progress)
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.10 released

Post by Richard Russell »

BigEd wrote:
Sun Jun 13, 2021 8:16 pm
My only remaining puzzlement is that you report getting a very slightly different result with a MinGW build
Why puzzlement? With completely different code (assembler code written by me in one case, GCC library code in the other) the surprise would probably be as great if they gave identical results! For what it's worth, my code uses the identity:

Code: Select all

x^y = EXP(y * LN(x))
If I compare the two results at the binary level by running this code:

Code: Select all

      x = PI ^ PI
      PRINT ~ !(^x+8) AND &FFFF !(^x+4) !^x
I get these values for my assembler code and powl() respectively:

Code: Select all

      4004  91D9405E  39F5F390
      4004  91D9405E  39F5F393
I don't know which is more accurate; you might be able to tell me.
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Richard Russell »

Soruk wrote:
Sun Jun 13, 2021 9:37 pm
I've got it to the point this little test program gives the correct responses on all platforms
Impressive! In just two days you've updated Matrix Brandy from being inferior to my BASICs in this regard to being superior (my BASICs get the answer wrong in a couple of pathological cases that yours now handles correctly). What's more, you're prepared to issue a new release in just a few hours whilst it takes me up to six weeks to update BBCSDL and a year or more to update BB4W. What a difference being a professional programmer makes, I am truly humbled. :cry:
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
Soruk
Posts: 932
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Soruk »

Richard Russell wrote:
Sun Jun 13, 2021 11:37 pm
Soruk wrote:
Sun Jun 13, 2021 9:37 pm
I've got it to the point this little test program gives the correct responses on all platforms
Impressive! In just two days you've updated Matrix Brandy from being inferior to my BASICs in this regard to being superior (my BASICs get the answer wrong in a couple of pathological cases that yours now handles correctly). What's more, you're prepared to issue a new release in just a few hours whilst it takes me up to six weeks to update BBCSDL and a year or more to update BB4W. What a difference being a professional programmer makes, I am truly humbled. :cry:
I'm not a professional programmer (I'm a systems administrator), and I haven't actually issued a formal release for this at this point (indeed my last actual release was in February), it's only in the nightly builds and the git repository. Also, my nightly builds are quite likely to be based on little tweaks and really should be considered unstable. I guess I just make my development process a bit more visible (my git history shows many mis-steps I make along the way towards what I'm aiming for, and as you know I've made some really bad implementation mistakes along the way) which may give the appearance of frequent releases. You have nothing to feel bad about, your process obviously works for you and you have a robust and solid product as a result.

I disagree with Matrix Brandy giving superior results, as you use float80s for your floating points, I'm using float64s as per Acorn BBC BASIC VI (and Brandy has done before I picked it up, even though it used the BASIC V moniker despite the only difference in the Acorn world is 40 bit vs 64 bit floats).
Matrix Brandy BASIC VI (work in progress)
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Richard Russell »

Soruk wrote:
Mon Jun 14, 2021 12:16 am
I disagree with Matrix Brandy giving superior results, as you use float80s for your floating points, I'm using float64s as per Acorn BBC BASIC VI
I wasn't meaning in terms of precision; 80-bit floats can occasionally be useful. But Brandy's (and BASIC VI's) approach of using nothing better than 64-bit doubles is now being vindicated, since x86 is in the wane and is being replaced by CPUs that provide no hardware support for anything better. Not only that but Microsoft's compilers (e.g. Visual C++) provide no support for 80-bit floats even on x86 CPUs.

So supporting 80-bit floats in my BASIC's has turned out to be a mistake. Not only does it mean that identical programs running on different platforms can give different results, it also has a dramatic effect on performance because numeric values can't be stored or passed in registers internally, but must always go via memory.
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
User avatar
BigEd
Posts: 4234
Joined: Sun Jan 24, 2010 10:24 am
Location: West Country
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.10 released

Post by BigEd »

Thanks Richard
Richard Russell wrote:
Sun Jun 13, 2021 9:56 pm
BigEd wrote:
Sun Jun 13, 2021 8:16 pm
My only remaining puzzlement is that you report getting a very slightly different result with a MinGW build
Why puzzlement? With completely different code (assembler code written by me in one case, GCC library code in the other) the surprise would probably be as great if they gave identical results!
I understand now!


For what it's worth, my code uses the identity:

Code: Select all

x^y = EXP(y * LN(x))
If I compare the two results at the binary level by running this code:

Code: Select all

      x = PI ^ PI
      PRINT ~ !(^x+8) AND &FFFF !(^x+4) !^x
I get these values for my assembler code and powl() respectively:

Code: Select all

      4004  91D9405E  39F5F390
      4004  91D9405E  39F5F393
I don't know which is more accurate; you might be able to tell me.
Using 'bc -l' on the command line, I can set 'obase=16' and 'scale=64' to calculate at more than twice the necessary precision, and then

Code: Select all

p=3.14159265358979323851280895940618620443274267017841339111328125
is the correct value of pi approximated to 64 significant bits:

Code: Select all

p*4
C.90FDAA22168C2350000000000000000000000000000000000000
so we can calculate p^p with e(l(p)*p), or, to see the hex with the alignment we want:

Code: Select all

e(l(p)*p)*4
91.D9405E39F5F39112F914E758A8194A9D11D8C9F6BD1F9D9E1EC92D
which would round to, and is a little bit greater than,

Code: Select all

91.D9405E39F5F391
and that, finally, gives the prize to your assembler code, being just a tiny bit more than 1 ULP adrift. (I think this is expected: whereas simpler operations like sqrt can be within 1 ULP, log and exp are more difficult to get so accurate, and IEEE floating point, and the x87, don't promise to do so.)
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC V for Linux with SDL: V1.21.16 released

Post by Richard Russell »

Richard Russell wrote:
Mon Jun 14, 2021 9:35 am
it also has a dramatic effect on performance because numeric values can't be stored or passed in registers internally, but must always go via memory.
I should add that in my hand-crafted assembler code I do store and pass around 80-bit floats in registers, indeed my code is as far as possible entirely register based (apart from genuinely 'global' variables). But I can do that because I'm not constrained by any ABI requirements (well, strictly I should stick to the ABI to allow debuggers to work, but I ignore that!).

A lot is made of the cleverness of modern compilers in being able to approach the efficiency of an experienced human coder, but they are still constrained by the ABI and if that says a 10-byte object cannot be passed as a parameter, or returned from a function, in registers then no matter how 'clever' the compiler it's not going to be as good as my code. :(
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
Soruk
Posts: 932
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.10 released

Post by Soruk »

Some updates - I've implemented OSWORDs 11 and 12 and SYS "OS_ReadPalette", along with VDU variables 148-152.

I've also rebuilt the Windows nightly builds.
Matrix Brandy BASIC VI (work in progress)
Soruk
Posts: 932
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Matrix Brandy BASIC VI for console and SDL1.2: V1.22.11 released

Post by Soruk »

Hi,

I've released version 1.22.11 of Matrix Brandy BASIC VI, with binary builds for Win32, Win64, RISC OS 26-bit and RISC OS 32-bit.

Changes in this release include:
- System: Mouse position wasn't taking into account change of ORIGIN.
- System: Changes to dlopen, otherwise symbols weren't being recognised.
- System: SYS "Brandy_dlgetaddr" optionally takes a second parameter of a library handle returned by SYS "Brandy_dlopen".
- System: SYS now only operates in 64-bit mode on 64-bit hardware.
- System: Fixed a bug where the keyboard would stop responding after a while in full-screen mode.
- System: Bug fix on new-style MODE call where MODEs 3, 6 and 7 could be matched. It now only matches existing graphics-capable modes, and will construct one (effectively doing *NewMode 126 x y bpp 1 1) if no matches to existing modes are found.
- System: Emulated syscall OS_ReadModeVariable was incorrectly also returning VDU variables. Now only Mode variables are returned, attempts to get any other variable return 0, as they do on RISC OS.
- System: Implemented OSWORDs 11 and 12, and SYS "OS_ReadPalette"
- System: Implemented VDU flags 148-152, so 0-12 and 128-161 are now supported.
- System: Reading VDU variables for TINT was giving incorrect values.
- System: VDU20 wasn't updating the display (unlike VDU19), fixed.
- BASIC: Fixed a bug whereby the OSCLI command might have its parameter trampled on.
- BASIC: On non-RISC OS platforms, increase SYS parameters to 16 to support "Brandy_dlcall" calling symbols which take a lot of parameters.
- BASIC: Power was broken in the upper echelons of 64-bit ints, also conversion to ints was a bit broken for edge cases.
- BASIC: Evaluations now carried out internally with 80-bit floats (where available), cast to 64-bit when returning values to BASIC.

Source and binary downloads are available on the website, with source also at GitHub.
Matrix Brandy BASIC VI (work in progress)
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.11 released

Post by Richard Russell »

I think this has come up before, but since it's been raised again in this thread how difficult would it be to make this work in Matrix Brandy:

Code: Select all

   10 PROCtest(a%())
   20 PRINT DIM(a%(),1)
   30 END
      
   50 DEF PROCtest(RETURN b%())
   60 DIM b%(10)
   70 ENDPROC
In my BASICs the array a%() is successfully DIMmed and the program prints 10, as it should (in my opinion!); but in Matrix Brandy it gives rise to a "Cannot find array a%() at line 10" error. I'm left wondering, therefore, whether it's simply a spurious error message (after all it's perfectly normal for a variable passed as a RETURNed parameter not to exist) and that perhaps it might work with no extra effort if the error wasn't generated.
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
Soruk
Posts: 932
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.11 released

Post by Soruk »

Richard Russell wrote:
Sun Jul 18, 2021 10:29 am
I think this has come up before, but since it's been raised again in this thread how difficult would it be to make this work in Matrix Brandy:

Code: Select all

   10 PROCtest(a%())
   20 PRINT DIM(a%(),1)
   30 END
      
   50 DEF PROCtest(RETURN b%())
   60 DIM b%(10)
   70 ENDPROC
In my BASICs the array a%() is successfully DIMmed and the program prints 10, as it should (in my opinion!); but in Matrix Brandy it gives rise to a "Cannot find array a%() at line 10" error. I'm left wondering, therefore, whether it's simply a spurious error message (after all it's perfectly normal for a variable passed as a RETURNed parameter not to exist) and that perhaps it might work with no extra effort if the error wasn't generated.
I've had a quick look at this, but if I make it skip the error, I get further errors down the road as it's then trying to pass a NULL pointer.

Incidentally, it does not work on the most recent build of BBC BASIC for RISC OS I can run on my virtual RiscPC.
retarr-ro.png
Matrix Brandy BASIC VI (work in progress)
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.11 released

Post by Richard Russell »

Soruk wrote:
Sat Jul 24, 2021 12:38 pm
I've had a quick look at this, but if I make it skip the error, I get further errors down the road as it's then trying to pass a NULL pointer.
It seems that Brandy works rather differently from my BASICs in this regard. In mine, when you pass a RETURNed parameter (whether it be a numeric variable, string variable, array or structure) there is no requirement that it exist prior to the FN/PROC call. That makes sense to me, because if it is declared as RETURNed it might be being used solely to return information from the FN/PROC (it might also be passing information into the FN/PROC but that is optional).

In the case of an array (or structure in my BASICs) that is the difference between an ordinary parameter and a RETURNed parameter. You can pass an array as a regular parameter, and that array can transfer its contents into the FN/PROC or return its contents from the FN/PROC, or both; but either way it must have been DIMensioned before the FN/PROC is called. If you pass it as a RETURNed parameter it need not have been DIMensioned first (but must then be DIMmed inside the FN/PROC).

This capability allows for a situation in which the dimensions of the array are known only inside the FN/PROC, and to implement opaque arrays (and structures) which is a capability any modern language should have.
Incidentally, it does not work on the most recent build of BBC BASIC for RISC OS I can run on my virtual RiscPC.
That was the point made in the other thread which triggered my enquiry. Indeed according to that thread it corrupts the stack! Neither is a good reason for other BBC BASIC implementations to follow suit, especially as it's such a useful feature. :)
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
Soruk
Posts: 932
Joined: Mon Jul 09, 2018 11:31 am
Location: Basingstoke, Hampshire
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.11 released

Post by Soruk »

Richard Russell wrote:
Sat Jul 24, 2021 1:59 pm
Soruk wrote:
Sat Jul 24, 2021 12:38 pm
Incidentally, it does not work on the most recent build of BBC BASIC for RISC OS I can run on my virtual RiscPC.
That was the point made in the other thread which triggered my enquiry. Indeed according to that thread it corrupts the stack! Neither is a good reason for other BBC BASIC implementations to follow suit, especially as it's such a useful feature. :)
Yep, I was reading that, and the ROOL thread too - but that was a slightly different issue of an array seemingly losing its LOCAL-ness after being dimensioned in a sub-procedure (an issue that doesn't arise in Matrix Brandy, instead I get an error that array has already been dimensioned the second time PROCsetup is called when running Stuart Painting's example from 19th July, 3:49pm in the ROOL thread), which does strike me as ever so slightly wrong! Also, that re-dimensioning in a FOR loop differing whether or not the FOR variable is used on the NEXT line.. #-o

PS. You mentioned the latest ARM BBC BASIC you had is 1.19. Here's a zip file of ARM BBC BASIC 1.84 (unpack in your hostfs directory, then inside RPCEmu, do *RMRUN BASIC to replace the ROM BASIC and start it up - but not while BASIC itself is running!). These are extracted from the latest !System released by ROOL for RISC OS 3.x systems, and at least on RISC OS 3.71 have no other module dependencies.
Matrix Brandy BASIC VI (work in progress)
User avatar
Richard Russell
Posts: 2406
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Matrix Brandy BASIC VI for console and SDL1.2: V1.22.11 released

Post by Richard Russell »

Soruk wrote:
Sat Jul 24, 2021 2:24 pm
unpack in your hostfs directory, then inside RPCEmu, do *RMRUN BASIC to replace the ROM BASIC and start it up - but not while BASIC itself is running!).
I only have Red Squirrel, not RPCEmu. Do those instructions apply to Red Squirrel as well?

I'm not up-to-date with RISC OS emulations on PCs. When I last looked, some time ago, Red Squirrel was the only free emulator and even that required obtaining highly dubious (i.e. illegal) copies of ROM images. But since then I think RISC OS has become more 'open' so I don't know whether that means there are now better and more legitimate free emulators available.

It's unusual for me to want to run ARM BASIC. Compatibility with it has never been a high priority for me, and I didn't know until quite recently that there had been any developments since the 1980s. I rather assumed it was in the same state as 6502 BBC BASIC, i.e. with the code so obscure and poorly documented that only Sophie understood it well enough to make changes!
I am suffering from 'cognitive decline' and depression. If you have a comment about the style or tone of this message please report it to the moderators by clicking the exclamation mark icon, rather than complaining on the public forum.
Post Reply

Return to “modern implementations of classic programming languages”