/* Title: utils.c
 * Author: Jed Marti KI7NNP
 * Description: Bit operations on long ints. Probably doesn't work on 32 bit machines.
 * Revision History: (Created Sun Sep 11 14:54:53 2022)
 */


#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "caps.h"


//uint8_t bitson(uint64_t v)
///*     Return the number of bits on in a 64 bit integer, naive solution.
// * Parameters:
// *   v: 64 bit integer - count its bits on.
// * External References: none
// * Returned values: 0 to 64.
// * Errors detected: none
// */
//{
//  uint8_t bcnt = 0;
//  for (; v != 0; v >>= 1) if (v & 1) ++bcnt;
//  return bcnt;
//}


uint8_t bitson(uint64_t x)
/*     A much faster version of that above especially if there are many bits on. The divide and
 *   conquer strategy on pages 65 and 66 of "Hacker's Delight", by Henry S. Warren, Jr. Addison
 *   Wesley, 2003.
 * Parameters:
 *   x: 64 bit int to count the bits on in.
 * External References: none
 * Returned values: 0-64.
 * Errors detected: none
 */
{
  x -= (x >> 1) & 0x5555555555555555;
  x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
  x = (x + (x >> 4)) & 0x0F0F0F0F0F0F0F0F;
  x += x >> 8;
  x += x >> 16;
  x += x >> 32;
  return (uint8_t) (x & 0x7F);
}



uint8_t bitIndex(uint64_t v, uint8_t whichb)
/*     Return the index of a selected on bit. Thus the second bit of code 0x000014 is 4.
 *   This will correspond to a capacitor from the junk box file in the file order. 
 * Parameters:
 *   v: A 64 bit int with at least whichb bits on.
 *   whichb: which bit to get the index of. 1 is the lowest order 1, 2 the second and so on.
 * Eexternal References: none
 * Errors detected: The bit selected is not in the nubmer v. Should not occur.
 */
{
  uint8_t indx;
  for (indx = 0;; ++indx)
  {
    if ((v & 1) && whichb == 1) return indx;
    else if (v & 1) --whichb;
    v >>= 1;
  }
  fprintf(stderr, "bitIndex fails\n");
  exit(-1);
}



uint8_t isInt(char *msg)
/*     Check msg - if it's a valid unsigned integer (no spaces, etc).
 * Parameters:
 *   msg: 0 terminated string.
 * External References: none
 * Returned values: 0, not an integer, 1 an integer for atoi.
 * Errors detected: none
 */
{
  while (*msg != 0)
  {
    if (*msg < '0' || *msg > '9') return 0;
    ++msg;
  }
  return 1;
}


// EOF
