blob: e684e4c602c289fb65fd4a1085982b09ce7fea0b [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FBL_ALGORITHM_H_
#define FBL_ALGORITHM_H_
#include <lib/stdcompat/bit.h>
#include <stdlib.h>
#include <algorithm>
#include <limits>
#include <type_traits>
namespace fbl {
// round_up rounds up val until it is divisible by multiple.
// Zero is divisible by all multiples.
template <class T, class U, class L = std::conditional_t<sizeof(T) >= sizeof(U), T, U>,
class = std::enable_if_t<std::is_unsigned_v<T>>,
class = std::enable_if_t<std::is_unsigned_v<U>>>
constexpr const L round_up(const T& val_, const U& multiple_) {
const L val = static_cast<L>(val_);
const L multiple = static_cast<L>(multiple_);
return val == 0 ? 0
: cpp20::has_single_bit<L>(multiple) ? (val + (multiple - 1)) & ~(multiple - 1)
: ((val + (multiple - 1)) / multiple) * multiple;
}
// round_down rounds down val until it is divisible by multiple.
// Zero is divisible by all multiples.
template <class T, class U, class L = std::conditional_t<sizeof(T) >= sizeof(U), T, U>,
class = std::enable_if_t<std::is_unsigned_v<T>>,
class = std::enable_if_t<std::is_unsigned_v<U>>>
constexpr const L round_down(const T& val_, const U& multiple_) {
const L val = static_cast<L>(val_);
const L multiple = static_cast<L>(multiple_);
return val == 0 ? 0
: cpp20::has_single_bit<L>(multiple) ? val & ~(multiple - 1)
: (val / multiple) * multiple;
}
} // namespace fbl
#endif // FBL_ALGORITHM_H_