1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <chrono> 20 #include <compare> 21 #include <numeric> 22 #include <ostream> 23 #include <type_traits> 24 25 namespace aidl { 26 namespace google { 27 namespace hardware { 28 namespace power { 29 namespace impl { 30 namespace pixel { 31 32 template <class C> 33 struct is_chrono_duration : std::false_type {}; 34 35 template <class Rep, class Per> 36 struct is_chrono_duration<std::chrono::duration<Rep, Per>> : std::true_type {}; 37 38 template <typename T> 39 concept chrono_duration = is_chrono_duration<T>::value; 40 41 template <typename T> 42 concept arithmetic = std::is_arithmetic<T>::value; 43 44 template <arithmetic T, typename W> 45 struct PhysicalQuantityType final { 46 constexpr PhysicalQuantityType() noexcept = default; 47 constexpr explicit PhysicalQuantityType(T const &value) noexcept : value_(value) {} 48 constexpr PhysicalQuantityType(PhysicalQuantityType const &) noexcept = default; 49 constexpr PhysicalQuantityType &operator=(PhysicalQuantityType const &) noexcept = default; 50 explicit constexpr inline operator T() const { return value_; } 51 52 inline constexpr auto operator+(PhysicalQuantityType const &other) const { 53 return PhysicalQuantityType(value_ + other.value_); 54 } 55 inline constexpr auto operator-(PhysicalQuantityType const &other) const { 56 return PhysicalQuantityType(value_ - other.value_); 57 } 58 template <arithmetic C> 59 inline constexpr auto operator*(C const &other) const { 60 return PhysicalQuantityType(value_ * other); 61 } 62 template <arithmetic C> 63 inline constexpr auto operator/(C const &other) const { 64 return PhysicalQuantityType(value_ / other); 65 } 66 inline constexpr bool operator==(PhysicalQuantityType const &other) const { 67 return value_ == other.value_; 68 } 69 inline constexpr auto operator<=>(PhysicalQuantityType const &other) const { 70 return value_ <=> other.value_; 71 } 72 73 private: 74 T value_; 75 }; 76 77 template <arithmetic C, arithmetic T, typename W> 78 inline auto operator*(C const &other, PhysicalQuantityType<T, W> type) { 79 return type * other; 80 } 81 82 using Cycles = PhysicalQuantityType<int, struct CyclesTag>; 83 using Frequency = PhysicalQuantityType<int, struct FrequencyTag>; 84 85 inline std::ostream &operator<<(std::ostream &os, Cycles cycles) { 86 return os << "Cycles(" << int(cycles) << ")"; 87 }; 88 89 inline std::ostream &operator<<(std::ostream &os, Frequency freq) { 90 return os << "Frequency(" << int(freq) << ")"; 91 }; 92 93 inline constexpr Frequency operator/(Cycles const &cycles, chrono_duration auto time) { 94 auto const fpchrono = std::chrono::duration<float, std::chrono::seconds::period>(time); 95 return Frequency(static_cast<int>(cycles) / fpchrono.count()); 96 } 97 98 constexpr Frequency operator""_hz(unsigned long long hz) { 99 return Frequency(hz); 100 } 101 102 inline constexpr Cycles operator*(Frequency const &freq, chrono_duration auto time) { 103 auto const fpchrono = std::chrono::duration<float, std::chrono::seconds::period>(time); 104 return Cycles(static_cast<int>(freq) * fpchrono.count()); 105 } 106 107 inline constexpr Cycles operator*(chrono_duration auto time, Frequency const &freq) { 108 return freq * time; 109 } 110 111 } // namespace pixel 112 } // namespace impl 113 } // namespace power 114 } // namespace hardware 115 } // namespace google 116 } // namespace aidl 117