#!/usr/bin/perl -w

use strict;

# Compute average of second and further elements of array of arrays, except for
# last sub-array.  Just the simple successive summation is used, so this is
# suited only for values that do not differ hugely in size.
# -> Array ref
# <- List of averages
sub avgbut1
{
    my $ary= shift;
    my @sums= @{$$ary[0]};
    shift @sums;
    for (@$ary[1..$#$ary-1]) {
        for my $ind (0..$#sums) {
            $sums[$ind] += $$_[$ind+1];
        }
    }
    my $count= @$ary - 1;
    for (@sums) {
        $_ /= $count;
    }
    return @sums;
}



if( @ARGV < 2 || $ARGV[0] =~ /^--?h(?:elp)?$/i ) {
    print <<EOF;
usage: movavg.pl <averaging interval> <output step> [ <input file> ]
Computes the moving average of columns in space-separated numerical text files.
All values whose first column is within <averaging interval> of the output
time/position are averaged.  Results are output at every <output step>.  '#' is
recognised as starting a comment in the input.
EOF
    exit;
}


my ($range, $step)= splice(@ARGV, 0, 2);
my @current;
my ($outind, $outpos);

while( <> ) {
    s/#.*$//;
    next if /^\s*$/;
    push @current, [ split ];
    if( ! defined $outind ) {
        $outind= int( ($current[-1][0] + $step/2.0) / $step );
        $outpos= $step * $outind;
    }
    elsif( $current[-1][0] > $outpos + $range/2.0 ) {
        shift @current while $current[0][0] < $outpos - $range/2.0;
        if( @current > 1 ) {
            print $outpos, "\t\t", join("\t\t", avgbut1(\@current)), "\n";
        }
        ++$outind;
        $outpos= $step * $outind;
    }
}

push @current, undef;
while( 13 ) {
    shift @current while @current > 1 && $current[0][0] < $outpos - $range/2.0;
    last if @current == 1 || $outpos > $current[-2][0];
    print $outpos, "\t\t", join("\t\t", avgbut1(\@current)), "\n";
    ++$outind;
    $outpos= $step * $outind;
}


