Blame vdo/base/numUtils.h

Packit Service 310c69
/*
Packit Service 310c69
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 310c69
 *
Packit Service 310c69
 * This program is free software; you can redistribute it and/or
Packit Service 310c69
 * modify it under the terms of the GNU General Public License
Packit Service 310c69
 * as published by the Free Software Foundation; either version 2
Packit Service 310c69
 * of the License, or (at your option) any later version.
Packit Service 310c69
 * 
Packit Service 310c69
 * This program is distributed in the hope that it will be useful,
Packit Service 310c69
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 310c69
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 310c69
 * GNU General Public License for more details.
Packit Service 310c69
 * 
Packit Service 310c69
 * You should have received a copy of the GNU General Public License
Packit Service 310c69
 * along with this program; if not, write to the Free Software
Packit Service 310c69
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 310c69
 * 02110-1301, USA. 
Packit Service 310c69
 *
Packit Service 310c69
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/numUtils.h#1 $
Packit Service 310c69
 *
Packit Service 310c69
 * THIS FILE IS A CANDIDATE FOR THE EVENTUAL UTILITY LIBRARY.
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#ifndef NUM_UTILS_H
Packit Service 310c69
#define NUM_UTILS_H
Packit Service 310c69
Packit Service 310c69
#include "common.h"
Packit Service 310c69
#include "numeric.h"
Packit Service 310c69
Packit Service 310c69
#include "types.h"
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Return true if and only if a number is a power of two.
Packit Service 310c69
 **/
Packit Service 310c69
static inline bool isPowerOfTwo(uint64_t n)
Packit Service 310c69
{
Packit Service 310c69
  return (n > 0) && ((n & (n - 1)) == 0);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Efficiently calculate the base-2 logarithm of a number truncated to an
Packit Service 310c69
 * integer value.
Packit Service 310c69
 *
Packit Service 310c69
 * This also happens to be the bit index of the highest-order non-zero bit in
Packit Service 310c69
 * the binary representation of the number, which can easily be used to
Packit Service 310c69
 * calculate the bit shift corresponding to a bit mask or an array capacity,
Packit Service 310c69
 * or to calculate the binary floor or ceiling (next lowest or highest power
Packit Service 310c69
 * of two).
Packit Service 310c69
 *
Packit Service 310c69
 * @param n  The input value
Packit Service 310c69
 *
Packit Service 310c69
 * @return the integer log2 of the value, or -1 if the value is zero
Packit Service 310c69
 **/
Packit Service 310c69
static inline int logBaseTwo(uint64_t n)
Packit Service 310c69
{
Packit Service 310c69
  if (n == 0) {
Packit Service 310c69
    return -1;
Packit Service 310c69
  }
Packit Service 310c69
  // Many CPUs, including x86, directly support this calculation, so use the
Packit Service 310c69
  // GCC function for counting the number of leading high-order zero bits.
Packit Service 310c69
  return 63 - __builtin_clzll(n);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Find the minimum of two physical block numbers.
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static inline PhysicalBlockNumber minBlock(PhysicalBlockNumber a,
Packit Service 310c69
                                           PhysicalBlockNumber b)
Packit Service 310c69
{
Packit Service 310c69
  return (a < b) ? a : b;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Find the maximum of two physical block numbers.
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static inline PhysicalBlockNumber maxBlock(PhysicalBlockNumber a,
Packit Service 310c69
                                           PhysicalBlockNumber b)
Packit Service 310c69
{
Packit Service 310c69
  return (a > b) ? a : b;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Find the minimum of two block counts.
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static inline BlockCount minBlockCount(BlockCount a, BlockCount b)
Packit Service 310c69
{
Packit Service 310c69
  return (a < b) ? a : b;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Find the maximum of two block counts.
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static inline BlockCount maxBlockCount(BlockCount a, BlockCount b)
Packit Service 310c69
{
Packit Service 310c69
  return (a > b) ? a : b;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Find the minimum of two sequence numbers.
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static inline SequenceNumber minSequenceNumber(SequenceNumber a,
Packit Service 310c69
                                               SequenceNumber b)
Packit Service 310c69
{
Packit Service 310c69
  return (a < b) ? a : b;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Return the minimum of two page counts.
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static inline PageCount minPageCount(PageCount a, PageCount b)
Packit Service 310c69
{
Packit Service 310c69
  return (a < b) ? a : b;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Return the maximum of two page counts.
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static inline PageCount maxPageCount(PageCount a, PageCount b)
Packit Service 310c69
{
Packit Service 310c69
  return (a > b) ? a : b;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Round upward towards the nearest multiple of quantum.
Packit Service 310c69
 *
Packit Service 310c69
 * @param number        a number
Packit Service 310c69
 * @param quantum       the quantum
Packit Service 310c69
 *
Packit Service 310c69
 * @return the least multiple of quantum not less than number
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static inline size_t roundUpToMultipleSizeT(size_t number, size_t quantum)
Packit Service 310c69
{
Packit Service 310c69
  return number + quantum - 1 - ((number + quantum - 1) % quantum);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Round upward towards the nearest multiple of quantum for uint64_t
Packit Service 310c69
 *
Packit Service 310c69
 * @param number        a number
Packit Service 310c69
 * @param quantum       the quantum
Packit Service 310c69
 *
Packit Service 310c69
 * @return the least multiple of quantum not less than number
Packit Service 310c69
 **/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static inline uint64_t roundUpToMultipleUInt64T(uint64_t number,
Packit Service 310c69
                                                uint64_t quantum)
Packit Service 310c69
{
Packit Service 310c69
  return number + quantum - 1 - ((number + quantum - 1) % quantum);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Check whether the given value is between the lower and upper bounds,
Packit Service 310c69
 * within a cyclic range of values from 0 to (modulus - 1). The value
Packit Service 310c69
 * and both bounds must be smaller than the modulus.
Packit Service 310c69
 *
Packit Service 310c69
 * @param lower    The lowest value to accept
Packit Service 310c69
 * @param value    The value to check
Packit Service 310c69
 * @param upper    The highest value to accept
Packit Service 310c69
 * @param modulus  The size of the cyclic space, no more than 2^15
Packit Service 310c69
 *
Packit Service 310c69
 * @return true if the value is in range
Packit Service 310c69
 **/
Packit Service 310c69
static inline bool inCyclicRange(uint16_t lower,
Packit Service 310c69
                                 uint16_t value,
Packit Service 310c69
                                 uint16_t upper,
Packit Service 310c69
                                 uint16_t modulus)
Packit Service 310c69
{
Packit Service 310c69
  if (value < lower) {
Packit Service 310c69
    value += modulus;
Packit Service 310c69
  }
Packit Service 310c69
  if (upper < lower) {
Packit Service 310c69
    upper += modulus;
Packit Service 310c69
  }
Packit Service 310c69
  return (value <= upper);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Compute the number of buckets of a given size which are required to hold a
Packit Service 310c69
 * given number of objects.
Packit Service 310c69
 *
Packit Service 310c69
 * @param objectCount  The number of objects to hold
Packit Service 310c69
 * @param bucketSize   The size of a bucket
Packit Service 310c69
 *
Packit Service 310c69
 * @return The number of buckets required
Packit Service 310c69
 **/
Packit Service 310c69
static inline uint64_t computeBucketCount(uint64_t objectCount,
Packit Service 310c69
                                          uint64_t bucketSize)
Packit Service 310c69
{
Packit Service 310c69
  uint64_t quotient = objectCount / bucketSize;
Packit Service 310c69
  if ((objectCount % bucketSize) > 0) {
Packit Service 310c69
    ++quotient;
Packit Service 310c69
  }
Packit Service 310c69
  return quotient;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
#endif // NUM_UTILS_H