#!/usr/bin/perl

# Copyright (c) 2003
#       John Jetmore <jj33@pobox.com>.  All rights reserved.
# This code freely redistributable provided my name and this copyright notice
# are not removed

use strict;
use Getopt::Std;

my($p_name) = $0 =~ m|/?([^/]+)$|;
my $p_usage = "Usage: $p_name [--help] [-if] [-p<precision>] [-s<seed>] "
            . "[-n<count>] [<max>|<min>-<max>]";
ext_usage();

my %opt   = ();
getopts('s:n:fp:i', \%opt) || mexit(2);
# s - seed for srand
# n - number of random numbers to produce in one run
# f - produce floats instead of ints
# p - specify precision - implies -f
# i - increment by one on <high> calls (rand -i 6 is 1-6, not 0-5)

my $range = shift || "1-100";
my $high  = 0;
my $low   = 0;
my $seed  = $opt{s} || (time() ^ ($$ + ($$ << 15)));
my $count = 1;

if ($opt{n}) {
  if ($opt{n} > 0 && $opt{n} =~ /^\d+$/) {
    $count = $opt{n};
  } else {
    mexit(3, "options to -n must be an integer > 0");
  }
}
if ($opt{p}) {
  if ($opt{p} <= 0 || $opt{p} !~ /^\d+$/) {
    mexit(4, "options to -p must be an integer > 0");
  }
  $opt{p} = '.' . $opt{p};
}

if ($range =~ /^(-?\d+)-(-?\d+)$/) {
  $low  = $1;
  $high = $2;
} elsif ($range =~ /^\d+$/) {
  if ($opt{i}) {
    $low  = 1;
    $high = $range;
  } else {
    $low  = 0;
    $high = $range - 1;
  }
} else {
  mexit(1);
}

srand($seed);
foreach (1..$count) {
  my $r = rand($high + 1 - $low) + $low;
  if ($opt{f} || $opt{p}) {
    $r = sprintf("%$opt{p}f", $r);
  } else {
    $r = int($r);
  }
  print $r, "\n";
  #print int(rand($high + 1 - $low)) + $low, "\n";
}

exit;

sub mexit {
  my $exit = shift || 11;
  my $msg  = shift || $p_usage;

  print STDERR "$msg\n";
  exit($exit);
}

sub ext_usage {
  return if ($ARGV[0] !~ /^--help$/i);

  print "$p_usage\n\n";
  print "Produce a random number\n",
        "Example: $p_name 6\n",
        "\n",
        "Options:\n",
	"  -i\twhen specifying only <max>, x will be in 1 <= x <= <max>,\n",
	"\t\tnot 0 <= x < <max>\n",
	"  -f\tnumbers provided as floats, not integers\n",
	"  -p\tspecify precision (implies -f)\n",
        "  -s\tspecify the seed to the random number generator - produce\n",
	"\t\tpredicable number sequences\n",
	"  -n\tspecify an amount of random number sto be generated, one\n",
	"\t\tper line.",
        "\n",
        "Examples:\n",
        "  $p_name 6\n",
        "\tproduces integer x such that 0 <= x < 6\n",
	"  $p_name\n",
	"\tbehaves like '$p_name 100', 0 <= x < 100\n",
        "  $p_name 1-6\n",
        "\t1 <= x <= 6\n",
        "  $p_name -10-10\n",
        "\t-10 <= x <= 10\n",
	"  $p_name -n 2 10-20\n",
	"\tproduces 2 numbers, each 10 <= x <= 20\n",
        "\n",
	"Comments:\n",
	"  calling $p_name with just <max> mimics perl's rand(), with\n",
	"\tthe exception of returning an integer.  However, since this\n",
	"\tisn't what most people expect, specifying a range is\n",
	"\tinclusive on both ends.\n",
	"  To clarify, '$p_name 6' returns a value in the set [012345],\n",
	"\twhile '$p_name 0-6' returns a value in the set [0123456].\n",
	"\n",
        "Exit Status:\n",
	"  0\tno errors occurred\n",
        "  1\timproper target range\n",
        "  2\terror parsing command line arguments\n",
        "  3\terror in -n\n",
        "  4\terror in -p\n",
        "\n",
        "Contact:\n",
        "  proj-rand\@jetmore.net\n";
  exit(0);
}
