|
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
|