blob: db1f3d3dce664256297ce80ecdf41acaef78b50f [file] [log] [blame]
Yuri Wiitala51398aa2019-07-17 18:48:30 -07001// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef UTIL_INTEGER_DIVISION_H_
6#define UTIL_INTEGER_DIVISION_H_
7
8#include <type_traits>
9
10namespace openscreen {
11
12// Returns CEIL(num รท denom). |denom| must not equal zero. This function is
13// compatible with any integer-like type, including the integer-based
14// std::chrono duration types.
15//
16// Optimization note: See DividePositivesRoundingUp().
17template <typename Integer>
18constexpr auto DivideRoundingUp(Integer num, Integer denom) {
19 if (denom < Integer{0}) {
20 num *= -1;
21 denom *= -1;
22 }
23 if (num < Integer{0}) {
24 return num / denom;
25 }
26 return (num + denom - Integer{1}) / denom;
27}
28
29// Same as DivideRoundingUp(), except is more-efficient for hot code paths that
30// know |num| is always greater or equal to zero, and |denom| is always greater
31// than zero.
32template <typename Integer>
33constexpr Integer DividePositivesRoundingUp(Integer num, Integer denom) {
34 return DivideRoundingUp<typename std::make_unsigned<Integer>::type>(num,
35 denom);
36}
37
38// Divides |num| by |denom|, and rounds to the nearest integer (exactly halfway
39// between integers will round to the higher integer). This function is
40// compatible with any integer-like type, including the integer-based
41// std::chrono duration types.
42//
43// Optimization note: See DividePositivesRoundingNearest().
44template <typename Integer>
45constexpr auto DivideRoundingNearest(Integer num, Integer denom) {
46 if (denom < Integer{0}) {
47 num *= -1;
48 denom *= -1;
49 }
50 if (num < Integer{0}) {
51 return (num - ((denom - Integer{1}) / 2)) / denom;
52 }
53 return (num + (denom / 2)) / denom;
54}
55
56// Same as DivideRoundingNearest(), except is more-efficient for hot code paths
57// that know |num| is always greater or equal to zero, and |denom| is always
58// greater than zero.
59template <typename Integer>
60constexpr Integer DividePositivesRoundingNearest(Integer num, Integer denom) {
61 return DivideRoundingNearest<typename std::make_unsigned<Integer>::type>(
62 num, denom);
63}
64
65} // namespace openscreen
66
67#endif // UTIL_INTEGER_DIVISION_H_