Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #135446
| From | peter <peter.noreply@tin.it> |
|---|---|
| Newsgroups | comp.lang.forth |
| Subject | F>R, FR@ and FR> Float to return stack words |
| Date | 2026-08-28 00:04 +0200 |
| Organization | A noiseless patient Spider |
| Message-ID | <20260828000428.00007e53@tin.it> (permalink) |
I recently wanted to adapt compelx-kahan.fs, the complex implementation
by Julian V. Noble and David N. Williams, to the capabilities of
ntf64/lxf64.
One thing I wanted to get away from was the Baden-style float locals,
fa fb .. and to-fa to-fb .. and the use of temporary buffers.
I replaced them with F>R, FR@ and FR>. Moving floats to the return stack.
This works well as both stacks are 64 bits. The effect was very good.
Taking Z* as an example:
Original Z* using 2 temporary buffers
: z* (f: x y u v -- x*u-y*v x*v+y*u)
(
Uses the algorithm followed by jvn:
[x+iy]*[u+iv] = [[x+y]*u - y*[u+v]] + i[[x+y]*u + x*[v-u]]
Requires 3 multiplications and 5 additions.
)
zdup f+ (f: x y u v u+v)
[ fnoname ] literal f! (f: x y u v)
fover f- (f: x y u v-u)
[ fnoname float+ ] literal f! (f: x y u)
frot fdup (f: y u x x)
[ fnoname float+ ] literal f@ (f: y u x x v-u)
f*
[ fnoname float+ ] literal f! (f: y u x)
frot fdup (f: u x y y)
[ fnoname ] literal f@ (f: u x y y u+v)
f*
[ fnoname ] literal f! (f: u x y)
f+ f* fdup (f: u*[x+y] u*[x+y])
[ fnoname ] literal f@ f- (f: u*[x+y] x*u-y*v)
fswap
[ fnoname float+ ] literal f@ (f: x*u-y*v u*[x+y] x*[v-u])
f+ ; (f: x*u-y*v x*v+y*u)
With more or less direct exchange to using the return stack
I got
: z* ( f: x y u v -- x*u-y*v x*v+y*u)
zdup f+ f>r ( f: x y u v r: u+v)
fover f- f>r ( f: x y u r: u+v v-u)
frot fdup fr> ( f: y u x x v-u r: u+v)
f* ( f: y u x x*'v-u' r: u+v)
fr> fswap f>r f>r ( f: y u x r: x*'v-u' u+v)
frot fdup fr> ( f: u x y y u+v r: x*'v-u')
f* f>r ( f: u x y r: x*'v-u' y*'u+v')
f+ f* fdup fr> f- fswap fr> ( f: x*u-y*v u*[x+y] x*[v-u])
f+ ; ( f: x*u-y*v x*v+y*u)
The original give the following assembler code
seea Z*
0x4291A0 C4C17B584D00 vaddsd xmm1, xmm0, qword ptr [r13]
0x4291A6 C5FB110DD2965D00 vmovsd qword ptr [rel 0xA02880], xmm1
0x4291AE C4C17B5C4500 vsubsd xmm0, xmm0, qword ptr [r13]
0x4291B4 C5FB1105CC965D00 vmovsd qword ptr [rel 0xA02888], xmm0
0x4291BC C5FB1005C4965D00 vmovsd xmm0, qword ptr [rel 0xA02888]
0x4291C4 C4C17B594510 vmulsd xmm0, xmm0, qword ptr [r13+0x10]
0x4291CA C5FB1105B6965D00 vmovsd qword ptr [rel 0xA02888], xmm0
0x4291D2 C5FB1005A6965D00 vmovsd xmm0, qword ptr [rel 0xA02880]
0x4291DA C4C17B594508 vmulsd xmm0, xmm0, qword ptr [r13+0x8]
0x4291E0 C5FB110598965D00 vmovsd qword ptr [rel 0xA02880], xmm0
0x4291E8 C4C17B104508 vmovsd xmm0, qword ptr [r13+0x8]
0x4291EE C4C17B584510 vaddsd xmm0, xmm0, qword ptr [r13+0x10]
0x4291F4 C4C17B594500 vmulsd xmm0, xmm0, qword ptr [r13]
0x4291FA C5FB100D7E965D00 vmovsd xmm1, qword ptr [rel 0xA02880]
0x429202 C5FB5CD1 vsubsd xmm2, xmm0, xmm1
0x429206 C5FB100D7A965D00 vmovsd xmm1, qword ptr [rel 0xA02888]
0x42920E C5F358C8 vaddsd xmm1, xmm1, xmm0
0x429212 C5F310C1 vmovsd xmm0, xmm1, xmm1
0x429216 C4C17B115510 vmovsd qword ptr [r13+0x10], xmm2
0x42921C 4D8D6D10 lea r13, [r13+0x10]
0x429220 C3 ret
129 bytes, 21 instructions
ok
There are 3 multiplications, 5 add/sub and 8 loads/stores to the buffer
The revised version gives
seea Z*
0x428A50 C4C17B584D00 vaddsd xmm1, xmm0, qword ptr [r13]
0x428A56 C4C17B5C4500 vsubsd xmm0, xmm0, qword ptr [r13]
0x428A5C C4C17B594510 vmulsd xmm0, xmm0, qword ptr [r13+0x10]
0x428A62 C4C173594D08 vmulsd xmm1, xmm1, qword ptr [r13+0x8]
0x428A68 C4C17B105508 vmovsd xmm2, qword ptr [r13+0x8]
0x428A6E C4C16B585510 vaddsd xmm2, xmm2, qword ptr [r13+0x10]
0x428A74 C4C16B595500 vmulsd xmm2, xmm2, qword ptr [r13]
0x428A7A C5EB5CD9 vsubsd xmm3, xmm2, xmm1
0x428A7E C5FB58C2 vaddsd xmm0, xmm0, xmm2
0x428A82 C4C17B115D10 vmovsd qword ptr [r13+0x10], xmm3
0x428A88 4D8D6D10 lea r13, [r13+0x10]
0x428A8C C3 ret
61 bytes, 12 instructions
ok
Half the size and all memory loads/stores gone.
With the returns stack use I can also do things like
: +ulp f>r r> 1+ >r fr> ; ok
0e +ulp e. 5e-324 ok
0e +ulp fh. 0x0.0000000000001p-1022 ok
seea +ulp
0x42A260 C4E1F97EC0 vmovq rax, xmm0
0x42A265 48FFC0 inc rax
0x42A268 C4E1F96EC0 vmovq xmm0, rax
0x42A26D C3 ret
14 bytes, 4 instructions
ok
An alternative I considered was to introduce float locals. It would probably
have been more complicated. The result, in the best case, would be equal in
the generated code. The problem with locals is the scope, that is to the end
of the word. Of course the source would be more readable!
I might still implement float locals.
What do you have in your system?
BR
Peter
Back to comp.lang.forth | Previous | Next — Next in thread | Find similar | Unroll thread
F>R, FR@ and FR> Float to return stack words peter <peter.noreply@tin.it> - 2026-08-28 00:04 +0200
Re: F>R, FR@ and FR> Float to return stack words dxf <dxforth@gmail.com> - 2026-08-28 14:44 +1000
Re: F>R, FR@ and FR> Float to return stack words anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-08-28 06:50 +0000
Re: F>R, FR@ and FR> Float to return stack words marcel hendrix <mhx@iae.nl> - 2026-08-28 19:35 +0200
Re: F>R, FR@ and FR> Float to return stack words peter <peter.noreply@tin.it> - 2026-08-30 10:06 +0200
Re: F>R, FR@ and FR> Float to return stack words anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-08-30 13:31 +0000
Re: F>R, FR@ and FR> Float to return stack words peter <peter.noreply@tin.it> - 2026-08-30 15:58 +0200
Re: F>R, FR@ and FR> Float to return stack words anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-08-30 15:12 +0000
csiph-web