comparison osx/include/kj/units.h @ 49:3ab5a40c4e3b

Add Capnp and KJ builds for OSX
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 25 Oct 2016 14:48:23 +0100
parents
children 0994c39f1e94
comparison
equal deleted inserted replaced
48:9530b331f8c1 49:3ab5a40c4e3b
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2 // Licensed under the MIT License:
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21
22 // This file contains types which are intended to help detect incorrect usage at compile
23 // time, but should then be optimized down to basic primitives (usually, integers) by the
24 // compiler.
25
26 #ifndef KJ_UNITS_H_
27 #define KJ_UNITS_H_
28
29 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
30 #pragma GCC system_header
31 #endif
32
33 #include "common.h"
34
35 namespace kj {
36
37 // =======================================================================================
38 // IDs
39
40 template <typename UnderlyingType, typename Label>
41 struct Id {
42 // A type-safe numeric ID. `UnderlyingType` is the underlying integer representation. `Label`
43 // distinguishes this Id from other Id types. Sample usage:
44 //
45 // class Foo;
46 // typedef Id<uint, Foo> FooId;
47 //
48 // class Bar;
49 // typedef Id<uint, Bar> BarId;
50 //
51 // You can now use the FooId and BarId types without any possibility of accidentally using a
52 // FooId when you really wanted a BarId or vice-versa.
53
54 UnderlyingType value;
55
56 inline constexpr Id(): value(0) {}
57 inline constexpr explicit Id(int value): value(value) {}
58
59 inline constexpr bool operator==(const Id& other) const { return value == other.value; }
60 inline constexpr bool operator!=(const Id& other) const { return value != other.value; }
61 inline constexpr bool operator<=(const Id& other) const { return value <= other.value; }
62 inline constexpr bool operator>=(const Id& other) const { return value >= other.value; }
63 inline constexpr bool operator< (const Id& other) const { return value < other.value; }
64 inline constexpr bool operator> (const Id& other) const { return value > other.value; }
65 };
66
67 // =======================================================================================
68 // Quantity and UnitRatio -- implement unit analysis via the type system
69
70 template <typename T> constexpr bool isIntegral() { return false; }
71 template <> constexpr bool isIntegral<char>() { return true; }
72 template <> constexpr bool isIntegral<signed char>() { return true; }
73 template <> constexpr bool isIntegral<short>() { return true; }
74 template <> constexpr bool isIntegral<int>() { return true; }
75 template <> constexpr bool isIntegral<long>() { return true; }
76 template <> constexpr bool isIntegral<long long>() { return true; }
77 template <> constexpr bool isIntegral<unsigned char>() { return true; }
78 template <> constexpr bool isIntegral<unsigned short>() { return true; }
79 template <> constexpr bool isIntegral<unsigned int>() { return true; }
80 template <> constexpr bool isIntegral<unsigned long>() { return true; }
81 template <> constexpr bool isIntegral<unsigned long long>() { return true; }
82
83 template <typename Number, typename Unit1, typename Unit2>
84 class UnitRatio {
85 // A multiplier used to convert Quantities of one unit to Quantities of another unit. See
86 // Quantity, below.
87 //
88 // Construct this type by dividing one Quantity by another of a different unit. Use this type
89 // by multiplying it by a Quantity, or dividing a Quantity by it.
90
91 static_assert(isIntegral<Number>(), "Underlying type for UnitRatio must be integer.");
92
93 public:
94 inline UnitRatio() {}
95
96 constexpr explicit UnitRatio(Number unit1PerUnit2): unit1PerUnit2(unit1PerUnit2) {}
97 // This constructor was intended to be private, but GCC complains about it being private in a
98 // bunch of places that don't appear to even call it, so I made it public. Oh well.
99
100 template <typename OtherNumber>
101 inline constexpr UnitRatio(const UnitRatio<OtherNumber, Unit1, Unit2>& other)
102 : unit1PerUnit2(other.unit1PerUnit2) {}
103
104 template <typename OtherNumber>
105 inline constexpr UnitRatio<decltype(Number(1)+OtherNumber(1)), Unit1, Unit2>
106 operator+(UnitRatio<OtherNumber, Unit1, Unit2> other) const {
107 return UnitRatio<decltype(Number(1)+OtherNumber(1)), Unit1, Unit2>(
108 unit1PerUnit2 + other.unit1PerUnit2);
109 }
110 template <typename OtherNumber>
111 inline constexpr UnitRatio<decltype(Number(1)-OtherNumber(1)), Unit1, Unit2>
112 operator-(UnitRatio<OtherNumber, Unit1, Unit2> other) const {
113 return UnitRatio<decltype(Number(1)-OtherNumber(1)), Unit1, Unit2>(
114 unit1PerUnit2 - other.unit1PerUnit2);
115 }
116
117 template <typename OtherNumber, typename Unit3>
118 inline constexpr UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit3, Unit2>
119 operator*(UnitRatio<OtherNumber, Unit3, Unit1> other) const {
120 // U1 / U2 * U3 / U1 = U3 / U2
121 return UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit3, Unit2>(
122 unit1PerUnit2 * other.unit1PerUnit2);
123 }
124 template <typename OtherNumber, typename Unit3>
125 inline constexpr UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit1, Unit3>
126 operator*(UnitRatio<OtherNumber, Unit2, Unit3> other) const {
127 // U1 / U2 * U2 / U3 = U1 / U3
128 return UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit1, Unit3>(
129 unit1PerUnit2 * other.unit1PerUnit2);
130 }
131
132 template <typename OtherNumber, typename Unit3>
133 inline constexpr UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit3, Unit2>
134 operator/(UnitRatio<OtherNumber, Unit1, Unit3> other) const {
135 // (U1 / U2) / (U1 / U3) = U3 / U2
136 return UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit3, Unit2>(
137 unit1PerUnit2 / other.unit1PerUnit2);
138 }
139 template <typename OtherNumber, typename Unit3>
140 inline constexpr UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit1, Unit3>
141 operator/(UnitRatio<OtherNumber, Unit3, Unit2> other) const {
142 // (U1 / U2) / (U3 / U2) = U1 / U3
143 return UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit1, Unit3>(
144 unit1PerUnit2 / other.unit1PerUnit2);
145 }
146
147 template <typename OtherNumber>
148 inline decltype(Number(1) / OtherNumber(1))
149 operator/(UnitRatio<OtherNumber, Unit1, Unit2> other) const {
150 return unit1PerUnit2 / other.unit1PerUnit2;
151 }
152
153 inline bool operator==(UnitRatio other) const { return unit1PerUnit2 == other.unit1PerUnit2; }
154 inline bool operator!=(UnitRatio other) const { return unit1PerUnit2 != other.unit1PerUnit2; }
155
156 private:
157 Number unit1PerUnit2;
158
159 template <typename OtherNumber, typename OtherUnit>
160 friend class Quantity;
161 template <typename OtherNumber, typename OtherUnit1, typename OtherUnit2>
162 friend class UnitRatio;
163
164 template <typename N1, typename N2, typename U1, typename U2>
165 friend inline constexpr UnitRatio<decltype(N1(1) * N2(1)), U1, U2>
166 operator*(N1, UnitRatio<N2, U1, U2>);
167 };
168
169 template <typename N1, typename N2, typename U1, typename U2>
170 inline constexpr UnitRatio<decltype(N1(1) * N2(1)), U1, U2>
171 operator*(N1 n, UnitRatio<N2, U1, U2> r) {
172 return UnitRatio<decltype(N1(1) * N2(1)), U1, U2>(n * r.unit1PerUnit2);
173 }
174
175 template <typename Number, typename Unit>
176 class Quantity {
177 // A type-safe numeric quantity, specified in terms of some unit. Two Quantities cannot be used
178 // in arithmetic unless they use the same unit. The `Unit` type parameter is only used to prevent
179 // accidental mixing of units; this type is never instantiated and can very well be incomplete.
180 // `Number` is the underlying primitive numeric type.
181 //
182 // Quantities support most basic arithmetic operators, intelligently handling units, and
183 // automatically casting the underlying type in the same way that the compiler would.
184 //
185 // To convert a primitive number to a Quantity, multiply it by unit<Quantity<N, U>>().
186 // To convert a Quantity to a primitive number, divide it by unit<Quantity<N, U>>().
187 // To convert a Quantity of one unit to another unit, multiply or divide by a UnitRatio.
188 //
189 // The Quantity class is not well-suited to hardcore physics as it does not allow multiplying
190 // one quantity by another. For example, multiplying meters by meters won't get you square
191 // meters; it will get you a compiler error. It would be interesting to see if template
192 // metaprogramming could properly deal with such things but this isn't needed for the present
193 // use case.
194 //
195 // Sample usage:
196 //
197 // class SecondsLabel;
198 // typedef Quantity<double, SecondsLabel> Seconds;
199 // constexpr Seconds SECONDS = unit<Seconds>();
200 //
201 // class MinutesLabel;
202 // typedef Quantity<double, MinutesLabel> Minutes;
203 // constexpr Minutes MINUTES = unit<Minutes>();
204 //
205 // constexpr UnitRatio<double, SecondsLabel, MinutesLabel> SECONDS_PER_MINUTE =
206 // 60 * SECONDS / MINUTES;
207 //
208 // void waitFor(Seconds seconds) {
209 // sleep(seconds / SECONDS);
210 // }
211 // void waitFor(Minutes minutes) {
212 // waitFor(minutes * SECONDS_PER_MINUTE);
213 // }
214 //
215 // void waitThreeMinutes() {
216 // waitFor(3 * MINUTES);
217 // }
218
219 static_assert(isIntegral<Number>(), "Underlying type for Quantity must be integer.");
220
221 public:
222 inline constexpr Quantity() {}
223
224 inline constexpr Quantity(MaxValue_): value(maxValue) {}
225 inline constexpr Quantity(MinValue_): value(minValue) {}
226 // Allow initialization from maxValue and minValue.
227 // TODO(msvc): decltype(maxValue) and decltype(minValue) deduce unknown-type for these function
228 // parameters, causing the compiler to complain of a duplicate constructor definition, so we
229 // specify MaxValue_ and MinValue_ types explicitly.
230
231 inline explicit constexpr Quantity(Number value): value(value) {}
232 // This constructor was intended to be private, but GCC complains about it being private in a
233 // bunch of places that don't appear to even call it, so I made it public. Oh well.
234
235 template <typename OtherNumber>
236 inline constexpr Quantity(const Quantity<OtherNumber, Unit>& other)
237 : value(other.value) {}
238
239 template <typename OtherNumber>
240 inline constexpr Quantity<decltype(Number(1) + OtherNumber(1)), Unit>
241 operator+(const Quantity<OtherNumber, Unit>& other) const {
242 return Quantity<decltype(Number(1) + OtherNumber(1)), Unit>(value + other.value);
243 }
244 template <typename OtherNumber>
245 inline constexpr Quantity<decltype(Number(1) - OtherNumber(1)), Unit>
246 operator-(const Quantity<OtherNumber, Unit>& other) const {
247 return Quantity<decltype(Number(1) - OtherNumber(1)), Unit>(value - other.value);
248 }
249 template <typename OtherNumber>
250 inline constexpr Quantity<decltype(Number(1) * OtherNumber(1)), Unit>
251 operator*(OtherNumber other) const {
252 static_assert(isIntegral<OtherNumber>(), "Multiplied Quantity by non-integer.");
253 return Quantity<decltype(Number(1) * other), Unit>(value * other);
254 }
255 template <typename OtherNumber>
256 inline constexpr Quantity<decltype(Number(1) / OtherNumber(1)), Unit>
257 operator/(OtherNumber other) const {
258 static_assert(isIntegral<OtherNumber>(), "Divided Quantity by non-integer.");
259 return Quantity<decltype(Number(1) / other), Unit>(value / other);
260 }
261 template <typename OtherNumber>
262 inline constexpr decltype(Number(1) / OtherNumber(1))
263 operator/(const Quantity<OtherNumber, Unit>& other) const {
264 return value / other.value;
265 }
266 template <typename OtherNumber>
267 inline constexpr decltype(Number(1) % OtherNumber(1))
268 operator%(const Quantity<OtherNumber, Unit>& other) const {
269 return value % other.value;
270 }
271
272 template <typename OtherNumber, typename OtherUnit>
273 inline constexpr Quantity<decltype(Number(1) * OtherNumber(1)), OtherUnit>
274 operator*(const UnitRatio<OtherNumber, OtherUnit, Unit>& ratio) const {
275 return Quantity<decltype(Number(1) * OtherNumber(1)), OtherUnit>(
276 value * ratio.unit1PerUnit2);
277 }
278 template <typename OtherNumber, typename OtherUnit>
279 inline constexpr Quantity<decltype(Number(1) / OtherNumber(1)), OtherUnit>
280 operator/(const UnitRatio<OtherNumber, Unit, OtherUnit>& ratio) const {
281 return Quantity<decltype(Number(1) / OtherNumber(1)), OtherUnit>(
282 value / ratio.unit1PerUnit2);
283 }
284 template <typename OtherNumber, typename OtherUnit>
285 inline constexpr Quantity<decltype(Number(1) % OtherNumber(1)), Unit>
286 operator%(const UnitRatio<OtherNumber, Unit, OtherUnit>& ratio) const {
287 return Quantity<decltype(Number(1) % OtherNumber(1)), Unit>(
288 value % ratio.unit1PerUnit2);
289 }
290 template <typename OtherNumber, typename OtherUnit>
291 inline constexpr UnitRatio<decltype(Number(1) / OtherNumber(1)), Unit, OtherUnit>
292 operator/(const Quantity<OtherNumber, OtherUnit>& other) const {
293 return UnitRatio<decltype(Number(1) / OtherNumber(1)), Unit, OtherUnit>(value / other.value);
294 }
295
296 template <typename OtherNumber>
297 inline constexpr bool operator==(const Quantity<OtherNumber, Unit>& other) const {
298 return value == other.value;
299 }
300 template <typename OtherNumber>
301 inline constexpr bool operator!=(const Quantity<OtherNumber, Unit>& other) const {
302 return value != other.value;
303 }
304 template <typename OtherNumber>
305 inline constexpr bool operator<=(const Quantity<OtherNumber, Unit>& other) const {
306 return value <= other.value;
307 }
308 template <typename OtherNumber>
309 inline constexpr bool operator>=(const Quantity<OtherNumber, Unit>& other) const {
310 return value >= other.value;
311 }
312 template <typename OtherNumber>
313 inline constexpr bool operator<(const Quantity<OtherNumber, Unit>& other) const {
314 return value < other.value;
315 }
316 template <typename OtherNumber>
317 inline constexpr bool operator>(const Quantity<OtherNumber, Unit>& other) const {
318 return value > other.value;
319 }
320
321 template <typename OtherNumber>
322 inline Quantity& operator+=(const Quantity<OtherNumber, Unit>& other) {
323 value += other.value;
324 return *this;
325 }
326 template <typename OtherNumber>
327 inline Quantity& operator-=(const Quantity<OtherNumber, Unit>& other) {
328 value -= other.value;
329 return *this;
330 }
331 template <typename OtherNumber>
332 inline Quantity& operator*=(OtherNumber other) {
333 value *= other;
334 return *this;
335 }
336 template <typename OtherNumber>
337 inline Quantity& operator/=(OtherNumber other) {
338 value /= other.value;
339 return *this;
340 }
341
342 private:
343 Number value;
344
345 template <typename OtherNumber, typename OtherUnit>
346 friend class Quantity;
347
348 template <typename Number1, typename Number2, typename Unit2>
349 friend inline constexpr auto operator*(Number1 a, Quantity<Number2, Unit2> b)
350 -> Quantity<decltype(Number1(1) * Number2(1)), Unit2>;
351
352 template <typename T>
353 friend inline constexpr T unit();
354 };
355
356 template <typename T>
357 inline constexpr T unit() { return T(1); }
358 // unit<Quantity<T, U>>() returns a Quantity of value 1. It also, intentionally, works on basic
359 // numeric types.
360
361 template <typename Number1, typename Number2, typename Unit>
362 inline constexpr auto operator*(Number1 a, Quantity<Number2, Unit> b)
363 -> Quantity<decltype(Number1(1) * Number2(1)), Unit> {
364 return Quantity<decltype(Number1(1) * Number2(1)), Unit>(a * b.value);
365 }
366
367 template <typename Number1, typename Number2, typename Unit, typename Unit2>
368 inline constexpr auto operator*(UnitRatio<Number1, Unit2, Unit> ratio,
369 Quantity<Number2, Unit> measure)
370 -> decltype(measure * ratio) {
371 return measure * ratio;
372 }
373
374 // =======================================================================================
375 // Absolute measures
376
377 template <typename T, typename Label>
378 class Absolute {
379 // Wraps some other value -- typically a Quantity -- but represents a value measured based on
380 // some absolute origin. For example, if `Duration` is a type representing a time duration,
381 // Absolute<Duration, UnixEpoch> might be a calendar date.
382 //
383 // Since Absolute represents measurements relative to some arbitrary origin, the only sensible
384 // arithmetic to perform on them is addition and subtraction.
385
386 // TODO(someday): Do the same automatic expansion of integer width that Quantity does? Doesn't
387 // matter for our time use case, where we always use 64-bit anyway. Note that fixing this
388 // would implicitly allow things like multiplying an Absolute by a UnitRatio to change its
389 // units, which is actually totally logical and kind of neat.
390
391 public:
392 inline constexpr Absolute operator+(const T& other) const { return Absolute(value + other); }
393 inline constexpr Absolute operator-(const T& other) const { return Absolute(value - other); }
394 inline constexpr T operator-(const Absolute& other) const { return value - other.value; }
395
396 inline Absolute& operator+=(const T& other) { value += other; return *this; }
397 inline Absolute& operator-=(const T& other) { value -= other; return *this; }
398
399 inline constexpr bool operator==(const Absolute& other) const { return value == other.value; }
400 inline constexpr bool operator!=(const Absolute& other) const { return value != other.value; }
401 inline constexpr bool operator<=(const Absolute& other) const { return value <= other.value; }
402 inline constexpr bool operator>=(const Absolute& other) const { return value >= other.value; }
403 inline constexpr bool operator< (const Absolute& other) const { return value < other.value; }
404 inline constexpr bool operator> (const Absolute& other) const { return value > other.value; }
405
406 private:
407 T value;
408
409 explicit constexpr Absolute(T value): value(value) {}
410
411 template <typename U>
412 friend inline constexpr U origin();
413 };
414
415 template <typename T, typename Label>
416 inline constexpr Absolute<T, Label> operator+(const T& a, const Absolute<T, Label>& b) {
417 return b + a;
418 }
419
420 template <typename T> struct UnitOf_ { typedef T Type; };
421 template <typename T, typename Label> struct UnitOf_<Absolute<T, Label>> { typedef T Type; };
422 template <typename T>
423 using UnitOf = typename UnitOf_<T>::Type;
424 // UnitOf<Absolute<T, U>> is T. UnitOf<AnythingElse> is AnythingElse.
425
426 template <typename T>
427 inline constexpr T origin() { return T(0 * unit<UnitOf<T>>()); }
428 // origin<Absolute<T, U>>() returns an Absolute of value 0. It also, intentionally, works on basic
429 // numeric types.
430
431 } // namespace kj
432
433 #endif // KJ_UNITS_H_