Blame source/vdo/base/numUtils.h

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