/* **********************************************************************
 * *	                                                                *
 * *             Routines to help with Bytes/Words/Longs                *
 * *                                                                    *
 * **********************************************************************
 * File: libs/user/byteops.c
 *
 *                COPYRIGHT (c) 1994, 2001, 2003  BY
 *         SIGMET INCORPORATED, WESTFORD MASSACHUSETTS, U.S.A.
 * 
 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
 * ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
 * INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
 * COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
 * OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
 * TRANSFERED.
 *
 *   movb_2_to_1()       Copy every second byte to a byte array
 *   movb_4_to_1()       Copy every fourth byte to a byte array
 *   mneg_4_to_1()       Negate every fourth byte, and copy to a byte array
 *   move_neg_words()    Copy and negate an array of words
 *   uniquesum()         Make a 'unique' summation of bytes
 *
 *   memset_f4()  memset_f8()   (Array initialization routines)
 *   memset_s4()  memset_s2()
 *   memset_u4()  memset_u2()
 *
 *   bbput_1()  bbput_2()  bbput_4()    (Big-Bit Put/Clr/Set/Test routines)
 *   bbclr_1()  bbclr_2()  bbclr_4()
 *   bbset_1()  bbset_2()  bbset_4()
 *   bbtst_1()  bbtst_2()  bbtst_4()
 */
#include <stdio.h>
#include <string.h>
#include "sigtypes.h"
#include "user_lib.h"

/* ------------------------------
 * Move every second byte to a packed array of bytes.
 */
void movb_2_to_1(const void* in_a, void* out_a, SINT4 icount_a )
{
  const SINT1 *in=in_a; SINT1 *out=out_a ; SINT4 icount=icount_a ;
  while( icount > 0 ) { *out++ = *in ; in+=2 ; icount-- ; }
}
		
/* ------------------------------
 * Move every fourth byte to a packed array of bytes.
 */
void movb_4_to_1(const void* in_a, void* out_a, SINT4 icount_a )
{
  const SINT1 *in=in_a; SINT1 *out=out_a ; SINT4 icount=icount_a ;
  while( icount > 0 ) { *out++ = *in ; in+=4 ; icount-- ; }
}
	
/* ------------------------------
 * Negate every second byte, and copy to a packed array of bytes.
 */
void mneg_2_to_1(const void* in_a, void* out_a, SINT4 icount_a )
{
  const SINT1 *in=in_a; SINT1 *out=out_a ; SINT4 icount=icount_a ;
  while( icount > 0 ) { *out++ = (-(*in)) ; in+=2 ; icount-- ; }
}
	
/* ------------------------------
 * Negate every fourth byte, and copy to a packed array of bytes.
 */
void mneg_4_to_1(const void* in_a, void* out_a, SINT4 icount_a )
{
  const SINT1 *in=in_a; SINT1 *out=out_a ; SINT4 icount=icount_a ;
  while( icount > 0 ) { *out++ = (-(*in)) ; in+=4 ; icount-- ; }
}

/* ------------------------------
 * Move and negate an array of words
 */
void move_neg_words(const void* in_a, void* out_a, SINT4 icount_a )
{
  const SINT2 *in=in_a; SINT2 *out=out_a ; SINT4 icount=icount_a ;
  while( icount > 0 ) { *out++ = (-(*in++)) ; icount-- ; }
}

/* ------------------------------
 * Make a somewhat unique 32-bit integer, given an array of bytes.
 * This can be used to check whether the array has changed from one
 * point in time to another.
 */
UINT4 iunique_sum( const void *array_a, SINT4 count_a )
{
  SINT4 ii ; UINT4 isum=0, irand=12345 ; const UINT1 *pch=array_a ;
  for( ii=0 ; ii < count_a ; ii++ ) {
    isum += (irand * *pch++) ; irand = (irand + 10007) & 0x00FFFFFF ;
  }
  return( isum ) ;
}

/* ------------------------------
 * Big Bit Field Set/Clear/Test routines.  These permit you to pack
 * bit fields more efficiently.  The return value is the value of the
 * bit prior to the call.  Three different routines are defined for
 * one-byte, two-byte, and four-byte internal accesses.  This is only
 * important if the array will also be accessed by other C code.
 */
#define MAKEBBSUBS( BBPUT, BBCLR, BBSET, BBTST, TYPE, SHIFT ) \
  UINT1 BBPUT( volatile void *barray_a, SINT4 ibit_a, UINT1 iVal_a ) \
  { \
    TYPE *pval = &((TYPE *)barray_a)[ ibit_a >> SHIFT ], ival = *pval ; \
    TYPE imask = (1 << (ibit_a & (BIT(SHIFT)-1)) ) ; \
    if( iVal_a ) *pval |= imask ; else *pval &= ~imask ; \
    return( (ival & imask) != 0 ) ; \
  } \
   \
  UINT1 BBCLR( volatile void *barray_a, SINT4 ibit_a ) \
  { \
    TYPE *pval = &((TYPE *)barray_a)[ ibit_a >> SHIFT ], ival = *pval ; \
    TYPE imask = (1 << (ibit_a & (BIT(SHIFT)-1)) ) ; \
    *pval &= ~imask ; return( (ival & imask) != 0 ) ; \
  } \
   \
  UINT1 BBSET( volatile void *barray_a, SINT4 ibit_a ) \
  { \
    TYPE *pval = &((TYPE *)barray_a)[ ibit_a >> SHIFT ], ival = *pval ; \
    TYPE imask = (1 << (ibit_a & (BIT(SHIFT)-1)) ) ; \
    *pval |= imask ; return( (ival & imask) != 0 ) ; \
  } \
   \
  UINT1 BBTST( volatile const void *barray_a, SINT4 ibit_a ) \
  { \
    TYPE *pval = &((TYPE *)barray_a)[ ibit_a >> SHIFT ], ival = *pval ; \
    TYPE imask = (1 << (ibit_a & (BIT(SHIFT)-1)) ) ; \
    return( (ival & imask) != 0 ) ; \
  }

MAKEBBSUBS( bbput_1, bbclr_1, bbset_1, bbtst_1, UINT1, 3 )
MAKEBBSUBS( bbput_2, bbclr_2, bbset_2, bbtst_2, UINT2, 4 )
MAKEBBSUBS( bbput_4, bbclr_4, bbset_4, bbtst_4, UINT4, 5 )

/* ------------------------------
 * Simple array operations.  These are included to make the transition
 * from TI320 code a little easier, i.e., because the TI320 "int" and
 * "float" has a sizeof() one.  But they're handy for initializing any
 * non-byte array.
 */
void memset_f4( volatile FLT4 f4Array_a[], FLT4 f4Value_a, SINT4 iCount_a )
{
  SINT4 iCount = iCount_a ; volatile FLT4 *pF4Array = f4Array_a ;
  while( iCount-- > 0 ) *pF4Array++ = f4Value_a ;
}
void memset_f8( volatile FLT8 f8Array_a[], FLT8 f8Value_a, SINT4 iCount_a )
{
  SINT4 iCount = iCount_a ; volatile FLT8 *pF8Array = f8Array_a ;
  while( iCount-- > 0 ) *pF8Array++ = f8Value_a ;
}
void memset_s4( volatile SINT4 s4Array_a[], SINT4 s4Value_a, SINT4 iCount_a )
{
  SINT4 iCount = iCount_a ; volatile SINT4 *pS4Array = s4Array_a ;
  while( iCount-- > 0 ) *pS4Array++ = s4Value_a ;
}
void memset_s2( volatile SINT2 s2Array_a[], SINT2 s2Value_a, SINT4 iCount_a )
{
  SINT4 iCount = iCount_a ; volatile SINT2 *pS2Array = s2Array_a ;
  while( iCount-- > 0 ) *pS2Array++ = s2Value_a ;
}
void memset_u4( volatile UINT4 u4Array_a[], UINT4 u4Value_a, SINT4 iCount_a )
{
  SINT4 iCount = iCount_a ; volatile UINT4 *pU4Array = u4Array_a ;
  while( iCount-- > 0 ) *pU4Array++ = u4Value_a ;
}
void memset_u2( volatile UINT2 u2Array_a[], UINT2 u2Value_a, SINT4 iCount_a )
{
  SINT4 iCount = iCount_a ; volatile UINT2 *pU2Array = u2Array_a ;
  while( iCount-- > 0 ) *pU2Array++ = u2Value_a ;
}
