div.h
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2015 Kaspar Schleiser <kaspar@schleiser.de>
3  * SPDX-FileCopyrightText: 2016 Eistec AB
4  * SPDX-License-Identifier: LGPL-2.1-only
5  */
6 
7 #pragma once
8 
23 #include <assert.h>
24 #include <stdint.h>
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
33 #define DIV_H_INV_15625_32 0x431bde83ul
34 
38 #define DIV_H_INV_15625_64 0x431bde82d7b634dbull
39 
43 #define DIV_H_INV_15625_SHIFT 12
44 
58 uint64_t _div_mulhi64(const uint64_t a, const uint64_t b);
59 
66 static inline uint64_t div_u64_by_15625(uint64_t val)
67 {
68  if (val > 16383999997ull) {
69  return (_div_mulhi64(DIV_H_INV_15625_64, val) >> DIV_H_INV_15625_SHIFT);
70  }
71  return (val * DIV_H_INV_15625_32) >> (DIV_H_INV_15625_SHIFT + 32);
72 }
73 
87 static inline uint32_t div_u64_by_125(uint64_t val)
88 {
89  /* a higher value would overflow the result type */
90  assert(val <= 536870911999LLU);
91 
92  uint32_t hi = val >> 32;
93  uint32_t lo = val;
94  uint32_t r = (lo >> 16) + (hi << 16);
95  uint32_t res = r / 125;
96  r = ((r % 125) << 16) + (lo & 0xFFFF);
97  res = (res << 16) + r / 125;
98  return res;
99 }
100 
107 static inline uint64_t div_u64_by_1000000(uint64_t val)
108 {
109  return div_u64_by_15625(val) >> 6;
110 }
111 
126 static inline uint32_t div_u32_by_15625div512(uint32_t val)
127 {
128  return ((uint64_t)(val) * DIV_H_INV_15625_32) >> (DIV_H_INV_15625_SHIFT + 32 - 9);
129 }
130 
140 static inline uint64_t div_u64_by_15625div512(uint64_t val)
141 {
142  /*
143  * This saves around 1400 bytes of ROM on Cortex-M platforms (both ARMv6 and
144  * ARMv7) from avoiding linking against __aeabi_uldivmod and related helpers
145  */
146  if (val > 16383999997ull) {
147  /* this would overflow 2^64 in the multiplication that follows, need to
148  * use the long version */
149  return (_div_mulhi64(DIV_H_INV_15625_64, val) >> (DIV_H_INV_15625_SHIFT - 9));
150  }
151  return (val * DIV_H_INV_15625_32) >> (DIV_H_INV_15625_SHIFT + 32 - 9);
152 }
153 
160 static inline uint32_t div_u32_by_44488(uint32_t val)
161 {
162  return ((uint64_t)val * 0xBC8F1391UL) >> (15 + 32);
163 }
164 
171 static inline uint32_t div_u32_mod_44488(uint32_t val)
172 {
173  return val - (div_u32_by_44488(val)*44488);
174 }
175 
176 #ifdef __cplusplus
177 }
178 #endif
POSIX.1-2008 compliant version of the assert macro.
#define assert(cond)
abort the program if assertion is false
Definition: assert.h:143
static uint32_t div_u64_by_125(uint64_t val)
Integer divide val by 125.
Definition: div.h:87
static uint32_t div_u32_mod_44488(uint32_t val)
Modulo 44488.
Definition: div.h:171
static uint64_t div_u64_by_1000000(uint64_t val)
Integer divide val by 1000000.
Definition: div.h:107
static uint32_t div_u32_by_15625div512(uint32_t val)
Divide val by (15625/512)
Definition: div.h:126
static uint64_t div_u64_by_15625(uint64_t val)
Integer divide val by 15625, 64 bit version.
Definition: div.h:66
#define DIV_H_INV_15625_64
Approximation of (2**l)/d for d=15625, l=12, 64 bits.
Definition: div.h:38
#define DIV_H_INV_15625_32
Approximation of (2**l)/d for d=15625, l=12, 32 bits.
Definition: div.h:33
static uint32_t div_u32_by_44488(uint32_t val)
Integer divide val by 44488.
Definition: div.h:160
#define DIV_H_INV_15625_SHIFT
Required shifts for division by 15625, l above.
Definition: div.h:43
static uint64_t div_u64_by_15625div512(uint64_t val)
Divide val by (15625/512)
Definition: div.h:140