/***************************************************
     hb-midilib-math.c
     Realtime MIDI Library for the MIT HandyBoard
     colby leider (cnl@dartmouth.edu)
     last updated 9.16.97

     http://music.dartmouth.edu/~colby/hb.html
***************************************************/


/* Note: some math functions after Dr. Richard F. Drushel, Case
         Western Reserve Univ. (used by permission).  See his
         libraries at http://lcs.www.media.mit.edu/groups/
         el/projects/handy-board/software/contrib/drushel for
         more information and for his random number routines*/


/* min:
        returns the minimum-valued of two integers */
/***************************************************************/
int
min(int x, int y)
{
    if (x < y) return x;
    else return y;
}


/* fmin:
        returns the minimum-valued of two floats */
/***************************************************************/
float
fmin(float x, float y)
{
    if (x < y) return x;
    else return y;
}


/* lmin:
        returns the minimum-valued of two longs */
/***************************************************************/
long
lmin(long x, long y)
{
    if (x < y) return x;
    else return y;
}


/* max:
        returns the maximum-valued of two integers */
/***************************************************************/
int
max(int x, int y)
{
    if (x > y) return x;
    else return y;
}


/* fmax:
        returns the maximum-valued of two floats */
/***************************************************************/
float
fmax(float x, float y)
{
    if (x > y) return x;
    else return y;
}


/* lmax:
        returns the maximum-valued of two longs */
/***************************************************************/
long
lmax(long x, long y)
{
    if (x > y) return x;
    else return y;
}


/* round:
        rounds a float to the nearest integer and returns the
        integer */
/***************************************************************/
int
round(float x)
{
    float i;
    i = x - (float)(int)x;
    if ((i < 0.5) && (i > -0.5)) return (int)x;
    else if (i >= 0.5) return (int)(x + 1.0);
    else return (int)(x - 1.0);
}


/* trunc:
        truncates a float and returns the integer */
/***************************************************************/
int
trunc(float x)
{
    return (int)x;
}


/* abs:
        returns the absolute value of an integer */
/***************************************************************/
int
abs(int x)
{
    if (x < 0) return (-x);
    else return x;
}


/* fabs:
        returns the absolute value of a float */
/***************************************************************/
float
fabs(float x)
{
    if (x < 0.0) return (-x);
    else return x;
}


/* labs:
        returns the absolute value of a long */
/***************************************************************/
long
labs(long x)
{
    if (x < (long)0) return (-x);
    else return x;
}


/* print_array:
        sequentially prints each member of an integer array to
        the LCD every 500 ms */
/***************************************************************/
void
print_array(int theArray[])
{
    int i;
    for (i=0; i<_array_size(theArray); i++)
    {
        printf("\n%d", theArray[i]);
        msleep(500L);
    }
}


/* print_farray:
        sequentially prints each member of a float array to the
        LCD every 500 ms */
/***************************************************************/
void
print_farray(float theArray[])
{
    int i;
    for (i=0; i<_array_size(theArray); i++)
    {
        printf("\n%f", theArray[i]);
        msleep(500L);
    }
}


/* print_larray:
        sequentially prints each member of a float array to the
        LCD every 500 ms */
/***************************************************************/
void
print_larray(float theArray[])
{
    int i;
    for (i=0; i<_array_size(theArray); i++)
    {
        printf("\n%l", theArray[i]);
        msleep(500L);
    }
}


/* array_min:
        returns the minimum-valued element in an array of
        integers */
/***************************************************************/
int
array_min(int theArray[])
{
    int i, minimum;
    minimum = theArray[0];
    for (i=1; i<_array_size(theArray); i++)
    {
        if (theArray[i] < minimum)
            minimum = theArray[i];
     }
     return minimum;
}


/* array_fmin:
        returns the minimum-valued element in an array of floats */
/***************************************************************/
float
array_fmin(float theArray[])
{
    int i;
   float minimum;
    minimum = theArray[0];
    for (i=1; i<_array_size(theArray); i++)
    {
        if (theArray[i] < minimum)
            minimum = theArray[i];
     }
     return minimum;
}


/* array_lmin:
        returns the minimum-valued element in an array of longs */
/***************************************************************/
long
array_lmin(long theArray[])
{
    int i;
    long minimum;
    minimum = theArray[0];
    for (i=1; i<_array_size(theArray); i++)
    {
        if (theArray[i] < minimum)
            minimum = theArray[i];
     }
     return minimum;
}


/* array_max:
        returns the maximum-valued element in an array of
        integers */
/***************************************************************/
int
array_max(int theArray[])
{
    int i, maximum;
    maximum = theArray[0];
    for (i=1; i<_array_size(theArray); i++)
    {
        if (theArray[i] > maximum)
            maximum = theArray[i];
     }
     return maximum;
}


/* array_fmax:
        returns the maximum-valued array in an array of floats */
/***************************************************************/
float
array_fmax(float theArray[])
{
    int i;
    float maximum;
    maximum = theArray[0];
    for (i=1; i<_array_size(theArray); i++)
    {
        if (theArray[i] > maximum)
            maximum = theArray[i];
     }
     return maximum;
}


/* array_lmax:
        returns the maximum-valued element in an array of longs */
/***************************************************************/
long
array_lmax(long theArray[])
{
    int i;
    long maximum;
    maximum = theArray[0];
    for (i=1; i<_array_size(theArray); i++)
    {
        if (theArray[i] > maximum)
            maximum = theArray[i];
     }
     return maximum;
}


/* array_avg:
        returns the arithmetic mean of the elements in an array
        of integers */
/***************************************************************/
float
array_avg(int theArray[])
{
    int i;
    float avg;
    avg = 0.0;
    for (i=0; i<_array_size(theArray); i++)
    {
        avg += (float)theArray[i];
    }
    avg = avg / (float)_array_size(theArray);
    return avg;
}


/* array_favg:
        returns the arithmetic mean of the elements in an array
        of floats */
/***************************************************************/
float
array_favg(float theArray[])
{
    int i;
    float avg;
    avg = 0.0;
    for (i=0; i<_array_size(theArray); i++)
    {
        avg += theArray[i];
    }
    avg = avg / (float)_array_size(theArray);
    return avg;
}


/* array_lavg:
        returns the arithmetic mean of the elements in an array
        of longs */
/***************************************************************/
float
array_lavg(long theArray[])
{
    int i;
    float avg;
    avg = 0.0;
    for (i=0; i<_array_size(theArray); i++)
    {
        avg += (float)theArray[i];
    }
    avg = avg / (float)_array_size(theArray);
    return avg;
}


/* sum:
        returns the sum of the elements in an array of integers */
/***************************************************************/
int
sum(int theArray[])
{
    int temp, i;
    temp = 0;
    for (i=0; i<_array_size(theArray); i++)
    {
        temp += theArray[i];
    }
    return (temp);
}


/* fsum:
        returns the sum of the elements in an array of floats */
/***************************************************************/
float 
fsum(float theArray[])
{
    float temp;
    int i;
    temp = 0.0;
    for (i=0; i<_array_size(theArray); i++)
    {
        temp += theArray[i];
    }
    return (temp);
}


/* lsum:
        returns the sum of the elements in an array of longs */
/***************************************************************/
long 
lsum(long theArray[])
{
    long temp;
    int i;
    temp = 0L;
    for (i=0; i<_array_size(theArray); i++)
    {
        temp += theArray[i];
    }
    return (temp);
}


/* in:
        returns 1 if the given element is in an array of integers,
        0 otherwise */
/***************************************************************/
int
in(int theArray[], int theElement)
{
    int i;
    for (i=0; i<_array_size(theArray); i++)
    {
        if (theArray[i] == theElement)
        {
            return 1;
            break;
        }
    }
    return 0;
}


/* fin:
        returns 1 if the given element is in an array of floats,
        0 otherwise */
/***************************************************************/
int
fin(float theArray[], float theElement)
{
    int i;
    for (i=0; i<_array_size(theArray); i++)
    {
        if (theArray[i] == theElement)
        {
            return 1;
            break;
        }
    }
    return 0;
}


/* lin:
        returns 1 if the given element is in an array of longs,
        0 otherwise */
/***************************************************************/
int
lin(long theArray[], long theElement)
{
    int i;
    for (i=0; i<_array_size(theArray); i++)
    {
        if (theArray[i] == theElement)
        {
            return 1;
            break;
        }
    }
    return 0;
}


/* approx_in:
        returns 1 if the given element is in an array of integers
        to within a specified tolerance value, 0 otherwise */
/***************************************************************/
int
approx_in(int theArray[], int theElement, float tolerance)
{
    int i;
    for (i=0; i<_array_size(theArray); i++)
    {
        if ((fabs((float)(theArray[i]-theElement)) < fabs((float)theElement * tolerance)))
        {
           return 1;
           break;
        }
    }
    return 0;
}


/* approx_fin:
        returns 1 if the given element is in an array of floats
        to within a specified tolerance value, 0 otherwise */
/***************************************************************/
int
approx_fin(float theArray[], float theElement, float tolerance)
{
    int i;
    for (i=0; i<_array_size(theArray); i++)
    {
        if ((fabs((float)(theArray[i]-theElement)) < fabs((float)theElement * tolerance)))
        {
            return 1;
            break;
        }
    }
    return 0;
}


/* approx_lin:
        returns 1 if the given element is in an array of longs to
        within a specified tolerance value, 0 otherwise */
/***************************************************************/
int
approx_lin(long theArray[], long theElement, float tolerance)
{
    int i;
    for (i=0; i<_array_size(theArray); i++)
    {
        if ((fabs((float)(theArray[i]-theElement)) < fabs((float)theElement * tolerance)))
        {
            return 1;
            break;
        }
    }
    return 0;
}


/* choose:
        returns a randomly-indexed value from the given array of
        integers */
/***************************************************************/
int
choose(int theArray[])
{
    return (theArray[random(_array_size(theArray))]);
}


/* fchoose:
        returns a randomly-indexed value from the given array of
        floats */
/***************************************************************/
float
fchoose(float theArray[])
{
    return (theArray[random(_array_size(theArray))]);
}


/* lchoose:
        returns a randomly-indexed value from the given array of
        longs */
/***************************************************************/
long
lchoose(long theArray[])
{
    return (theArray[random(_array_size(theArray))]);
}


/* at:
        returns the element in the given array of integers
        indexed by the specified location (with wrapped
        indexing) */
/***************************************************************/
int
at(int theArray[], int loc)
{
    return(theArray[loc % _array_size(theArray)]);
}


/* fat:
        returns the element in the given array of floats indexed
        by the specified location (with wrapped indexing) */
/***************************************************************/
float
fat(float theArray[], int loc)
{
    return(theArray[loc % _array_size(theArray)]);
}


/* lat:
        returns the element in the given array of longs indexed
        by the specified location (with wrapped indexing) */
/***************************************************************/
long
lat(long theArray[], int loc)
{
    return(theArray[loc % _array_size(theArray)]);
}
