////////////////////////////////////////////////////////////////////////////////////
// PackIntegerArrays(hiOrderArray, leftShift, loOrderArray)
//
// Packs two integer arrays into the space of a single AFL 32-bit floating point array.
//
// Arguments:
//    hiOrderArray = input array to be shifted left
//    loOrderArray = input array to be added into the final result
//    leftShift    = number of bit positions to left shift the hiOrderArray
// Returns
//    Array containing the two integers packed together

AmiVar PackIntegerArrays(int NumArgs, AmiVar *ArgsTable)
{
  AmiVar result;

  result = gSite.AllocArrayResult();

  int nSize = gSite.GetArraySize();

  float *hiOrderArray =  ArgsTable[0].array;
  float *loOrderArray =  ArgsTable[1].array;
  int leftShift       = (int) ArgsTable[2].val;

  for (int i = 0; i < nSize; i++)
  {
    if (IS_EMPTY(hiOrderArray[i]) || IS_EMPTY(loOrderArray[i]))
      result.array[i] = EMPTY_VAL;
    else
    {
      unsigned long int *word32 = (unsigned long int *)(&result.array[i]);
      unsigned long int hiBits = hiOrderArray[i];
      unsigned long int loBits = loOrderArray[i];
      *word32 = (hiBits << leftShift) | loBits;
    }
  }

  return result;
}


////////////////////////////////////////////////////////////////////////////////////
// GetPackedBits(floatValue, rightShift, numMaskBits)
//
// Extracts a bit segment from a 32 bit float. The float is typecast to an unsigned 
// long int, then the bits are shifted right. Finally, a mask is applied.
//
// Arguments:
//    floatValue  = 32 bit value from which to extract some subset of bits
//    rightShift  = number of bit positions to right shift before extracting
//    numMaskBits = number of lo-order bits to extract after shifting
// Returns
//    Float

static unsigned long int maskBits[33] = 
{
  0,
  1,
  3,
  7,
  15,
  31,
  63,
  127,
  255,
  511,
  1023,
  2047,
  4095,
  8191,
  16383,
  32767,
  65535,
  131071,
  262143,
  524287,
  1048575,
  2097151,
  4194303,
  8388607,
  16777215,
  33554431,
  67108863,
  134217727,
  268435455,
  536870911,
  1073741823,
  2147483647,
  4294967295,
};

AmiVar GetPackedBits(int NumArgs, AmiVar *ArgsTable)
{
  AmiVar result;

  float             *floatValuePtr = (float *)&ArgsTable[0].val;
  unsigned long int rightShift     = (unsigned long int)ArgsTable[1].val;
  int               numMaskBits    = (int)ArgsTable[2].val;

  unsigned long int *word32 = (unsigned long int *)(floatValuePtr);
  result.val = (*word32 >> rightShift) & maskBits[numMaskBits];
  result.type = VAR_FLOAT;

  return result;
}
