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