Mercurial > hg > sv-dependency-builds
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_ |