Coverage Report

Created: 2026-09-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
27.4k
Value Add<int64_t>(int64_t v0, int64_t v1) {
39
27.4k
  auto sum = cel::internal::CheckedAdd(v0, v1);
40
27.4k
  if (!sum.ok()) {
41
10.0k
    return ErrorValue(sum.status());
42
10.0k
  }
43
17.4k
  return IntValue(*sum);
44
27.4k
}
45
46
template <>
47
5.32k
Value Add<uint64_t>(uint64_t v0, uint64_t v1) {
48
5.32k
  auto sum = cel::internal::CheckedAdd(v0, v1);
49
5.32k
  if (!sum.ok()) {
50
4.92k
    return ErrorValue(sum.status());
51
4.92k
  }
52
392
  return UintValue(*sum);
53
5.32k
}
54
55
template <>
56
1.09k
Value Add<double>(double v0, double v1) {
57
1.09k
  return DoubleValue(v0 + v1);
58
1.09k
}
59
60
template <class Type>
61
Value Sub(Type v0, Type v1);
62
63
template <>
64
252k
Value Sub<int64_t>(int64_t v0, int64_t v1) {
65
252k
  auto diff = cel::internal::CheckedSub(v0, v1);
66
252k
  if (!diff.ok()) {
67
8.61k
    return ErrorValue(diff.status());
68
8.61k
  }
69
243k
  return IntValue(*diff);
70
252k
}
71
72
template <>
73
6.48k
Value Sub<uint64_t>(uint64_t v0, uint64_t v1) {
74
6.48k
  auto diff = cel::internal::CheckedSub(v0, v1);
75
6.48k
  if (!diff.ok()) {
76
4.22k
    return ErrorValue(diff.status());
77
4.22k
  }
78
2.26k
  return UintValue(*diff);
79
6.48k
}
80
81
template <>
82
12.7k
Value Sub<double>(double v0, double v1) {
83
12.7k
  return DoubleValue(v0 - v1);
84
12.7k
}
85
86
template <class Type>
87
Value Mul(Type v0, Type v1);
88
89
template <>
90
33.5k
Value Mul<int64_t>(int64_t v0, int64_t v1) {
91
33.5k
  auto prod = cel::internal::CheckedMul(v0, v1);
92
33.5k
  if (!prod.ok()) {
93
18.2k
    return ErrorValue(prod.status());
94
18.2k
  }
95
15.3k
  return IntValue(*prod);
96
33.5k
}
97
98
template <>
99
1.31k
Value Mul<uint64_t>(uint64_t v0, uint64_t v1) {
100
1.31k
  auto prod = cel::internal::CheckedMul(v0, v1);
101
1.31k
  if (!prod.ok()) {
102
367
    return ErrorValue(prod.status());
103
367
  }
104
950
  return UintValue(*prod);
105
1.31k
}
106
107
template <>
108
256
Value Mul<double>(double v0, double v1) {
109
256
  return DoubleValue(v0 * v1);
110
256
}
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
201k
Value Div<int64_t>(int64_t v0, int64_t v1) {
119
201k
  auto quot = cel::internal::CheckedDiv(v0, v1);
120
201k
  if (!quot.ok()) {
121
28.1k
    return ErrorValue(quot.status());
122
28.1k
  }
123
173k
  return IntValue(*quot);
124
201k
}
125
126
// Division operations for integer types should check for
127
// division by 0
128
template <>
129
13.3k
Value Div<uint64_t>(uint64_t v0, uint64_t v1) {
130
13.3k
  auto quot = cel::internal::CheckedDiv(v0, v1);
131
13.3k
  if (!quot.ok()) {
132
4.82k
    return ErrorValue(quot.status());
133
4.82k
  }
134
8.57k
  return UintValue(*quot);
135
13.3k
}
136
137
template <>
138
65.8k
Value Div<double>(double v0, double v1) {
139
65.8k
  static_assert(std::numeric_limits<double>::is_iec559,
140
65.8k
                "Division by zero for doubles must be supported");
141
142
  // For double, division will result in +/- inf
143
65.8k
  return DoubleValue(v0 / v1);
144
65.8k
}
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
179k
Value Modulo<int64_t>(int64_t v0, int64_t v1) {
154
179k
  auto mod = cel::internal::CheckedMod(v0, v1);
155
179k
  if (!mod.ok()) {
156
2.74k
    return ErrorValue(mod.status());
157
2.74k
  }
158
176k
  return IntValue(*mod);
159
179k
}
160
161
template <>
162
1.86k
Value Modulo<uint64_t>(uint64_t v0, uint64_t v1) {
163
1.86k
  auto mod = cel::internal::CheckedMod(v0, v1);
164
1.86k
  if (!mod.ok()) {
165
1.51k
    return ErrorValue(mod.status());
166
1.51k
  }
167
345
  return UintValue(*mod);
168
1.86k
}
169
170
// Helper method
171
// Registers all arithmetic functions for template parameter type.
172
template <class Type>
173
74.4k
absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) {
174
74.4k
  using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>;
175
74.4k
  CEL_RETURN_IF_ERROR(registry.Register(
176
74.4k
      FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false),
177
74.4k
      FunctionAdapter::WrapFunction(&Add<Type>)));
178
179
74.4k
  CEL_RETURN_IF_ERROR(registry.Register(
180
74.4k
      FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false),
181
74.4k
      FunctionAdapter::WrapFunction(&Sub<Type>)));
182
183
74.4k
  CEL_RETURN_IF_ERROR(registry.Register(
184
74.4k
      FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false),
185
74.4k
      FunctionAdapter::WrapFunction(&Mul<Type>)));
186
187
74.4k
  return registry.Register(
188
74.4k
      FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false),
189
74.4k
      FunctionAdapter::WrapFunction(&Div<Type>));
190
74.4k
}
arithmetic_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterArithmeticFunctionsForType<long>(cel::FunctionRegistry&)
Line
Count
Source
173
24.8k
absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) {
174
24.8k
  using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>;
175
24.8k
  CEL_RETURN_IF_ERROR(registry.Register(
176
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false),
177
24.8k
      FunctionAdapter::WrapFunction(&Add<Type>)));
178
179
24.8k
  CEL_RETURN_IF_ERROR(registry.Register(
180
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false),
181
24.8k
      FunctionAdapter::WrapFunction(&Sub<Type>)));
182
183
24.8k
  CEL_RETURN_IF_ERROR(registry.Register(
184
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false),
185
24.8k
      FunctionAdapter::WrapFunction(&Mul<Type>)));
186
187
24.8k
  return registry.Register(
188
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false),
189
24.8k
      FunctionAdapter::WrapFunction(&Div<Type>));
190
24.8k
}
arithmetic_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterArithmeticFunctionsForType<unsigned long>(cel::FunctionRegistry&)
Line
Count
Source
173
24.8k
absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) {
174
24.8k
  using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>;
175
24.8k
  CEL_RETURN_IF_ERROR(registry.Register(
176
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false),
177
24.8k
      FunctionAdapter::WrapFunction(&Add<Type>)));
178
179
24.8k
  CEL_RETURN_IF_ERROR(registry.Register(
180
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false),
181
24.8k
      FunctionAdapter::WrapFunction(&Sub<Type>)));
182
183
24.8k
  CEL_RETURN_IF_ERROR(registry.Register(
184
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false),
185
24.8k
      FunctionAdapter::WrapFunction(&Mul<Type>)));
186
187
24.8k
  return registry.Register(
188
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false),
189
24.8k
      FunctionAdapter::WrapFunction(&Div<Type>));
190
24.8k
}
arithmetic_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterArithmeticFunctionsForType<double>(cel::FunctionRegistry&)
Line
Count
Source
173
24.8k
absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) {
174
24.8k
  using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>;
175
24.8k
  CEL_RETURN_IF_ERROR(registry.Register(
176
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false),
177
24.8k
      FunctionAdapter::WrapFunction(&Add<Type>)));
178
179
24.8k
  CEL_RETURN_IF_ERROR(registry.Register(
180
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false),
181
24.8k
      FunctionAdapter::WrapFunction(&Sub<Type>)));
182
183
24.8k
  CEL_RETURN_IF_ERROR(registry.Register(
184
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false),
185
24.8k
      FunctionAdapter::WrapFunction(&Mul<Type>)));
186
187
24.8k
  return registry.Register(
188
24.8k
      FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false),
189
24.8k
      FunctionAdapter::WrapFunction(&Div<Type>));
190
24.8k
}
191
192
}  // namespace
193
194
absl::Status RegisterArithmeticFunctions(FunctionRegistry& registry,
195
24.8k
                                         const RuntimeOptions& options) {
196
24.8k
  CEL_RETURN_IF_ERROR(RegisterArithmeticFunctionsForType<int64_t>(registry));
197
24.8k
  CEL_RETURN_IF_ERROR(RegisterArithmeticFunctionsForType<uint64_t>(registry));
198
24.8k
  CEL_RETURN_IF_ERROR(RegisterArithmeticFunctionsForType<double>(registry));
199
200
  // Modulo
201
24.8k
  CEL_RETURN_IF_ERROR(registry.Register(
202
24.8k
      BinaryFunctionAdapter<Value, int64_t, int64_t>::CreateDescriptor(
203
24.8k
          cel::builtin::kModulo, false),
204
24.8k
      BinaryFunctionAdapter<Value, int64_t, int64_t>::WrapFunction(
205
24.8k
          &Modulo<int64_t>)));
206
207
24.8k
  CEL_RETURN_IF_ERROR(registry.Register(
208
24.8k
      BinaryFunctionAdapter<Value, uint64_t, uint64_t>::CreateDescriptor(
209
24.8k
          cel::builtin::kModulo, false),
210
24.8k
      BinaryFunctionAdapter<Value, uint64_t, uint64_t>::WrapFunction(
211
24.8k
          &Modulo<uint64_t>)));
212
213
  // Negation group
214
24.8k
  CEL_RETURN_IF_ERROR(
215
24.8k
      registry.Register(UnaryFunctionAdapter<Value, int64_t>::CreateDescriptor(
216
24.8k
                            cel::builtin::kNeg, false),
217
24.8k
                        UnaryFunctionAdapter<Value, int64_t>::WrapFunction(
218
24.8k
                            [](int64_t value) -> Value {
219
24.8k
                              auto inv = cel::internal::CheckedNegation(value);
220
24.8k
                              if (!inv.ok()) {
221
24.8k
                                return ErrorValue(inv.status());
222
24.8k
                              }
223
24.8k
                              return IntValue(*inv);
224
24.8k
                            })));
225
226
24.8k
  return registry.Register(
227
24.8k
      UnaryFunctionAdapter<double, double>::CreateDescriptor(cel::builtin::kNeg,
228
24.8k
                                                             false),
229
24.8k
      UnaryFunctionAdapter<double, double>::WrapFunction(
230
24.8k
          [](double value) -> double { return -value; }));
231
24.8k
}
232
233
}  // namespace cel