#!/bin/bash

usage()
{
  echo "usage: binhist { -s <skip> | -n <length> | -d <stride> } <wordtype> <file> [<bin size>]"
  echo "<wordtype> may be [u]int(8|16|32|64)(le|be) or single or double.  [u]short, [u]int, [u]long and float are also supported but are platform-dependent." | fmt
  echo "<skip>, <length> and <stride> are in bytes; <stride> is the number of bytes to discard between words, not an offset." | fmt
  exit -1;
}

length=Inf
stride=0
while [ "${1:0:1}" = "-" ]; do
  if [ "$1" = "-s" ]; then
    shift
    skip="fread(fp, $1, \"char\");"
  elif [ "$1" = "-n" ]; then
    shift
    length="$1"
  elif [ "$1" = "-d" ]; then
    shift
    stride="$1"
  else
    usage
  fi
  shift
done

test $# -eq 2 -o $# -eq 3 || usage
type=$1
file=$2
binsize=${3:-1}

arch=native
if [ "$type" != "single" ]; then
  if [ "${type%le}" != "$type" ]; then
    arch=ieee-le
    type=${type%le}
  elif [ "${type%be}" != "$type" ]; then
    arch=ieee-be
    type=${type%be}
  fi
fi

octave -q <<EOF
fp= fopen( "$file", "rb" );
$skip
data= fread(fp, $length, "$type", $stride, "$arch");
mx= max(0, max(data));
mn= min(0, min(data));
ubits= max(max(0, ceil(log2(-mn))), ceil(log2(mx+1)));
binsize= $binsize;
nubins= ceil(2 ** ubits / binsize);
if( mn < 0 )
  bins= -nubins*binsize:binsize:nubins*binsize-1;
else
  bins= 0:binsize:nubins*binsize-1;
endif
histo= hist(data, bins+(binsize-1)/2);
cumhisto= cumsum(histo);
fdisp(stdout, [bins' histo' cumhisto'])
EOF

