/*----------------------------------------------------------------*
 *
 * File : poolInVector.h
 * Author : NTM
 * Created : 30/06/06
 *
 *
 * Copyright (C) Nicolas Thierry-Mieg, 2006.
 *
 *
 * This file is part of InterPool, written by 
 * Nicolas Thierry-Mieg (CNRS, France) Nicolas.Thierry-Mieg@imag.fr
 *
 * InterPool is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * InterPool is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with InterPool; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *-----------------------------------------------------------------*/

#include "types.h" /* MOT, ARCH */
#include "masks.h" /* MASKS */

#include "poolInVector.h"


/*!
  \brief Return the number of MOTs used to store a negPools or 
  other xxxPools vector, in closure and unitC datatypes. 
  We use a single bit per pool.
  nbPools is the number of pools.
*/
int nbMotsPerPoolsVec(int nbPools)
{
  /* a MOT has ARCH bits, hence to store nbPools bits we need
     1 + (nbPools - 1)/ARCH mots. */
  /* return (1 + (nbPools - 1)/ARCH) ; */
  /* optimizing this, it's often called */
  static int nbp = 0 ;
  static int nbmots = 0 ;

  if (nbPools != nbp)
    {
      /* nbPools changed (or first call), recompute nbmots */
      nbp = nbPools ;
      nbmots = 1 + (nbPools - 1)/ARCH ;
    }
  return(nbmots) ;
}


/*!
  Given a MOT* storing a posPools or negPools vector, set the 
  bit coding for pool of absolute number absPoolNum to value.
  value must be 0 or 1 (anything not 0 is treated as 1).
  Of course myVector must be large enough to hold the pool's value.
*/
void setPoolInVector(MOT* myVector, int absPoolNum, int value)
{
  /* build the table of masks once and for all */
  static MOT tabmask[ARCH+1] = MASKS ;

  /* which MOT must be modified? since CHAR_BIT*sizeof(MOT) pools are coded 
     in each MOT, it is the MOT number absPoolNum / (CHAR_BIT*sizeof(MOT)).
     Also note that CHAR_BIT*sizeof(MOT) == ARCH (this must be checked in 
     any main, see config.h) */
  int motNumber = absPoolNum / ARCH ;
  MOT* toUpdate = myVector + motNumber ;

  /* which bit should be set in *toUpdate? 
     Just use bit number absPoolNum%ARCH, counting from right to left,
     ie use as a mask tabmask[absPoolNum%ARCH];
     but since (poolnum % ARCH) == (poolnum & (ARCH-1)), this is 
     equivalent to: */
  int bitToChange = absPoolNum & (ARCH-1) ;
  /* now set the bit to the correct value */
  if (value==0)
    *toUpdate = *toUpdate & (~tabmask[bitToChange]) ;
  else
    *toUpdate = *toUpdate | tabmask[bitToChange] ;
}


/*!
  Given a MOT* storing a posPools or negPools vector, get and 
  return the bit coding for pool absPoolNum.
  Return value will be 0 or 1.
*/
int getPoolInVector(MOT* myVector, int absPoolNum)
{
  /* build the table of masks once and for all */
  static MOT tabmask[ARCH+1] = MASKS ;

  /* which MOT holds the value of chosen pool? see setPoolInVector */
  int motNumber = absPoolNum / ARCH ;
  MOT motValue = *(myVector + motNumber) ;

  /* in motValue, which bit holds the value for the chosen pool? again,
     see setPoolInVector for the discussion. */
  int bitToRead = absPoolNum & (ARCH-1) ;

  /* modify motValue, so that it holds all 0's except for the correct bit, which
     can be 1 or 0 */
  motValue = motValue & tabmask[bitToRead] ;

  /* now return 0 or 1 depending on motValue */
  if (motValue==0)
    return(0) ;
  else
    return(1) ;
}


