/proc/self/cwd/runtime/standard/arithmetic_functions.cc
Line | Count | Source |
1 | | // Copyright 2023 Google LLC |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include "runtime/standard/arithmetic_functions.h" |
16 | | |
17 | | #include <cstdint> |
18 | | #include <limits> |
19 | | |
20 | | #include "absl/status/status.h" |
21 | | #include "absl/strings/string_view.h" |
22 | | #include "base/builtins.h" |
23 | | #include "base/function_adapter.h" |
24 | | #include "common/value.h" |
25 | | #include "internal/overflow.h" |
26 | | #include "internal/status_macros.h" |
27 | | #include "runtime/function_registry.h" |
28 | | #include "runtime/runtime_options.h" |
29 | | |
30 | | namespace cel { |
31 | | namespace { |
32 | | |
33 | | // Template functions providing arithmetic operations |
34 | | template <class Type> |
35 | | Value Add(Type v0, Type v1); |
36 | | |
37 | | template <> |
38 | 491 | Value Add<int64_t>(int64_t v0, int64_t v1) { |
39 | 491 | auto sum = cel::internal::CheckedAdd(v0, v1); |
40 | 491 | if (!sum.ok()) { |
41 | 36 | return ErrorValue(sum.status()); |
42 | 36 | } |
43 | 455 | return IntValue(*sum); |
44 | 491 | } |
45 | | |
46 | | template <> |
47 | 104 | Value Add<uint64_t>(uint64_t v0, uint64_t v1) { |
48 | 104 | auto sum = cel::internal::CheckedAdd(v0, v1); |
49 | 104 | if (!sum.ok()) { |
50 | 36 | return ErrorValue(sum.status()); |
51 | 36 | } |
52 | 68 | return UintValue(*sum); |
53 | 104 | } |
54 | | |
55 | | template <> |
56 | 142 | Value Add<double>(double v0, double v1) { |
57 | 142 | return DoubleValue(v0 + v1); |
58 | 142 | } |
59 | | |
60 | | template <class Type> |
61 | | Value Sub(Type v0, Type v1); |
62 | | |
63 | | template <> |
64 | 4.16k | Value Sub<int64_t>(int64_t v0, int64_t v1) { |
65 | 4.16k | auto diff = cel::internal::CheckedSub(v0, v1); |
66 | 4.16k | if (!diff.ok()) { |
67 | 72 | return ErrorValue(diff.status()); |
68 | 72 | } |
69 | 4.08k | return IntValue(*diff); |
70 | 4.16k | } |
71 | | |
72 | | template <> |
73 | 347 | Value Sub<uint64_t>(uint64_t v0, uint64_t v1) { |
74 | 347 | auto diff = cel::internal::CheckedSub(v0, v1); |
75 | 347 | if (!diff.ok()) { |
76 | 128 | return ErrorValue(diff.status()); |
77 | 128 | } |
78 | 219 | return UintValue(*diff); |
79 | 347 | } |
80 | | |
81 | | template <> |
82 | 923 | Value Sub<double>(double v0, double v1) { |
83 | 923 | return DoubleValue(v0 - v1); |
84 | 923 | } |
85 | | |
86 | | template <class Type> |
87 | | Value Mul(Type v0, Type v1); |
88 | | |
89 | | template <> |
90 | 521 | Value Mul<int64_t>(int64_t v0, int64_t v1) { |
91 | 521 | auto prod = cel::internal::CheckedMul(v0, v1); |
92 | 521 | if (!prod.ok()) { |
93 | 92 | return ErrorValue(prod.status()); |
94 | 92 | } |
95 | 429 | return IntValue(*prod); |
96 | 521 | } |
97 | | |
98 | | template <> |
99 | 275 | Value Mul<uint64_t>(uint64_t v0, uint64_t v1) { |
100 | 275 | auto prod = cel::internal::CheckedMul(v0, v1); |
101 | 275 | if (!prod.ok()) { |
102 | 69 | return ErrorValue(prod.status()); |
103 | 69 | } |
104 | 206 | return UintValue(*prod); |
105 | 275 | } |
106 | | |
107 | | template <> |
108 | 58 | Value Mul<double>(double v0, double v1) { |
109 | 58 | return DoubleValue(v0 * v1); |
110 | 58 | } |
111 | | |
112 | | template <class Type> |
113 | | Value Div(Type v0, Type v1); |
114 | | |
115 | | // Division operations for integer types should check for |
116 | | // division by 0 |
117 | | template <> |
118 | 1.23k | Value Div<int64_t>(int64_t v0, int64_t v1) { |
119 | 1.23k | auto quot = cel::internal::CheckedDiv(v0, v1); |
120 | 1.23k | if (!quot.ok()) { |
121 | 289 | return ErrorValue(quot.status()); |
122 | 289 | } |
123 | 944 | return IntValue(*quot); |
124 | 1.23k | } |
125 | | |
126 | | // Division operations for integer types should check for |
127 | | // division by 0 |
128 | | template <> |
129 | 508 | Value Div<uint64_t>(uint64_t v0, uint64_t v1) { |
130 | 508 | auto quot = cel::internal::CheckedDiv(v0, v1); |
131 | 508 | if (!quot.ok()) { |
132 | 247 | return ErrorValue(quot.status()); |
133 | 247 | } |
134 | 261 | return UintValue(*quot); |
135 | 508 | } |
136 | | |
137 | | template <> |
138 | 826 | Value Div<double>(double v0, double v1) { |
139 | 826 | static_assert(std::numeric_limits<double>::is_iec559, |
140 | 826 | "Division by zero for doubles must be supported"); |
141 | | |
142 | | // For double, division will result in +/- inf |
143 | 826 | return DoubleValue(v0 / v1); |
144 | 826 | } |
145 | | |
146 | | // Modulo operation |
147 | | template <class Type> |
148 | | Value Modulo(Type v0, Type v1); |
149 | | |
150 | | // Modulo operations for integer types should check for |
151 | | // division by 0 |
152 | | template <> |
153 | 2.00k | Value Modulo<int64_t>(int64_t v0, int64_t v1) { |
154 | 2.00k | auto mod = cel::internal::CheckedMod(v0, v1); |
155 | 2.00k | if (!mod.ok()) { |
156 | 631 | return ErrorValue(mod.status()); |
157 | 631 | } |
158 | 1.37k | return IntValue(*mod); |
159 | 2.00k | } |
160 | | |
161 | | template <> |
162 | 393 | Value Modulo<uint64_t>(uint64_t v0, uint64_t v1) { |
163 | 393 | auto mod = cel::internal::CheckedMod(v0, v1); |
164 | 393 | if (!mod.ok()) { |
165 | 143 | return ErrorValue(mod.status()); |
166 | 143 | } |
167 | 250 | return UintValue(*mod); |
168 | 393 | } |
169 | | |
170 | | // Helper method |
171 | | // Registers all arithmetic functions for template parameter type. |
172 | | template <class Type> |
173 | 43.5k | absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) { |
174 | 43.5k | using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>; |
175 | 43.5k | CEL_RETURN_IF_ERROR(registry.Register( |
176 | 43.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false), |
177 | 43.5k | FunctionAdapter::WrapFunction(&Add<Type>))); |
178 | | |
179 | 43.5k | CEL_RETURN_IF_ERROR(registry.Register( |
180 | 43.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false), |
181 | 43.5k | FunctionAdapter::WrapFunction(&Sub<Type>))); |
182 | | |
183 | 43.5k | CEL_RETURN_IF_ERROR(registry.Register( |
184 | 43.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false), |
185 | 43.5k | FunctionAdapter::WrapFunction(&Mul<Type>))); |
186 | | |
187 | 43.5k | return registry.Register( |
188 | 43.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false), |
189 | 43.5k | FunctionAdapter::WrapFunction(&Div<Type>)); |
190 | 43.5k | } arithmetic_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterArithmeticFunctionsForType<long>(cel::FunctionRegistry&) Line | Count | Source | 173 | 14.5k | absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) { | 174 | 14.5k | using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>; | 175 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( | 176 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false), | 177 | 14.5k | FunctionAdapter::WrapFunction(&Add<Type>))); | 178 | | | 179 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( | 180 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false), | 181 | 14.5k | FunctionAdapter::WrapFunction(&Sub<Type>))); | 182 | | | 183 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( | 184 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false), | 185 | 14.5k | FunctionAdapter::WrapFunction(&Mul<Type>))); | 186 | | | 187 | 14.5k | return registry.Register( | 188 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false), | 189 | 14.5k | FunctionAdapter::WrapFunction(&Div<Type>)); | 190 | 14.5k | } |
arithmetic_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterArithmeticFunctionsForType<unsigned long>(cel::FunctionRegistry&) Line | Count | Source | 173 | 14.5k | absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) { | 174 | 14.5k | using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>; | 175 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( | 176 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false), | 177 | 14.5k | FunctionAdapter::WrapFunction(&Add<Type>))); | 178 | | | 179 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( | 180 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false), | 181 | 14.5k | FunctionAdapter::WrapFunction(&Sub<Type>))); | 182 | | | 183 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( | 184 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false), | 185 | 14.5k | FunctionAdapter::WrapFunction(&Mul<Type>))); | 186 | | | 187 | 14.5k | return registry.Register( | 188 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false), | 189 | 14.5k | FunctionAdapter::WrapFunction(&Div<Type>)); | 190 | 14.5k | } |
arithmetic_functions.cc:absl::lts_20260107::Status cel::(anonymous namespace)::RegisterArithmeticFunctionsForType<double>(cel::FunctionRegistry&) Line | Count | Source | 173 | 14.5k | absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) { | 174 | 14.5k | using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>; | 175 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( | 176 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false), | 177 | 14.5k | FunctionAdapter::WrapFunction(&Add<Type>))); | 178 | | | 179 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( | 180 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false), | 181 | 14.5k | FunctionAdapter::WrapFunction(&Sub<Type>))); | 182 | | | 183 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( | 184 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false), | 185 | 14.5k | FunctionAdapter::WrapFunction(&Mul<Type>))); | 186 | | | 187 | 14.5k | return registry.Register( | 188 | 14.5k | FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false), | 189 | 14.5k | FunctionAdapter::WrapFunction(&Div<Type>)); | 190 | 14.5k | } |
|
191 | | |
192 | | } // namespace |
193 | | |
194 | | absl::Status RegisterArithmeticFunctions(FunctionRegistry& registry, |
195 | 14.5k | const RuntimeOptions& options) { |
196 | 14.5k | CEL_RETURN_IF_ERROR(RegisterArithmeticFunctionsForType<int64_t>(registry)); |
197 | 14.5k | CEL_RETURN_IF_ERROR(RegisterArithmeticFunctionsForType<uint64_t>(registry)); |
198 | 14.5k | CEL_RETURN_IF_ERROR(RegisterArithmeticFunctionsForType<double>(registry)); |
199 | | |
200 | | // Modulo |
201 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
202 | 14.5k | BinaryFunctionAdapter<Value, int64_t, int64_t>::CreateDescriptor( |
203 | 14.5k | cel::builtin::kModulo, false), |
204 | 14.5k | BinaryFunctionAdapter<Value, int64_t, int64_t>::WrapFunction( |
205 | 14.5k | &Modulo<int64_t>))); |
206 | | |
207 | 14.5k | CEL_RETURN_IF_ERROR(registry.Register( |
208 | 14.5k | BinaryFunctionAdapter<Value, uint64_t, uint64_t>::CreateDescriptor( |
209 | 14.5k | cel::builtin::kModulo, false), |
210 | 14.5k | BinaryFunctionAdapter<Value, uint64_t, uint64_t>::WrapFunction( |
211 | 14.5k | &Modulo<uint64_t>))); |
212 | | |
213 | | // Negation group |
214 | 14.5k | CEL_RETURN_IF_ERROR( |
215 | 14.5k | registry.Register(UnaryFunctionAdapter<Value, int64_t>::CreateDescriptor( |
216 | 14.5k | cel::builtin::kNeg, false), |
217 | 14.5k | UnaryFunctionAdapter<Value, int64_t>::WrapFunction( |
218 | 14.5k | [](int64_t value) -> Value { |
219 | 14.5k | auto inv = cel::internal::CheckedNegation(value); |
220 | 14.5k | if (!inv.ok()) { |
221 | 14.5k | return ErrorValue(inv.status()); |
222 | 14.5k | } |
223 | 14.5k | return IntValue(*inv); |
224 | 14.5k | }))); |
225 | | |
226 | 14.5k | return registry.Register( |
227 | 14.5k | UnaryFunctionAdapter<double, double>::CreateDescriptor(cel::builtin::kNeg, |
228 | 14.5k | false), |
229 | 14.5k | UnaryFunctionAdapter<double, double>::WrapFunction( |
230 | 14.5k | [](double value) -> double { return -value; })); |
231 | 14.5k | } |
232 | | |
233 | | } // namespace cel |