/** * Copyright © 2014 Mattias Andrée (maandree@member.fsf.org) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #ifndef ALGO_ALGORITHMS_BITS_POWERS_H #define ALGO_ALGORITHMS_BITS_POWERS_H /* NB! This will not play nice if the placeholder `T` is * not set to a type only containing [0-9A-Za-z_] (and $ * in GNU C). Therefore, with the exception of `char`, * `short`, `int`, `long`, `float` and `double`, you * should only use `typedef`:ed types. */ #include /* Note: These functions assume C-rules for integer encoding, * namely, then n:th bit represent 2 to the power of n, and * the bitwise or is equivalent to addition if all operands * are single-bit valued. */ /** * Compute whether an integer is a power of two. * Note that zero is indeed not a power of two. * * This function only works on integer types. And it * assumes that C-rules for integer encoding applies. * * `algo_make_implementation_of_is_power_of_2(T)` * is used to make this function available for a particular * data type `T`. And implementation without modifiers and * attributes will be expanded. You may add `static`, * `inline` and `__attribute__` before calling * `algo_make_implementation_of_is_power_of_2(T)`. * * `algo_make_prototype_of_is_power_of_2(T)` * is the prototype counterpart of * `algo_make_implementation_of_is_power_of_2(T)`. * It too is will not add any modifiers or attributes by * default. It will neither add a semicolon at the end of * the prototype. * * `algo_is_power_of_2(T)` is used to get the version * of the function that supports the data type `T`. * `&(algo_is_power_of_2(T))` gets the address of this * function and `algo_is_power_of_2(T)(items, n, min, max)` * calls the function. * * This function is constant, if you are using GCC you * should add `__attribute__((const))` to its prototype. * * @param value The integer. * @return Whether the integer is a power of two. */ //>fun () { int algo_is_power_of_2__##T(T value) { /* The left hand side clears the least significant bit set. */ return (value & (value - 1)) == 0; /* Or alternatively: (value & -value) == value*/ } //>} ; . ../make_fun /** * Computes the nearest, but higher, power of two, * independently of whether the current value is * a power of two or not. * * This function only works on integer types. And it * assumes that C-rules for integer encoding applies. * * `algo_make_implementation_of_next_power_of_2(T)` * is used to make this function available for a particular * data type `T`. And implementation without modifiers and * attributes will be expanded. You may add `static`, * `inline` and `__attribute__` before calling * `algo_make_implementation_of_next_power_of_2(T)`. * * `algo_make_prototype_of_next_power_of_2(T)` * is the prototype counterpart of * `algo_make_implementation_of_next_power_of_2(T)`. * It too is will not add any modifiers or attributes by * default. It will neither add a semicolon at the end of * the prototype. * * `algo_next_power_of_2(T)` is used to get the version * of the function that supports the data type `T`. * `&(algo_next_power_of_2(T))` gets the address of this * function and `algo_next_power_of_2(T)(items, n, min, max)` * calls the function. * * This function is constant, if you are using GCC you * should add `__attribute__((const))` to its prototype. * * Undefined behaviour is invoked if `value` is negative. * * @param value The current value, must be non-negative. * @return The next power of two. */ //>fun () { T algo_next_power_of_2__##T(T value) { size_t i, n = sizeof(T); value |= value >> 1; value |= value >> 2; value |= value >> 3; for (i = 1; n > i; i <<= 1) value |= value >> (i * 8); return value + 1; } //>} ; . ../make_fun /* Hopefully you compiler can unroll the loop fully * and optimise out our helper variables. These are * added simply for flexibility and not assuming * any limitations on how large an integer can be. */ /** * Computes the nearest, but higher, power of two, * but only if the current value is not a power of two. * If the current value is a power of 2, that value * will be returned. * * This function only works on integer types. And it * assumes that C-rules for integer encoding applies. * * `algo_make_implementation_of_next_power_of_2(T)` * is used to make this function available for a particular * data type `T`. And implementation without modifiers and * attributes will be expanded. You may add `static`, * `inline` and `__attribute__` before calling * `algo_make_implementation_of_next_power_of_2(T)`. * * `algo_make_prototype_of_next_power_of_2(T)` * is the prototype counterpart of * `algo_make_implementation_of_next_power_of_2(T)`. * It too is will not add any modifiers or attributes by * default. It will neither add a semicolon at the end of * the prototype. * * `algo_next_power_of_2(T)` is used to get the version * of the function that supports the data type `T`. * `&(algo_next_power_of_2(T))` gets the address of this * function and `algo_next_power_of_2(T)(items, n, min, max)` * calls the function. * * This function is constant, if you are using GCC you * should add `__attribute__((const))` to its prototype. * * Undefined behaviour is invoked if `value` is zero or * negative. * * @param value The current value, must be positive. * @return The next power of two, or the current * value if it already is a power of 2. */ //>fun () { T algo_next_power_of_2__##T(T value) { size_t i, n = sizeof(T); value -= 1; value |= value >> 1; value |= value >> 2; value |= value >> 3; for (i = 1; n > i; i <<= 1) value |= value >> (i * 8); return value + 1; } //>} ; . ../make_fun /** * Computes the nearest, but higher, power of two, * but only if the current value is not a power of two. * If the current value is a power of 2, that value * will be returned. However, if the value is non-positive, * zero will be returned. * * This function only works on integer types. And it * assumes that C-rules for integer encoding applies. * * `algo_make_implementation_of_next_power_of_2_or_zero(T)` * is used to make this function available for a particular * data type `T`. And implementation without modifiers and * attributes will be expanded. You may add `static`, * `inline` and `__attribute__` before calling * `algo_make_implementation_of_next_power_of_2_or_zero(T)`. * * `algo_make_prototype_of_next_power_of_2_or_zero(T)` * is the prototype counterpart of * `algo_make_implementation_of_next_power_of_2_or_zero(T)`. * It too is will not add any modifiers or attributes by * default. It will neither add a semicolon at the end of * the prototype. * * `algo_next_power_of_2_or_zero(T)` is used to get the version * of the function that supports the data type `T`. * `&(algo_next_power_of_2_or_zero(T))` gets the address of this * function and `algo_next_power_of_2_or_zero(T)(items, n, min, max)` * calls the function. * * This function is constant, if you are using GCC you * should add `__attribute__((const))` to its prototype. * * `algo_next_power_of_2_or_zero(T)(value | 1)` would behave * the same way, except, 0 would map to 1. * * @param value The current value. * @return The next power of two or zero, or the * current value if it already is a power * of 2 or zero. */ //>fun () { T algo_next_power_of_2_or_zero__##T(T value) { size_t i, n = sizeof(T); value -= 1; value &= ~((1 << (n * CHAR_BIT - 1)) - 1); value |= value >> 1; value |= value >> 2; value |= value >> 3; for (i = 1; n > i; i <<= 1) value |= value >> (i * 8); return value + 1; } //>} ; . ../make_fun #endif