Discussion:
Average of a list
(too old to reply)
B. Pym
2024-06-06 03:31:29 UTC
Permalink
SP-Forth:

REQUIRE list-all ~ygrek/lib/list/all.f
list ALSO!
REQUIRE CASE-INS lib/ext/caseins.f

0 0
%[ 10 % 20 % 30 % 40 % 50 % 60 % 70 % 80 % 90 % ]%
:noname ( sum count n -- sum2 count2 ) 1 d+ ;
iter
/ .

===>
50
mhx
2024-06-06 06:17:32 UTC
Permalink
: %[ 0 ; : % + ; : ]% . ;
10 % 20 % 30 % 40 % 50 % 60 % 70 % 80 % 90 % 450 ok

( I don't know what your itered operation is supposed to be ).

-marcel
ahmed
2024-06-06 06:46:04 UTC
Permalink
Hi,

: %[ 0 0 ; : % swap 1+ swap rot + swap ; : ]% / . ;

%[ 10 % 20 % 30 % 40 % 50 % 60 % 70 % 80 % 90 % ]%
gives 50

Why all the requires to do just the mean?

Ahmed
ahmed
2024-06-06 08:34:13 UTC
Permalink
Or better

: %[ 0 0 ; : % rot + swap 1+ ; : ]% / . ;

%[ 10 % 20 % 30 % 40 % 50 % 60 % 70 % 80 % 90 % ]%

gives 50

Ahmed
mhx
2024-06-06 08:47:38 UTC
Permalink
FORTH> 0 value n : %[ 0 clear n ; : % + 1 +TO n ; : ]% n / . ; ok
FORTH> %[ 10 % 20 % 30 % 40 % 50 % 60 % 70 % 80 % 90 % ]% 50 ok

-marcel
Hans Bezemer
2024-06-07 11:40:14 UTC
Permalink
Post by B. Pym
REQUIRE list-all ~ygrek/lib/list/all.f
list ALSO!
REQUIRE CASE-INS lib/ext/caseins.f
0 0
%[ 10 % 20 % 30 % 40 % 50 % 60 % 70 % 80 % 90 % ]%
:noname ( sum count n -- sum2 count2 ) 1 d+ ;
iter
/ .
===>
50
include lib/sequence.4th

{ 10 20 30 40 50 60 70 80 90 } dup sum over length / . cr free

---8<---
$ pp4th -x clf240607.4th
50
---8<---

Hans Bezemer
LIT
2024-06-07 20:32:22 UTC
Permalink
: AVG DEPTH 0 SWAP DUP >R 0 DO SWAP + LOOP R> / . ;

10 20 30 40 50 60 70 80 90

OK
AVG
50
OK
LIT
2024-06-07 20:37:03 UTC
Permalink
Oh, that SWAP inside a loop is actually superfluous...
dxf
2024-06-08 03:20:30 UTC
Permalink
: AVG  DEPTH 0 SWAP DUP >R 0 DO SWAP + LOOP R> / . ;
10 20 30 40 50 60 70 80 90
OK
AVG
50
OK
You wouldn't make a good magician. No sense of theatrics.
LIT
2024-06-08 10:13:34 UTC
Permalink
Post by dxf
You wouldn't make a good magician. No sense of theatrics.
Striving for simplicity, you know. ;)
minforth
2024-06-08 10:49:34 UTC
Permalink
Pym should have shown an example of DFT over a vector in Lisp,
without loading some "fft" library.

Otherwise "garbage in, garbage out".

BTW, the Maxima CAS is written in Lisp.
Ahmed
2024-06-08 12:24:58 UTC
Permalink
I would say:
from -0.4e to 0.4e with step 0.1e

Ahmed
minforth
2024-06-18 18:29:08 UTC
Permalink
I also use an array stack, with some syntactic sugar:

MinForth 3.6 (32 bit) (fp matrix)
# m[ 10 20 30 40 50 60 70 80 90 ] ok
M: <1> | # m.
[ 10 20 30 40 50 60 70 80 90 ] ok
M: <1> | # ' f+ mreduce ok
M: <1> | f: 450 | # mnumel s>f f/ ok
M: <1> | f: 50 | # ok \ <- average
# mdrop fdrop linspace[ -0.4 +0.4 9 ] ok
M: <1> | # m.
[ -0.4 -0.3 -0.2 -0.1 0 0.1 0.2 0.3 0.4 ] ok
M: <1> | # ' fsin mmap mtrans m. ok
[ -0.389418
-0.29552
-0.198669
-0.0998334
0
0.0998334
0.198669
0.29552
0.389418 ] ok
M: <2> | #
a***@spenarnc.xs4all.nl
2024-06-19 09:00:55 UTC
Permalink
Post by minforth
MinForth 3.6 (32 bit) (fp matrix)
# m[ 10 20 30 40 50 60 70 80 90 ] ok
M: <1> | # m.
[ 10 20 30 40 50 60 70 80 90 ] ok
M: <1> | # ' f+ mreduce ok
M: <1> | f: 450 | # mnumel s>f f/ ok
M: <1> | f: 50 | # ok \ <- average
# mdrop fdrop linspace[ -0.4 +0.4 9 ] ok
M: <1> | # m.
[ -0.4 -0.3 -0.2 -0.1 0 0.1 0.2 0.3 0.4 ] ok
M: <1> | # ' fsin mmap mtrans m. ok
[ -0.389418
-0.29552
-0.198669
-0.0998334
0
0.0998334
0.198669
0.29552
0.389418 ] ok
M: <2> | #
An array stack, a string stack ...

Honestly I think for these it is preferred to use a heap aka ALLOCATE.
Maybe it is a hassle to FREE them but that at least give more
flexibility. And then there is the possibility of having sloppy
garbage collectors, the once that inspect each possible pointer to
heap space and if they are pointing in heap space, keep the item just in case.

Addition of those is valuable for a host of other things.
--
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 -
minforth
2024-06-19 09:46:27 UTC
Permalink
You are right, of course. The array stack does not contain
vector/matrix data, but fat pointers (structs) to (re)allocated
heap objects (the matrix elements). Sizing is done automatically.
By the way, dynamic strings are treated like character vectors.

At startup, the rather small array stack is preallocated from
bottom to top with pointers and yet empty objects. On exit,
the heap objects are freed by a loop that traverses the stack.
The same procedure is used to external VECTOR or MATRIX values,
which are linked for this purpose.

Individual heap objects can be freed by setting the referencing
stack element or external value to NIL. There is no garbage
collector. I tried reference counting, but it was not worth the
hassle because my applications rarely have more than about few
dozen external objects alive at the same time.

I can't remember ever having a memory leak because all the
heap objects are referenced through the stack or through the
chain of external VECTOR/MATRIX values. So all heap objects
can be found and managed easily.
alaa
2024-06-22 21:51:31 UTC
Permalink
\ for fun only. no profit generated.
VOCABULARY lists ALSO lists DEFINITIONS
variable in
: init in ON HERE -1 ( running counter ) 0 ( initial list count) ;
: add C, 1+ ; \ assume numbers within a byte.
: parse BL WORD FIND IF EXECUTE ELSE COUNT NUMBER THEN ; \ assuming list
items are either numbers or words returning single item.
: %[ init BEGIN add parse in @ NOT UNTIL ;
: ]% in OFF OVER C! ;
: .% COUNT BOUNDS DO I C@ . SPACE LOOP ;

\ Examples
CR %[ 1 2 3 4 5 6 7 8 9 10 ]% .%
CR %[ 51 32 13 ]% .%

\ with Average
: avg 0 OVER COUNT BOUNDS DO I C@ + LOOP SWAP C@ / ;
CR %[ 1 2 3 4 5 6 7 8 9 10 ]% avg .
CR %[ 1 2 3 ]% avg .

\ contents can be words
: six 7 ;
CR %[ six six six ]% .%
Ahmed
2024-06-08 12:21:59 UTC
Permalink
Some time ago, I wrote a gforth script for vector stack and defined some
functions and operations on it.
for example:

1e 10e vvrange vvmean f. 5. ok
1e 10e vvrange 10e vv*s vvmean f. 50. ok <---------- here, a solution
for this thread
1e 10e vvrange 10e vv*s 100e vv+s vvmean f. 150. ok

the functions defined on the vector stack are the vectorized versions of
the same functions on floats, for example:

: vvfunction create ' , does> @ is function vstack-1 vstack-top 2dup
(vfunction) vstack+1 ;

vvfunction vvsin fsin
vvfunction vvcos fcos
vvfunction vvexp fexp

and so on.

An example of application:

1e 10e vvrange 0.1e vv*s -0.5e vv+s vvsin vv|.
-0.389418342308651
-0.29552020666134
-0.198669330795061
-0.0998334166468281
0.
0.0998334166468282
0.198669330795061
0.29552020666134
0.389418342308651 ok

that gives sine of values in -0.5e to 0.5e with a step 0.1e


Ahmed
Buzz McCool
2024-07-10 22:08:59 UTC
Permalink
: 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
r> \ Move the number of floating point values to the stack
s>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
dxf
2024-07-11 03:31:17 UTC
Permalink
: 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
while    \ while true
f+       \ Add two values on the floating point stack
1 +      \ Increment counter
repeat   \ Repeat test at begin word
r>       \ Move the number of floating point values to the stack
s>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
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)
;
Buzz McCool
2024-07-11 16:35:40 UTC
Permalink
Post by dxf
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?
Post by dxf
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
r> s>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
dxf
2024-07-12 03:53:00 UTC
Permalink
Post by Buzz McCool
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.
Buzz McCool
2024-07-12 17:25:47 UTC
Permalink
Post by dxf
Post by Buzz McCool
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.
Buzz McCool
2024-07-15 17:18:55 UTC
Permalink
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
s>f f/ ; ( sum/count)
minforth
2024-07-18 07:24:37 UTC
Permalink
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
Buzz McCool
2024-07-18 14:56:37 UTC
Permalink
Post by minforth
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.
minforth
2024-07-18 16:22:22 UTC
Permalink
Good and easy, no problem with that. Perhaps I have been bitten by
importing too many bad csv files in the past... 😉
dxf
2024-07-19 01:49:26 UTC
Permalink
Post by minforth
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.
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.
Buzz McCool
2024-07-19 15:15:32 UTC
Permalink
Post by dxf
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.

dxf
2024-07-11 03:47:55 UTC
Permalink
: 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/ ;
ahmed
2024-07-11 07:06:40 UTC
Permalink
Post by dxf
Post by Buzz McCool
: 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
ahmed
2024-07-11 07:20:45 UTC
Permalink
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
minforth
2024-07-11 10:11:27 UTC
Permalink
Non standard
: FSAVG fdepth dup 1- FOR f+ NEXT s>f f/ ;
ahmed
2024-07-11 12:30:49 UTC
Permalink
Post by minforth
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
ahmed
2024-07-11 12:49:57 UTC
Permalink
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
minforth
2024-07-11 15:05:05 UTC
Permalink
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.
ahmed
2024-07-11 15:16:57 UTC
Permalink
Thanks for the explanation.
How can I get FOR and NEXT with MinForth? I have MF384.

Ahmed
minforth
2024-07-11 16:23:00 UTC
Permalink
Post by ahmed
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.)
Anton Ertl
2024-07-12 08:06:19 UTC
Permalink
Post by Buzz McCool
: 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
a***@spenarnc.xs4all.nl
2024-07-12 10:24:03 UTC
Permalink
Post by Anton Ertl
Post by Buzz McCool
: 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.
Post by Anton Ertl
- 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 -
Loading...