1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_UNITS_H
3 #define _LINUX_UNITS_H
4
5 #include <linux/bits.h>
6 #include <linux/math.h>
7
8 /* Metric prefixes in accordance with Système international (d'unités) */
9 #define PETA 1000000000000000ULL
10 #define TERA 1000000000000ULL
11 #define GIGA 1000000000UL
12 #define MEGA 1000000UL
13 #define KILO 1000UL
14 #define HECTO 100UL
15 #define DECA 10UL
16 #define DECI 10UL
17 #define CENTI 100UL
18 #define MILLI 1000UL
19 #define MICRO 1000000UL
20 #define NANO 1000000000UL
21 #define PICO 1000000000000ULL
22 #define FEMTO 1000000000000000ULL
23
24 /*
25 * Percentage and related scaling units
26 *
27 * These macros define scaling factors used to convert between ratio and
28 * percentage-based representations with different decimal resolutions.
29 * They are used for precise fractional calculations in engineering, finance,
30 * and measurement applications.
31 *
32 * Examples:
33 * 1% = 0.01 = 1 / PERCENT
34 * 0.1% = 0.001 = 1 / PERMILLE
35 * 0.01% = 0.0001 = 1 / PERMYRIAD (1 basis point)
36 * 0.001% = 0.00001 = 1 / PERCENTMILLE
37 */
38 #define PERCENT 100
39 #define PERMILLE 1000
40 #define PERMYRIAD 10000
41 #define PERCENTMILLE 100000
42
43 #define NANOHZ_PER_HZ 1000000000UL
44 #define MICROHZ_PER_HZ 1000000UL
45 #define MILLIHZ_PER_HZ 1000UL
46
47 /* Hz based multipliers */
48 #define HZ_PER_KHZ 1000UL
49 #define HZ_PER_MHZ 1000000UL
50 #define HZ_PER_GHZ 1000000000UL
51
52 /* kHz based multipliers */
53 #define KHZ_PER_MHZ 1000UL
54 #define KHZ_PER_GHZ 1000000UL
55
56 #define MILLIWATT_PER_WATT 1000UL
57 #define MICROWATT_PER_MILLIWATT 1000UL
58 #define MICROWATT_PER_WATT 1000000UL
59
60 #define MICROJOULE_PER_JOULE 1000000UL
61 #define NANOJOULE_PER_JOULE 1000000000UL
62
63 #define BYTES_PER_KBIT (KILO / BITS_PER_BYTE)
64 #define BYTES_PER_MBIT (MEGA / BITS_PER_BYTE)
65 #define BYTES_PER_GBIT (GIGA / BITS_PER_BYTE)
66
67 #define ABSOLUTE_ZERO_MILLICELSIUS -273150
68
milli_kelvin_to_millicelsius(long t)69 static inline long milli_kelvin_to_millicelsius(long t)
70 {
71 return t + ABSOLUTE_ZERO_MILLICELSIUS;
72 }
73
millicelsius_to_milli_kelvin(long t)74 static inline long millicelsius_to_milli_kelvin(long t)
75 {
76 return t - ABSOLUTE_ZERO_MILLICELSIUS;
77 }
78
79 #define MILLIDEGREE_PER_DEGREE 1000
80 #define MILLIDEGREE_PER_DECIDEGREE 100
81
kelvin_to_millicelsius(long t)82 static inline long kelvin_to_millicelsius(long t)
83 {
84 return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DEGREE);
85 }
86
millicelsius_to_kelvin(long t)87 static inline long millicelsius_to_kelvin(long t)
88 {
89 t = millicelsius_to_milli_kelvin(t);
90
91 return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE);
92 }
93
deci_kelvin_to_celsius(long t)94 static inline long deci_kelvin_to_celsius(long t)
95 {
96 t = milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE);
97
98 return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE);
99 }
100
celsius_to_deci_kelvin(long t)101 static inline long celsius_to_deci_kelvin(long t)
102 {
103 t = millicelsius_to_milli_kelvin(t * MILLIDEGREE_PER_DEGREE);
104
105 return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE);
106 }
107
108 /**
109 * deci_kelvin_to_millicelsius_with_offset - convert Kelvin to Celsius
110 * @t: temperature value in decidegrees Kelvin
111 * @offset: difference between Kelvin and Celsius in millidegrees
112 *
113 * Return: temperature value in millidegrees Celsius
114 */
deci_kelvin_to_millicelsius_with_offset(long t,long offset)115 static inline long deci_kelvin_to_millicelsius_with_offset(long t, long offset)
116 {
117 return t * MILLIDEGREE_PER_DECIDEGREE - offset;
118 }
119
deci_kelvin_to_millicelsius(long t)120 static inline long deci_kelvin_to_millicelsius(long t)
121 {
122 return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE);
123 }
124
millicelsius_to_deci_kelvin(long t)125 static inline long millicelsius_to_deci_kelvin(long t)
126 {
127 t = millicelsius_to_milli_kelvin(t);
128
129 return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE);
130 }
131
kelvin_to_celsius(long t)132 static inline long kelvin_to_celsius(long t)
133 {
134 return t + DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS,
135 MILLIDEGREE_PER_DEGREE);
136 }
137
celsius_to_kelvin(long t)138 static inline long celsius_to_kelvin(long t)
139 {
140 return t - DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS,
141 MILLIDEGREE_PER_DEGREE);
142 }
143
144 #endif /* _LINUX_UNITS_H */
145