libtcspc C++ API
Streaming TCSPC and time tag data processing
Loading...
Searching...
No Matches
npint.hpp
1/*
2 * This file is part of libtcspc
3 * Copyright 2019-2026 Board of Regents of the University of Wisconsin System
4 * SPDX-License-Identifier: MIT
5 */
6
7#pragma once
8
9#include "int_types.hpp"
10
11#include <compare>
12#include <concepts>
13#include <istream>
14#include <limits>
15#include <ostream>
16#include <type_traits>
17
18namespace tcspc {
19
33template <std::integral T> class npint {
34 T v;
35
36 public:
38 using underlying_type = T;
39
40 // Rule of zero
41
49 constexpr npint() noexcept = default;
50
56 explicit constexpr npint(T value) noexcept : v(value) {}
57
61 explicit constexpr operator T() const noexcept { return v; }
62
68 [[nodiscard]] constexpr auto value() const noexcept -> T { return v; }
69
82 template <typename U>
83 requires(not std::same_as<T, U>)
84 explicit constexpr npint(npint<U> const &other) : v(T(other.value())) {
85 static_assert(
86 sizeof(T) <= sizeof(U) ||
87 std::is_unsigned_v<T> == std::is_unsigned_v<U>,
88 "Widening and changing signedness at the same time is not allowed");
89 }
90
91 // Operators
92
93 // The following operators are intentionally left out:
94 // ! && ||
95 // because we do not want to automatically treat a number as a boolean.
96
97 // Increment and decrement operators
98
100 constexpr auto operator++() -> npint { return npint(++v); }
101
103 constexpr auto operator++(int) -> npint { return npint(v++); }
104
106 constexpr auto operator--() -> npint { return npint(--v); }
107
109 constexpr auto operator--(int) -> npint { return npint(v--); }
110
111 // Compound assignment operators
112
114 constexpr auto operator+=(npint rhs) -> npint & {
115 v += rhs.v;
116 return *this;
117 }
118
120 constexpr auto operator-=(npint rhs) -> npint & {
121 v -= rhs.v;
122 return *this;
123 }
124
126 constexpr auto operator*=(npint rhs) -> npint & {
127 v *= rhs.v;
128 return *this;
129 }
130
132 constexpr auto operator/=(npint rhs) -> npint & {
133 v /= rhs.v;
134 return *this;
135 }
136
138 constexpr auto operator%=(npint rhs) -> npint & {
139 v %= rhs.v;
140 return *this;
141 }
142
144 constexpr auto operator&=(npint rhs) noexcept -> npint & {
145 v &= rhs.v;
146 return *this;
147 }
148
150 constexpr auto operator|=(npint rhs) noexcept -> npint & {
151 v |= rhs.v;
152 return *this;
153 }
154
156 constexpr auto operator^=(npint rhs) noexcept -> npint & {
157 v ^= rhs.v;
158 return *this;
159 }
160
162 template <typename U> constexpr auto operator>>=(npint<U> rhs) -> npint & {
163 v = static_cast<T>(v >> rhs.value());
164 return *this;
165 }
166
168 template <typename U> constexpr auto operator<<=(npint<U> rhs) -> npint & {
169 v = static_cast<T>(v << rhs.value());
170 return *this;
171 }
172
174 constexpr auto operator>>=(std::integral auto rhs) -> npint & {
175 v = static_cast<T>(v >> rhs);
176 return *this;
177 }
178
180 constexpr auto operator<<=(std::integral auto rhs) -> npint & {
181 v = static_cast<T>(v << rhs);
182 return *this;
183 }
184
185 // Unary arithmetic operators
186
188 constexpr auto operator+() const noexcept -> npint { return *this; }
189
191 constexpr auto operator-() const -> npint {
192 return npint(static_cast<T>(-v));
193 }
194
195 // Binary arithmetic operators
196
198 friend constexpr auto operator+(npint lhs, npint rhs) -> npint {
199 return lhs += rhs;
200 }
201
203 friend constexpr auto operator-(npint lhs, npint rhs) -> npint {
204 return lhs -= rhs;
205 }
206
208 friend constexpr auto operator*(npint lhs, npint rhs) -> npint {
209 return lhs *= rhs;
210 }
211
213 friend constexpr auto operator/(npint lhs, npint rhs) -> npint {
214 return lhs /= rhs;
215 }
216
218 friend constexpr auto operator%(npint lhs, npint rhs) -> npint {
219 return lhs %= rhs;
220 }
221
222 // Bitwise arithmetic operators
223
225 friend constexpr auto operator&(npint lhs, npint rhs) noexcept -> npint {
226 return lhs &= rhs;
227 }
228
230 friend constexpr auto operator|(npint lhs, npint rhs) noexcept -> npint {
231 return lhs |= rhs;
232 }
233
235 friend constexpr auto operator^(npint lhs, npint rhs) noexcept -> npint {
236 return lhs ^= rhs;
237 }
238
240 constexpr auto operator~() const noexcept -> npint {
241 return npint(static_cast<T>(~v));
242 }
243
245 template <typename U>
246 friend constexpr auto operator<<(npint lhs, npint<U> rhs) -> npint {
247 return lhs <<= rhs;
248 }
249
251 template <typename U>
252 friend constexpr auto operator>>(npint lhs, npint<U> rhs) -> npint {
253 return lhs >>= rhs;
254 }
255
257 friend constexpr auto operator<<(npint lhs, std::integral auto rhs)
258 -> npint {
259 return lhs <<= rhs;
260 }
261
263 friend constexpr auto operator>>(npint lhs, std::integral auto rhs)
264 -> npint {
265 return lhs >>= rhs;
266 }
267
268 // Binary comparison operators
269
271 friend constexpr auto operator<=>(npint lhs, npint rhs) noexcept
272 -> std::strong_ordering = default;
273
274 // Stream insertion and extraction operators
275
277 friend auto operator<<(std::ostream &strm, npint rhs) -> std::ostream & {
278 return strm << rhs.v;
279 }
280
282 friend auto operator>>(std::istream &strm, npint &rhs) -> std::istream & {
283 return strm >> rhs.v;
284 }
285};
286
293
300
307
314
321
328
335
342
348namespace literals {
349
353constexpr auto operator""_u8np(unsigned long long v) -> u8np {
354 return u8np(u8(v));
355}
356
360constexpr auto operator""_u16np(unsigned long long v) -> u16np {
361 return u16np(u16(v));
362}
363
367constexpr auto operator""_u32np(unsigned long long v) -> u32np {
368 return u32np(u32(v));
369}
370
374constexpr auto operator""_u64np(unsigned long long v) -> u64np {
375 return u64np(v);
376}
377
385constexpr auto operator""_i8np(unsigned long long v) -> i8np {
386 return v <= u8(std::numeric_limits<i8>::max()) ? i8np(static_cast<i8>(v))
387 : throw;
388}
389
397constexpr auto operator""_i16np(unsigned long long v) -> i16np {
398 return v <= u16(std::numeric_limits<i16>::max())
399 ? i16np(static_cast<i16>(v))
400 : throw;
401}
402
410constexpr auto operator""_i32np(unsigned long long v) -> i32np {
411 return v <= u32(std::numeric_limits<i32>::max())
412 ? i32np(static_cast<i32>(v))
413 : throw;
414}
415
424constexpr auto operator""_i64np(unsigned long long v) -> i64np {
425 return v <= u64(std::numeric_limits<i64>::max())
426 ? i64np(static_cast<i64>(v))
427 : throw;
428}
429
430} // namespace literals
431
432using namespace literals;
433
434} // namespace tcspc
435
436namespace std {
437
438// NOLINTNEXTLINE(cert-dcl58-cpp)
439template <typename T> struct numeric_limits<tcspc::npint<T>> {
440 static constexpr bool is_specialized = true;
441
442 static constexpr bool has_denorm_loss = numeric_limits<T>::has_denorm_loss;
443 static constexpr bool has_infinity = numeric_limits<T>::has_infinity;
444 static constexpr bool has_quiet_NaN = numeric_limits<T>::has_quiet_NaN;
445 static constexpr bool has_signaling_NaN =
446 numeric_limits<T>::has_signaling_NaN;
447 static constexpr bool is_bounded = numeric_limits<T>::is_bounded;
448 static constexpr bool is_exact = numeric_limits<T>::is_exact;
449 static constexpr bool is_iec559 = numeric_limits<T>::is_iec559;
450 static constexpr bool is_integer = numeric_limits<T>::is_integer;
451 static constexpr bool is_modulo = numeric_limits<T>::is_modulo;
452 static constexpr bool is_signed = numeric_limits<T>::is_signed;
453 static constexpr bool tinyness_before = numeric_limits<T>::tinyness_before;
454 static constexpr bool traps = numeric_limits<T>::traps;
455 static constexpr float_denorm_style has_denorm =
456 numeric_limits<T>::has_denorm;
457 static constexpr float_round_style round_style =
458 numeric_limits<T>::round_style;
459 static constexpr int digits = numeric_limits<T>::digits;
460 static constexpr int digits10 = numeric_limits<T>::digits10;
461 static constexpr int max_digits10 = numeric_limits<T>::max_digits10;
462 static constexpr int max_exponent = numeric_limits<T>::max_exponent;
463 static constexpr int max_exponent10 = numeric_limits<T>::max_exponent10;
464 static constexpr int min_exponent = numeric_limits<T>::min_exponent;
465 static constexpr int min_exponent10 = numeric_limits<T>::min_exponent10;
466 static constexpr int radix = numeric_limits<T>::radix;
467
468 static constexpr auto denorm_min() -> tcspc::npint<T> {
469 return tcspc::npint<T>(numeric_limits<T>::denorm_min());
470 }
471 static constexpr auto epsilon() -> tcspc::npint<T> {
472 return tcspc::npint<T>(numeric_limits<T>::epsilon());
473 }
474 static constexpr auto infinity() -> tcspc::npint<T> {
475 return tcspc::npint<T>(numeric_limits<T>::infinity());
476 }
477 static constexpr auto lowest() -> tcspc::npint<T> {
478 return tcspc::npint<T>(numeric_limits<T>::lowest());
479 }
480 static constexpr auto max() -> tcspc::npint<T> {
481 return tcspc::npint<T>(numeric_limits<T>::max());
482 }
483 static constexpr auto min() -> tcspc::npint<T> {
484 return tcspc::npint<T>(numeric_limits<T>::min());
485 }
486 static constexpr auto quiet_NaN() -> tcspc::npint<T> {
487 return tcspc::npint<T>(numeric_limits<T>::quiet_NaN());
488 }
489 static constexpr auto round_error() -> tcspc::npint<T> {
490 return tcspc::npint<T>(numeric_limits<T>::round_error());
491 }
492 static constexpr auto signaling_NaN() -> tcspc::npint<T> {
493 return tcspc::npint<T>(numeric_limits<T>::signaling_NaN());
494 }
495};
496
497} // namespace std
Non-promoted integers.
Definition npint.hpp:33
constexpr auto operator<<=(npint< U > rhs) -> npint &
Bitwise left shift assignment operator.
Definition npint.hpp:168
constexpr auto operator-() const -> npint
Unary minus operator.
Definition npint.hpp:191
friend constexpr auto operator/(npint lhs, npint rhs) -> npint
Division operator.
Definition npint.hpp:213
constexpr auto operator++(int) -> npint
Postfix increment operator.
Definition npint.hpp:103
constexpr auto operator++() -> npint
Prefix increment operator.
Definition npint.hpp:100
constexpr auto operator<<=(std::integral auto rhs) -> npint &
Bitwise left shift assignment operator.
Definition npint.hpp:180
constexpr auto operator>>=(npint< U > rhs) -> npint &
Bitwise right shift assignment operator.
Definition npint.hpp:162
friend constexpr auto operator+(npint lhs, npint rhs) -> npint
Addition operator.
Definition npint.hpp:198
friend constexpr auto operator%(npint lhs, npint rhs) -> npint
Remainder operator.
Definition npint.hpp:218
friend constexpr auto operator>>(npint lhs, std::integral auto rhs) -> npint
Bitwise right shift operator.
Definition npint.hpp:263
friend constexpr auto operator&(npint lhs, npint rhs) noexcept -> npint
Bitwise AND operator.
Definition npint.hpp:225
friend constexpr auto operator>>(npint lhs, npint< U > rhs) -> npint
Bitwise right shift operator.
Definition npint.hpp:252
constexpr auto operator^=(npint rhs) noexcept -> npint &
Bitwise XOR assignment operator.
Definition npint.hpp:156
constexpr auto operator+=(npint rhs) -> npint &
Addition assignment operator.
Definition npint.hpp:114
constexpr auto operator--(int) -> npint
Postfix decrement operator.
Definition npint.hpp:109
friend constexpr auto operator*(npint lhs, npint rhs) -> npint
Multiplication operator.
Definition npint.hpp:208
friend constexpr auto operator<=>(npint lhs, npint rhs) noexcept -> std::strong_ordering=default
Three-way comparison operator.
friend constexpr auto operator<<(npint lhs, std::integral auto rhs) -> npint
Bitwise left shift operator.
Definition npint.hpp:257
constexpr auto operator%=(npint rhs) -> npint &
Remainder assignment operator.
Definition npint.hpp:138
constexpr auto operator~() const noexcept -> npint
Bitwise NOT operator.
Definition npint.hpp:240
constexpr npint() noexcept=default
Construct an uninitialized value.
constexpr auto operator--() -> npint
Prefix decrement operator.
Definition npint.hpp:106
T underlying_type
The underlying (scalar) integer type.
Definition npint.hpp:38
friend constexpr auto operator^(npint lhs, npint rhs) noexcept -> npint
Bitwise XOR operator.
Definition npint.hpp:235
constexpr npint(npint< U > const &other)
Explicitly convert from an npint with a different underlying integer type.
Definition npint.hpp:84
constexpr auto value() const noexcept -> T
Definition npint.hpp:68
friend constexpr auto operator<<(npint lhs, npint< U > rhs) -> npint
Bitwise left shift operator.
Definition npint.hpp:246
constexpr auto operator/=(npint rhs) -> npint &
Division assignment operator.
Definition npint.hpp:132
constexpr auto operator|=(npint rhs) noexcept -> npint &
Bitwise OR assignment operator.
Definition npint.hpp:150
constexpr auto operator>>=(std::integral auto rhs) -> npint &
Bitwise right shift assignment operator.
Definition npint.hpp:174
friend constexpr auto operator-(npint lhs, npint rhs) -> npint
Subtraction operator.
Definition npint.hpp:203
friend auto operator<<(std::ostream &strm, npint rhs) -> std::ostream &
Stream insertion operator.
Definition npint.hpp:277
friend constexpr auto operator|(npint lhs, npint rhs) noexcept -> npint
Bitwise OR operator.
Definition npint.hpp:230
friend auto operator>>(std::istream &strm, npint &rhs) -> std::istream &
Stream extraction operator.
Definition npint.hpp:282
constexpr auto operator*=(npint rhs) -> npint &
Multiplication assignment operator.
Definition npint.hpp:126
constexpr auto operator-=(npint rhs) -> npint &
Subtraction assignment operator.
Definition npint.hpp:120
constexpr auto operator&=(npint rhs) noexcept -> npint &
Bitwise AND assignment operator.
Definition npint.hpp:144
constexpr auto operator+() const noexcept -> npint
Unary plus operator.
Definition npint.hpp:188
npint< u32 > u32np
Non-promoted unsigned 32-bit integer.
Definition npint.hpp:306
npint< i64 > i64np
Non-promoted signed 64-bit integer.
Definition npint.hpp:341
npint< i32 > i32np
Non-promoted signed 32-bit integer.
Definition npint.hpp:334
npint< u8 > u8np
Non-promoted unsigned 8-bit integer.
Definition npint.hpp:292
npint< i8 > i8np
Non-promoted signed 8-bit integer.
Definition npint.hpp:320
npint< u64 > u64np
Non-promoted unsigned 64-bit integer.
Definition npint.hpp:313
npint< u16 > u16np
Non-promoted unsigned 16-bit integer.
Definition npint.hpp:299
npint< i16 > i16np
Non-promoted signed 16-bit integer.
Definition npint.hpp:327
std::int32_t i32
Short name for int32_t.
Definition int_types.hpp:42
std::uint64_t u64
Short name for uint64_t.
Definition int_types.hpp:33
std::uint8_t u8
Short name for uint8_t.
Definition int_types.hpp:24
std::int64_t i64
Short name for int64_t.
Definition int_types.hpp:45
std::uint16_t u16
Short name for uint16_t.
Definition int_types.hpp:27
std::int16_t i16
Short name for int16_t.
Definition int_types.hpp:39
std::int8_t i8
Short name for int8_t.
Definition int_types.hpp:36
std::uint32_t u32
Short name for uint32_t.
Definition int_types.hpp:30
User-defined literals for tcspc::npint.
Definition npint.hpp:348
libtcspc namespace.
Definition acquire.hpp:29