1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mfbt/TemplateLib.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,111 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* 1.11 + * Reusable template meta-functions on types and compile-time values. Meta- 1.12 + * functions are placed inside the 'tl' namespace to avoid conflict with non- 1.13 + * meta functions of the same name (e.g., mozilla::tl::FloorLog2 vs. 1.14 + * mozilla::FloorLog2). 1.15 + * 1.16 + * When constexpr support becomes universal, we should probably use that instead 1.17 + * of some of these templates, for simplicity. 1.18 + */ 1.19 + 1.20 +#ifndef mozilla_TemplateLib_h 1.21 +#define mozilla_TemplateLib_h 1.22 + 1.23 +#include <limits.h> 1.24 +#include <stddef.h> 1.25 + 1.26 +namespace mozilla { 1.27 + 1.28 +namespace tl { 1.29 + 1.30 +/** Compute min/max. */ 1.31 +template<size_t I, size_t J> 1.32 +struct Min 1.33 +{ 1.34 + static const size_t value = I < J ? I : J; 1.35 +}; 1.36 +template<size_t I, size_t J> 1.37 +struct Max 1.38 +{ 1.39 + static const size_t value = I > J ? I : J; 1.40 +}; 1.41 + 1.42 +/** Compute floor(log2(i)). */ 1.43 +template<size_t I> 1.44 +struct FloorLog2 1.45 +{ 1.46 + static const size_t value = 1 + FloorLog2<I / 2>::value; 1.47 +}; 1.48 +template<> struct FloorLog2<0> { /* Error */ }; 1.49 +template<> struct FloorLog2<1> { static const size_t value = 0; }; 1.50 + 1.51 +/** Compute ceiling(log2(i)). */ 1.52 +template<size_t I> 1.53 +struct CeilingLog2 1.54 +{ 1.55 + static const size_t value = FloorLog2<2 * I - 1>::value; 1.56 +}; 1.57 + 1.58 +/** Round up to the nearest power of 2. */ 1.59 +template<size_t I> 1.60 +struct RoundUpPow2 1.61 +{ 1.62 + static const size_t value = size_t(1) << CeilingLog2<I>::value; 1.63 +}; 1.64 +template<> 1.65 +struct RoundUpPow2<0> 1.66 +{ 1.67 + static const size_t value = 1; 1.68 +}; 1.69 + 1.70 +/** Compute the number of bits in the given unsigned type. */ 1.71 +template<typename T> 1.72 +struct BitSize 1.73 +{ 1.74 + static const size_t value = sizeof(T) * CHAR_BIT; 1.75 +}; 1.76 + 1.77 +/** 1.78 + * Produce an N-bit mask, where N <= BitSize<size_t>::value. Handle the 1.79 + * language-undefined edge case when N = BitSize<size_t>::value. 1.80 + */ 1.81 +template<size_t N> 1.82 +struct NBitMask 1.83 +{ 1.84 + // Assert the precondition. On success this evaluates to 0. Otherwise it 1.85 + // triggers divide-by-zero at compile time: a guaranteed compile error in 1.86 + // C++11, and usually one in C++98. Add this value to |value| to assure 1.87 + // its computation. 1.88 + static const size_t checkPrecondition = 0 / size_t(N < BitSize<size_t>::value); 1.89 + static const size_t value = (size_t(1) << N) - 1 + checkPrecondition; 1.90 +}; 1.91 +template<> 1.92 +struct NBitMask<BitSize<size_t>::value> 1.93 +{ 1.94 + static const size_t value = size_t(-1); 1.95 +}; 1.96 + 1.97 +/** 1.98 + * For the unsigned integral type size_t, compute a mask M for N such that 1.99 + * for all X, !(X & M) implies X * N will not overflow (w.r.t size_t) 1.100 + */ 1.101 +template<size_t N> 1.102 +struct MulOverflowMask 1.103 +{ 1.104 + static const size_t value = 1.105 + ~NBitMask<BitSize<size_t>::value - CeilingLog2<N>::value>::value; 1.106 +}; 1.107 +template<> struct MulOverflowMask<0> { /* Error */ }; 1.108 +template<> struct MulOverflowMask<1> { static const size_t value = 0; }; 1.109 + 1.110 +} // namespace tl 1.111 + 1.112 +} // namespace mozilla 1.113 + 1.114 +#endif /* mozilla_TemplateLib_h */