/*
 * SCFNCA.C - some more core routines used by many packages
 *
 * Source Version: 2.0
 * Software Release #92-0043
 *
 */

#include "cpyright.h"

#include "score.h"

/*--------------------------------------------------------------------------*/

#define SC_TRANS_DATA(dtype, pd, stype, s, n)                                \
       {dtype *d;                                                            \
        d = (dtype *) *pd;                                                   \
        if (d == NULL)                                                       \
           {d   = FMAKE_N(dtype, n, "SC_TRANS_DATA:d");                      \
            *pd = (byte *) d;};                                              \
        if (d != NULL)                                                       \
           {if (strcmp(stype, SC_DOUBLE_S) == 0)                             \
               {SC_TRANS_TYPE(d, double, s, n);}                             \
            else if (strcmp(stype, SC_FLOAT_S) == 0)                         \
               {SC_TRANS_TYPE(d, float, s, n);}                              \
            else if ((strcmp(stype, SC_INTEGER_S) == 0) ||                   \
		     (strcmp(stype, "int") == 0))                            \
               {SC_TRANS_TYPE(d, int, s, n);}                                \
            else if (strcmp(stype, SC_LONG_S) == 0)                          \
               {SC_TRANS_TYPE(d, long, s, n);}                               \
            else if (strcmp(stype, SC_SHORT_S) == 0)                         \
               {SC_TRANS_TYPE(d, short, s, n);}                              \
            else if (strcmp(stype, SC_CHAR_S) == 0)                          \
               {SC_TRANS_TYPE(d, char, s, n);};                              \
	    ret = TRUE;}                                                     \
	else                                                                 \
	   ret = FALSE;}

/*--------------------------------------------------------------------------*/

#define SC_TRANS_TYPE(d, stype, s, n)                                        \
       {stype *ps;                                                           \
        ps = (stype *) s;                                                    \
        for (i = 0; i < n; i++, *d++ = *ps++);}

/*--------------------------------------------------------------------------*/

#ifdef IBMMP

# undef STDOUT
# include <pm_util.h>

int
 SC_ibm_non_ANSI_compliant = FALSE;

#endif

PFInt
 SC_convert_hook = SC_convert,
 SC_sizeof_hook = SC_sizeof;

PFVoid
 SC_container_hook = SC_container;

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/* SC_CONTAINER - simple place holder for a potentially complicated 
 *              - function
 */

void SC_container(dtype, stype)
   char *dtype, *stype;
   {

    strcpy(dtype, stype);

    return;}

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/* SC_CONVERT - convert data from one binary format to another
 *            - if destination pointer is NULL, space is allocated
 *            - if types are the same do nothing but return -1
 *            - arguments:
 *            -     dtype - type of destination data
 *            -     d     - pointer to converted data destination
 *            -     stype - type of source data
 *            -     s     - pointer to data to be converted
 *            -     n     - number of data items
 *            -     flag  - free source data flag
 */

int SC_convert(dtype, pd, stype, s, n, flag)
   char *dtype;
   byte **pd;
   char *stype;
   byte *s;
   int n, flag;
   {int i, ret;

    ret = FALSE;

    if (strcmp(dtype, SC_DOUBLE_S) == 0)
       {SC_TRANS_DATA(double, pd, stype, s, n);}

    else if (strcmp(dtype, SC_FLOAT_S) == 0)
       {SC_TRANS_DATA(float, pd, stype, s, n);}

    else if ((strcmp(dtype, SC_INTEGER_S) == 0) ||
	     (strcmp(dtype, "int") == 0))
       {SC_TRANS_DATA(int, pd, stype, s, n);}

    else if (strcmp(dtype, SC_LONG_S) == 0)
       {SC_TRANS_DATA(long, pd, stype, s, n);}

    else if (strcmp(dtype, SC_SHORT_S) == 0)
       {SC_TRANS_DATA(short, pd, stype, s, n);}

    else if (strcmp(dtype, SC_CHAR_S) == 0)
       {SC_TRANS_DATA(char, pd, stype, s, n);};

    if (flag && (ret == 1))
       SFREE(s);

    return(ret);}

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/* SC_SIZEOF - a string driven sizeof operator if you can't do any better */

int SC_sizeof(s)
   char *s;
   {int nb;

    if (strcmp(s, SC_DOUBLE_S) == 0)
       nb = sizeof(double);

    else if (strcmp(s, SC_FLOAT_S) == 0)
       nb = sizeof(float);

    else if (strcmp(s, SC_INTEGER_S) == 0)
       nb = sizeof(int);

    else if (strcmp(s, SC_LONG_S) == 0)
       nb = sizeof(long);

    else if (strcmp(s, SC_SHORT_S) == 0)
       nb = sizeof(short);

    else if (strcmp(s, SC_CHAR_S) == 0)
       nb = sizeof(char);

    else if (strchr(s, '*') != NULL)
       nb = sizeof(char *);

    else
       nb = 0;

    return(nb);}

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/* SC_FPRINTF - Wrapper for fprintf for handling null file pointers */

#ifdef PCC

int SC_fprintf(fp, fmt, va_alist)
   FILE *fp;
   char *fmt;
   va_dcl

#endif

#ifdef ANSI

int SC_fprintf(FILE *fp, char *fmt, ...)

#endif

   {int ret;

    ret = 0;

    if (fp != NULL)
       {SC_VA_START(fmt);
	ret = SC_VFPRINTF(fp, fmt);
	SC_VA_END;};

    FLUSH_ON(fp, NULL);

    return(ret);}

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/* SC_SETVBUF - a dummy setvbuf for the marginal systems */

int SC_setvbuf(stream, buf, type, size)
   FILE *stream;
   char *buf;
   int type;
   size_t size;
   {int ret;

#ifdef BBN

    ret = TRUE;

#else

#ifdef MAC

	if (stream == stdout)
	   ret = FALSE;
	else
	   ret = setvbuf(stream, buf, type, size);

#else

#ifdef IBMMP

    SC_ibm_non_ANSI_compliant = TRUE;

#else

    ret = setvbuf(stream, buf, type, size);

#endif

#endif

#endif

    return(ret);}

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/* SC_SETBUF - controlled version of C setbuf for marginal systems */

void SC_setbuf(fp, bf)
   FILE *fp;
   char *bf;
   {

#ifndef MAC

#ifdef IBMMP

    SC_ibm_non_ANSI_compliant = TRUE;

#else
    if (bf == NULL)
       io_setvbuf(fp, NULL, _IONBF, 0);
    else
       io_setvbuf(fp, bf, _IOFBF, SC_arrlen(bf));
#endif

#endif

    return;}
 
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/* SC_FFLUSH - controlled version of C fflush for marginal systems */

int SC_fflush(fp)
   FILE *fp;
   {

#ifdef IBMMP
/*
    if (SC_ibm_non_ANSI_compliant)
       mpc_flush(1);
*/
#endif

    return(0);}
 
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

/* SC_MACHINE_PRECISION - return a decimal number representing the
 *                      - fractional precision of floating point arithmetic
 *                      - on the current machine
 */

double SC_machine_precision()
   {int i;
    double x, y;
    double val[4];

    val[0] = 3.0;
    val[1] = exp(1.0);
    val[2] = sqrt(2.0);
    val[3] = asin(1.0);

    x = 1.0;

    for (i = 0; i < 4; i++)
        x *= val[i];

#if 0
    for (i = 0; i < 4; i++)
        x += val[i]*1.0e-8;

    for (i = 0; i < 4; i++)
        x -= val[i]*1.0e-8;
#endif

    for (i = 0; i < 4; i++)
        x /= val[i];

    x = ABS(1.0 - x);
    y = log10(x);
    y = ceil(y);
    x = pow(10.0, y);

    return(x);}
 
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/




