• Re: Average of a [stack]

    From Buzz McCool@21:1/5 to LIT on Wed Jul 10 15:08:59 2024
    On 6/7/2024 1:32 PM, LIT wrote:
    : AVG  DEPTH 0 SWAP DUP >R 0 DO SWAP + LOOP R> / . ;

    I coincidentally was doing averaging for the floating point stack when I
    ran across this posting. Other than adding stack comments, how can I
    improve this word?

    $ gforth
    ( Average all values on the floating point stack )
    : FloatStackAvg
    fdepth \ Place the number of floating point values on to the stack
    r \ Move the number of floating point values to the return stack
    1 \ Initialize loop counter to 1
    begin dup r@ < \ Duplicate counter, see if < fetched number of floats
    while \ while true
    f+ \ Add two values on the floating point stack
    1 + \ Increment counter
    repeat \ Repeat test at begin word
    \ Move the number of floating point values to the stack
    f \ Convert the number of floating point values to a float
    f/ \ Divide sum by number of floating point values to get average
    drop ; \ Remove the leftover loop counter value from the stack

    \ Place values on floating point stack
    0.120000e 0.118025e 0.118925e 0.120050e 0.119000e 0.122000e 0.120175e
    0.120150e 0.118925e 0.121775e ok f:10

    FloatStackAvg ok f:1
    fe. 119.902500000000E-3 ok

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ahmed@21:1/5 to dxf on Thu Jul 11 07:06:40 2024
    On Thu, 11 Jul 2024 3:47:55 +0000, dxf wrote:

    On 11/07/2024 8:08 am, Buzz McCool wrote:
    On 6/7/2024 1:32 PM, LIT wrote:
    : AVG  DEPTH 0 SWAP DUP >R 0 DO SWAP + LOOP R> / . ;

    I coincidentally was doing averaging for the floating point stack when I
    ran across this posting. Other than adding stack comments, how can I
    improve this word?

    Uses less words than BEGIN REPEAT but compiles to more code under VFX
    ...

    : FAVG ( rn ... r -- avg )
    fdepth dup >r 1- 0 ?do f+ loop r> s>f f/ ;


    Hi,
    without >r and r>
    : favg fdepth dup 1- 0 ?do f+ loop s>f f/ ;

    Ahmed

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ahmed@21:1/5 to All on Thu Jul 11 07:20:45 2024
    And with while

    : favg_while fdepth dup begin dup 1 > while f+ 1- repeat drop s>f f/ ;

    0.120000e 0.118025e 0.118925e 0.120050e 0.119000e 0.122000e 0.120175e
    ok f:7
    0.120150e 0.118925e 0.121775e ok f:10
    favg_while f. 0.1199025 ok

    Ahmed

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to All on Thu Jul 11 10:11:27 2024
    Non standard
    : FSAVG fdepth dup 1- FOR f+ NEXT s>f f/ ;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ahmed@21:1/5 to minforth on Thu Jul 11 12:30:49 2024
    On Thu, 11 Jul 2024 10:11:27 +0000, minforth wrote:

    Non standard
    : FSAVG fdepth dup 1- FOR f+ NEXT s>f f/ ;

    Tested it with gforth, it crashed the system.

    I added 0e in the definition
    : FSAVG fdepth 0e dup 1- FOR f+ NEXT s>f f/ ;

    and it worked
    1e 2e 3e 4e fsavg f. 2.5 ok

    Ahmed

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ahmed@21:1/5 to All on Thu Jul 11 12:49:57 2024
    And this worked too (with gforth).

    : FSAVG fdepth dup 2 - FOR f+ NEXT s>f f/ ; ok
    1e 2e 3e 4e fsavg f. 2.5 ok

    Ahmed

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to All on Thu Jul 11 15:05:05 2024
    That's the benefit of having standards: you can share code.
    In gforth:
    : tt 10 for i . next ; ok
    tt 10 9 8 7 6 5 4 3 2 1 0 ok
    In MinForth:
    : tt 10 for n . next ;
    tt 0 1 2 3 4 5 6 7 8 9 ok

    So gforth loops 11 times here. This is not wrong.
    You just have to know.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ahmed@21:1/5 to All on Thu Jul 11 15:16:57 2024
    Thanks for the explanation.
    How can I get FOR and NEXT with MinForth? I have MF384.

    Ahmed

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to ahmed on Thu Jul 11 16:23:00 2024
    On Thu, 11 Jul 2024 15:16:57 +0000, ahmed wrote:
    How can I get FOR and NEXT with MinForth? I have MF384.

    IIRC MF348 did not include iterators of the FOR family.
    (MF34xx was a "Forth2012-inspired" spin-off. There are no
    plans to release the main branch because it is too specific.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Buzz McCool@21:1/5 to dxf on Thu Jul 11 09:35:40 2024
    On 7/10/2024 8:31 PM, dxf wrote:
    Simpler to count down. I find it easier writing for a common-stack model.

    : FloatStackAvg ( rn ... r -- avg )
    fdepth dup >r ( count)
    begin 1- dup while ( not done)
    >r f+ ( add two floats) r>
    repeat drop
    r> s>f f/ ( sum/count)
    ;


    Thanks for sharing.

    What is the purpose of putting something on and then off the return
    stack on this line?
    >r f+ ( add two floats) r>

    Your example word seemed to work fine without it.

    : FloatStackAvg
    fdepth dup >r
    begin 1- dup while
    f+
    repeat drop
    f f/
    ; ok

    0.120000e 0.118025e 0.118925e 0.120050e 0.119000e 0.122000e 0.120175e 0.120150e 0.118925e 0.121775e ok f:10
    FloatStackAvg ok f:1
    fe. 119.902500000000E-3 ok

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to Buzz McCool on Fri Jul 12 08:06:19 2024
    Buzz McCool <buzz_mccool@yahoo.com> writes:
    On 6/7/2024 1:32 PM, LIT wrote:
    : AVG  DEPTH 0 SWAP DUP >R 0 DO SWAP + LOOP R> / . ;

    I coincidentally was doing averaging for the floating point stack when I
    ran across this posting. Other than adding stack comments, how can I
    improve this word?

    Eliminate DEPTH, e.g., by replacing it with a count of the elements
    you want to average over, or better, write a word that takes only a
    descriptor of, e.g., an array in memory, and averages over the array.

    Why should DEPTH not be used in this way? Because it means that AVG_
    consumes the whole stack and is useless in a word that keeps some
    temporary data deeper in the stack when it calls another word, an
    idiomatic way of using Forth.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2024: https://euro.theforth.net

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to Anton Ertl on Fri Jul 12 12:24:03 2024
    In article <2024Jul12.100619@mips.complang.tuwien.ac.at>,
    Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
    Buzz McCool <buzz_mccool@yahoo.com> writes:
    On 6/7/2024 1:32 PM, LIT wrote:
    : AVG  DEPTH 0 SWAP DUP >R 0 DO SWAP + LOOP R> / . ;

    I coincidentally was doing averaging for the floating point stack when I >>ran across this posting. Other than adding stack comments, how can I >>improve this word?

    Eliminate DEPTH, e.g., by replacing it with a count of the elements
    you want to average over, or better, write a word that takes only a >descriptor of, e.g., an array in memory, and averages over the array.

    Why should DEPTH not be used in this way? Because it means that AVG_ >consumes the whole stack and is useless in a word that keeps some
    temporary data deeper in the stack when it calls another word, an
    idiomatic way of using Forth.

    The minimum you should do is storing FDEPTH at the return stack,
    and then proceeding till you arrive at that stored depth.

    - anton

    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat purring. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Buzz McCool@21:1/5 to dxf on Fri Jul 12 10:25:47 2024
    On 7/11/2024 8:53 PM, dxf wrote:
    On 12/07/2024 2:35 am, Buzz McCool wrote:
    On 7/10/2024 8:31 PM, dxf wrote:
    Simpler to count down.  I find it easier writing for a common-stack model. >>>
    : FloatStackAvg ( rn ... r -- avg )
       fdepth dup >r ( count)
       begin  1- dup while ( not done)
         >r  f+ ( add two floats)  r>
       repeat  drop
       r> s>f f/ ( sum/count)
    ;


    Thanks for sharing.

    What is the purpose of putting something on and then off the return stack on this line?
          >r  f+ ( add two floats)  r>

    Your example word seemed to work fine without it.

    Traditionally floats existed on the data stack along with integers, doubles etc.
    This required being sensitive to what was on top of the stack. As time passed some
    argued floats should have their own stack. That's now progressed to Forth-200x
    outlawing floats on the data stack. Implementing a separate float stack is usually
    no issue for 16-bit processors and above but for 8-bit cpu's it's prohibitive.
    My observation is the same people that push for locals also push for floats on a
    separate stack using essentially the same argument.

    Thus your earlier comment "I find it easier writing for a common-stack
    model." which went over my head. Thanks for the explanation.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Buzz McCool@21:1/5 to Buzz McCool on Mon Jul 15 10:18:55 2024
    On 7/12/2024 10:25 AM, Buzz McCool wrote:
    On 7/10/2024 8:31 PM, dxf wrote:
    Simpler to count down.  I find it easier writing for a common-stack
    model.

    : FloatStackAvg ( rn ... r -- avg )
        fdepth dup >r ( count)
        begin  1- dup while ( not done)
          >r  f+ ( add two floats)  r>
        repeat  drop
        r> s>f f/ ( sum/count)
    ;

    So for a separate floating point stack model:

    : FloatStackAvg ( rn ... r -- avg )
    fdepth dup ( count)
    begin 1 - dup while ( not done)
    f+ ( add two floats)
    repeat drop
    f f/ ; ( sum/count)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to All on Thu Jul 18 07:24:37 2024
    IMO it is not more than a quick hack to digest the full fp stack,
    whatever it may contain or not at the given moment. It makes more sense
    to have also the number of expected items as parameter. Or define some enclosing words, eg.
    m( 1.5 0e pi -1.5 ) FARRAY invector

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Buzz McCool@21:1/5 to minforth on Thu Jul 18 07:56:37 2024
    On 7/18/2024 12:24 AM, minforth wrote:
    IMO it is not more than a quick hack to digest the full fp stack,
    whatever it may contain or not at the given moment. ...
    I understand where you (and Anton) are coming from. I was thinking that FloatStackAvg was a one-and-done word, but someone might want to use it
    with other words and thus have side efects.

    I have a note to perform an fclearstack to clear any existing values
    from the floating point stack before invoking that word for the time being.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to All on Thu Jul 18 16:22:22 2024
    Good and easy, no problem with that. Perhaps I have been bitten by
    importing too many bad csv files in the past... 😉

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Buzz McCool@21:1/5 to dxf on Fri Jul 19 08:15:32 2024
    On 7/18/2024 6:49 PM, dxf wrote:

    While c.l.f. challenges are often couched in terms of items on a stack,
    one is more likely to be dealing with data in memory and a count.
    Shifting the operation to the stack (assuming that's even viable) strikes
    me as unnecessary.

    In this instance, I was using Forth as a scientific calculator that I
    could easily show the data input, algorithm, and output results in a reproducible and sharable fashion.

    I stumbled upon the "Average of a list" thread from last month and took advantage of the discussion to get the knowledgeable c.l.f denizens to
    whittle down my naive code to its essentials and learn fish for myself a
    bit better in the future. Many thanks you and all who take the time to
    teach or opine.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From anthk@21:1/5 to ahmed on Wed May 14 05:51:35 2025
    On 2024-07-11, ahmed <melahi_ahmed@yahoo.fr> wrote:
    Thanks for the explanation.
    How can I get FOR and NEXT with MinForth? I have MF384.

    Ahmed

    In pforth (pfe), that's why I use to test code made for eforth:

    : >MARK ( --A ) HERE 0 , ;
    : AHEAD ( --A ) COMPILE branch >MARK ; IMMEDIATE
    : AFT ( a --a A ) DROP [COMPILE] AHEAD [COMPILE] BEGIN SWAP ; IMMEDIATE

    : FOR ( RUNTIME: N -- )
    COMPILE ABS \ NO NEGATIVES
    COMPILE LIT 0 , COMPILE SWAP
    [COMPILE] ?DO ; IMMEDIATE

    : NEXT
    COMPILE LIT -1 ,
    [COMPILE] +LOOP ; IMMEDIATE

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ahmed@21:1/5 to anthk on Wed May 14 07:07:28 2025
    On Wed, 14 May 2025 5:51:35 +0000, anthk wrote:

    On 2024-07-11, ahmed <melahi_ahmed@yahoo.fr> wrote:
    Thanks for the explanation.
    How can I get FOR and NEXT with MinForth? I have MF384.

    Ahmed

    In pforth (pfe), that's why I use to test code made for eforth:

    : >MARK ( --A ) HERE 0 , ;
    : AHEAD ( --A ) COMPILE branch >MARK ; IMMEDIATE
    : AFT ( a --a A ) DROP [COMPILE] AHEAD [COMPILE] BEGIN SWAP ; IMMEDIATE

    : FOR ( RUNTIME: N -- )
    COMPILE ABS \ NO NEGATIVES
    COMPILE LIT 0 , COMPILE SWAP
    [COMPILE] ?DO ; IMMEDIATE

    : NEXT
    COMPILE LIT -1 ,
    [COMPILE] +LOOP ; IMMEDIATE

    Thanks.

    I've already defined for and next in MinForth like this:

    : (0) 0 ;
    : (-1) -1 ;
    : for_ postpone (0) postpone swap postpone ?do ; immediate
    : _next postpone (-1) postpone +loop ; immediate

    and here is an example of use:

    : go_ 10 for_ i . _next ;

    go_ 10 9 8 7 6 5 4 3 2 1 0 ok


    Ahmed

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From ahmed@21:1/5 to Hans Bezemer on Wed May 14 11:45:49 2025
    On Wed, 14 May 2025 9:17:10 +0000, Hans Bezemer wrote:

    On 14-05-2025 09:07, ahmed wrote:
    On Wed, 14 May 2025 5:51:35 +0000, anthk wrote:

    On 2024-07-11, ahmed <melahi_ahmed@yahoo.fr> wrote:
    Thanks for the explanation.
    How can I get FOR and NEXT with MinForth? I have MF384.

    Ahmed

    In pforth (pfe), that's why I use to test code made for eforth:

    : >MARK ( --A ) HERE 0 , ;
    : AHEAD ( --A ) COMPILE branch >MARK ; IMMEDIATE
    : AFT ( a --a A ) DROP [COMPILE] AHEAD [COMPILE] BEGIN SWAP ; IMMEDIATE

    : FOR ( RUNTIME: N -- )
            COMPILE ABS  \ NO NEGATIVES
            COMPILE LIT 0 , COMPILE SWAP
            [COMPILE] ?DO ; IMMEDIATE

    : NEXT
            COMPILE LIT -1 ,
            [COMPILE] +LOOP ; IMMEDIATE

    Thanks.

    I've already defined for and next in MinForth like this:

    : (0) 0 ;
    : (-1) -1 ;
    : for_ postpone (0) postpone swap postpone ?do ; immediate
    : _next postpone (-1) postpone +loop ; immediate

    and here is an example of use:

    : go_ 10 for_ i . _next ;

    go_  10 9 8 7 6 5 4 3 2 1 0  ok

    Well, it isn't standardized - so you can make it anything you want to. I
    got two variants, the one I think it should be, and the one from eForth:

    :macro for >r begin r@ 0> while ;
    :macro next r> 1- >r repeat rdrop ;

    eForth:
    :macro for >r begin ;
    :macro next r@ 0> while r> 1- >r repeat rdrop ;

    They *SEEM* almost identical, but they aren't. The eForth one performs
    "the action" before the condition is tested, mine *AFTER* the condition
    is tested.

    Now - what do I expect when I issue a "10"? I expect a thing to be
    performed ten times. No more, no less. And that's what mine gets. The
    eForth one does not ten things, but eleven (including the zero). Also
    note my version fixes another DO..LOOP problem - it bombs out when the
    count is zero or less.

    Finally, we all agree DO..LOOP is deeply flawed (it is) but we still
    prefer to use it - preferably with loops with negative subscripts, or garnishing it with horrors like UNLOOP and LEAVE (Hello! - it's a
    *counted* loop. It should do as many times as I asked it to do initially
    - not halfway change my mind saying "Oops - now I want you to quit
    anyway").

    In a 1000 line Forth program I use DO..LOOP 11 times - none with LEAVE
    or UNLOOP. In another 500 line program, not at all. So if I had to
    encode FOR..NEXT I wouldn't choose DO..LOOP - for obvious reasons.

    Hans Bezemer

    Thanks for the information and the calrifications.

    I recopied it to gforth (using postpone) like this and it works.

    : for_ postpone >r postpone begin postpone r@ postpone 0> postpone while
    ; immediate ok

    : _next postpone r> postpone 1- postpone >r postpone repeat postpone
    rdrop ; immediate ok

    : go for_ i . _next ; ok

    10 go 10 9 8 7 6 5 4 3 2 1 ok

    0 go ok

    1 go 1 ok

    Ahmed

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)