div.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
3  * Copyright (C) 2016 Eistec AB
4  *
5  * This file is subject to the terms and conditions of the GNU Lesser
6  * General Public License v2.1. See the file LICENSE in the top level
7  * directory for more details.
8  */
9 
24 #ifndef DIV_H
25 #define DIV_H
26 
27 #include <assert.h>
28 #include <stdint.h>
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
37 #define DIV_H_INV_15625_32 0x431bde83ul
38 
42 #define DIV_H_INV_15625_64 0x431bde82d7b634dbull
43 
47 #define DIV_H_INV_15625_SHIFT 12
48 
62 uint64_t _div_mulhi64(const uint64_t a, const uint64_t b);
63 
70 static inline uint64_t div_u64_by_15625(uint64_t val)
71 {
72  if (val > 16383999997ull) {
73  return (_div_mulhi64(DIV_H_INV_15625_64, val) >> DIV_H_INV_15625_SHIFT);
74  }
75  return (val * DIV_H_INV_15625_32) >> (DIV_H_INV_15625_SHIFT + 32);
76 }
77 
91 static inline uint32_t div_u64_by_125(uint64_t val)
92 {
93  /* a higher value would overflow the result type */
94  assert(val <= 536870911999LLU);
95 
96  uint32_t hi = val >> 32;
97  uint32_t lo = val;
98  uint32_t r = (lo >> 16) + (hi << 16);
99  uint32_t res = r / 125;
100  r = ((r % 125) << 16) + (lo & 0xFFFF);
101  res = (res << 16) + r / 125;
102  return res;
103 }
104 
111 static inline uint64_t div_u64_by_1000000(uint64_t val)
112 {
113  return div_u64_by_15625(val) >> 6;
114 }
115 
130 static inline uint32_t div_u32_by_15625div512(uint32_t val)
131 {
132  return ((uint64_t)(val) * DIV_H_INV_15625_32) >> (DIV_H_INV_15625_SHIFT + 32 - 9);
133 }
134 
144 static inline uint64_t div_u64_by_15625div512(uint64_t val)
145 {
146  /*
147  * This saves around 1400 bytes of ROM on Cortex-M platforms (both ARMv6 and
148  * ARMv7) from avoiding linking against __aeabi_uldivmod and related helpers
149  */
150  if (val > 16383999997ull) {
151  /* this would overflow 2^64 in the multiplication that follows, need to
152  * use the long version */
153  return (_div_mulhi64(DIV_H_INV_15625_64, val) >> (DIV_H_INV_15625_SHIFT - 9));
154  }
155  return (val * DIV_H_INV_15625_32) >> (DIV_H_INV_15625_SHIFT + 32 - 9);
156 }
157 
164 static inline uint32_t div_u32_by_44488(uint32_t val)
165 {
166  return ((uint64_t)val * 0xBC8F1391UL) >> (15 + 32);
167 }
168 
175 static inline uint32_t div_u32_mod_44488(uint32_t val)
176 {
177  return val - (div_u32_by_44488(val)*44488);
178 }
179 
180 #ifdef __cplusplus
181 }
182 #endif
183 
184 #endif /* DIV_H */
static uint64_t div_u64_by_1000000(uint64_t val)
Integer divide val by 1000000.
Definition: div.h:111
#define DIV_H_INV_15625_64
Approximation of (2**l)/d for d=15625, l=12, 64 bits.
Definition: div.h:42
static uint64_t div_u64_by_15625div512(uint64_t val)
Divide val by (15625/512)
Definition: div.h:144
static uint32_t div_u32_by_44488(uint32_t val)
Integer divide val by 44488.
Definition: div.h:164
POSIX.1-2008 compliant version of the assert macro.
#define assert(cond)
abort the program if assertion is false
Definition: assert.h:104
static uint64_t div_u64_by_15625(uint64_t val)
Integer divide val by 15625, 64 bit version.
Definition: div.h:70
static uint32_t div_u64_by_125(uint64_t val)
Integer divide val by 125.
Definition: div.h:91
#define DIV_H_INV_15625_SHIFT
Required shifts for division by 15625, l above.
Definition: div.h:47
static uint32_t div_u32_mod_44488(uint32_t val)
Modulo 44488.
Definition: div.h:175
static uint32_t div_u32_by_15625div512(uint32_t val)
Divide val by (15625/512)
Definition: div.h:130
#define DIV_H_INV_15625_32
Approximation of (2**l)/d for d=15625, l=12, 32 bits.
Definition: div.h:37