I wrote:
> avg1d=: 3&(+/ % [)

After writing the above, and reading Joey Tuttle's post, I realized
that my simple expression, above, does not do what is needed.

The problem is that successive averages are supposed to use the
previous average as a part of their result.

Given
a,b,c,d,e,f,g

The fortran computation would produce intermediate results like

a,((a+b+c)%3),c,d,e,f,g
a,((a+b+c)%3),((((a+b+c)%3)+c+d)%3),d,e,f,g
and so on.

d, for example, would be replaced by
(((((a+b+c)%3)+c+d)%3)+d+e)%3

Or, simplifying
(a%27)+(b%27)+(c%27)+(c%9)+(d%9)+(d%3)+e%3

e would be replaced by
(a%81)+(b%81)+(c%81)+(c%27)+(d%27)+(d%9)+(e%9)+(e%3)+f%3

and so on...

The end sequence winds up looking like
a
(a%3)+(b%3)+c%3
(a%9)+(b%9)+(c%9)+(b%3)+c%3
(a%27)+(b%27)+(c%27)+(c%9)+(d%9)+(d%3)+e%3
(a%81)+(b%81)+(c%81)+(c%27)+(d%27)+(d%9)+(e%9)+(e%3)+f%3
...

This result is rather complex, and if I was given this
kind of specification in real life the first thing I'd
ask was: what is really being accomplished here?  Could
some similar but simpler sequence be used instead?

(Generally, it's a good idea to re-implement the algorithm
from first principles, instead of emulating the warts of
another language.  Emulating the warts tends to cost far, 
far more than implementing the features.)

That said, to implement it:

Generally, this can be thought of a the sum of some 
sequences of arrays.

The a contribution to the result looks like
a%1 3 9 27 81 ...

The two b contribution to the result looks like
b%_ 3 9 27 81 ...

The c contributions to the result look like
c%_ 3 9 27 81 ...
c%_ _ 3  9 27 ...

The d contributions to the result look like
d%_ _ 3 9 27 81 ...
d%_ _ _ 3  9 27 ...

And so on, with every element after the first two
contributing twice to the result.

To make my life simple, I would follow the general
pattern on edge cases.  I could always go and compute
them over again using special case code if that's 
important.

To get a list like _ _ _ 3 9 27

   (%1&~:)3 ^ 0 >. (i. 6)-2
_ _ _ 3 9 27


Or, the two scaling matrices:

   (%1&~:)3^0>.1+-~/~ i. 6
3 9 27 81 243 729
_ 3  9 27  81 243
_ _  3  9  27  81
_ _  _  3   9  27
_ _  _  _   3   9
_ _  _  _   _   3

   (%1&~:)3^0>.2+-~/~ i. 6
9 27 81 243 729 2187
3  9 27  81 243  729
_  3  9  27  81  243
_  _  3   9  27   81
_  _  _   3   9   27
_  _  _   _   3    9

So... I could define the result in terms of 
inner products of the original array with 
this kind of array.  

scale=: adverb :'%(%1&~:)3^0>.m+-~/~ i. #y'

avg1d=: (] +/ .* 1 scale) + (] +/ .* 2 scale)

Possibly with some post-processing code so that my 
result produces the same lack-of computation as the 
original fortran:

avg1d_simple=: (] +/ .* 1 scale) + (] +/ .* 2 scale)
avg1d=: {.,1&{,(2}._1}.avg1d_simple),{:

This seems like a lot of work for what looks like an
ad-hoc expression.  But perhaps this approach is useful
to someone.

-- 
Raul

----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to