/*                                              -*- mode:C++; fill-column:100 -*-
  SFBRandom.h - Arduino-compatible random number API for the SFB.
  Copyright (C) 2009 The Regents of the University of New Mexico.  All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  USA

  $Id$
*/

/**
  \file SFBRandom.h Arduino-compatible random number API for the SFB.
  \author David H. Ackley.  
  \date (C) 2009 All rights reserved.
  \lgpl
 */
#ifndef SFBRANDOM_H
#define SFBRANDOM_H

#include "random.h"  /* for randomImpl() */

/**
   Reseed the pseudo-random number generator (PRNG).  The provided \a seed determines the \e entire
   \e sequence of numbers that will be produced by subsequent calls to #random(u32),
   #random(int,int), and/or #randomBits(u32).  

   Note that during initialization the core software \e automatically seeds the PRNG with a seed
   that changes from one reboot to another, so, if this function is \e not called, the sequence of
   pseudo random numbers seen by the program will \e change from one reboot to the next.  It is only
   necessary to call this function if you wish to ensure a \e repeatable sequence of random numbers
   for some reason -- such as debugging.

   \param seed Value with which to seed the PRNG.

   \sideeffect The internal PRNG is initialized

   Compare this code:\code
    void setup() { 
      randomSeed(12);         // Set the PRNG to a known seed, once
    }
    void loop() {
      println(random(100));   // Print some decimal from 0..99
      println(random(-20,20));// Print some decimal from -20..19
      println(randomBits(16),HEX); // Print some hex from 0..FFFF
      println();            // Prints a blank line
      delay(1000);
    }
   \endcode

   to this code:\code
    void setup() { }
    void loop() {
      randomSeed(12);         // RESETS the PRNG to given seed, for a demo
                              // Note that calling randomSeed in the loop()
                              // function (or repeatedly) is usually a BUG!

      println(random(100));   // Always prints 9 (in this specific sketch)
      println(random(-20,20));// Always prints 11 (in this specific sketch)
      println(randomBits(16),HEX); // Always prints 1EC8 (in this specific sketch)
      println();            // Prints a blank line
      delay(1000);
    }
   \endcode
*/ 
extern void randomSeed(u32 seed);

/**
   Get a non-negative pseudo-random number that is less than \a max.

   \param max Size limit.  Returned values will always be \e less than \a max if possible.  Should
   be greater than or equal to 1, but passing 0 does not produce an error.

   \returns 0 if \a max is 0 or 1, otherwise returns a pseudo-random number in the range of 0
   through \a max-1, inclusive.

   \sideeffect The internal PRNG state is updated.

   \usage
   \code
    void setup() { }
    void loop() {
      println(random(2));   // Prints 0 or 1 equally likely
      println(random(3));   // Prints 0, 1, or 2 equally likely
      println(random(6));   // Prints 0, 1, 2, 3, 4, or 5 equally likely
      println();            // Prints a blank line
      delay(1000);
    }
   \endcode

*/ 
extern long random(u32 max);

/**
   Get a pseudo-random number that is greater than or equal to \a min but less than \a max.  For
   best efficiency (as well as code sanity), \a min should be less than or equal to \a max.
   However, if \a min is greater than \a max, that is \e not an error; instead it is treated as if
   the two arguments are swapped.  Beyond here we assume \a min is no larger than \a max.

   \param min Minimum value.  Returned values will always be \e greater than or equal to \a min

   \param max Minimum limit.  Returned values will always be \e less than \a max (unless \a max
   equals \a min, in which case the returned value will always be that value.)

   \returns \a min if \a max==\a min, else a pseudo-random number from \a min to \a max-1.

   \sideeffect The internal PRNG state is updated.

   \usage
   \code
    void setup() { }
    void loop() {
      println(random(0,2));   // Prints 0 or 1 equally likely
      println(random(3,3));   // Prints 3
      println(random(-2,2));  // Prints -2, -1, 0, or 1 equally likely (note max value 2 is excluded!)
      println(random(-2,3));  // Prints -2, -1, 0, 1, or 2 equally likely
      println(random(-7,-10));// Prints -10, -9 or -8 equally likely (note max value -7 is excluded!)
      println();              // Prints a blank line
      delay(1000);
    }
   \endcode
*/ 
extern long random(int min, int max);

/**
   Get a pseudo-random number containing \a n random bits, for \a n from 0 to 32 inclusive.  The
   returned number will be in the range of 0 to (1<<n)-1.

   \param n Number of random bits desired.  Minimum value \a n==0 is legal but somewhat pointless as
   the returned value will always be 0; any \a n>32 is treated as if \a n==32.

   \returns 0 if \a n==0, otherwise a pseudo-random number from 0 to (1<<n)-1.  

   \sideeffect The internal PRNG state is updated.

   \usage
   \code
    void setup() { }
    void loop() {
      println(randomBits(1), DEC);   // Prints 0 or 1 equally likely
      println(randomBits(3), DEC);   // Prints 0, 1, 2, 3, 4, 5, 6, or 7 equally likely
      println(randomBits(32), DEC);  // Prints any value from 0 to 4294967295 equally likely
      println(randomBits(99), DEC);  //     ditto
      println((int) randomBits(32)); // Prints any value from -2147483648 to 2147483647 equally likely
      println();                     // Prints a blank line
      delay(1000);
    }
   \endcode

*/ 
extern u32 randomBits(u32 n);

#endif /* SFBRANDOM_H */
