Coverage Report

Created: 2026-10-09 06:57

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.h"
28
#include "runtime/function_registry.h"
29
#include "runtime/runtime_options.h"
30
31
namespace cel {
32
namespace {
33
34
// Template functions providing arithmetic operations
35
template <class Type>
36
Value Add(Type v0, Type v1, const Function::InvokeContext& context);
37
38
template <>
39
Value Add<int64_t>(int64_t v0, int64_t v1,
40
40.0k
                   const Function::InvokeContext& context) {
41
40.0k
  auto sum = cel::internal::CheckedAdd(v0, v1);
42
40.0k
  if (!sum.ok()) {
43
10.9k
    return ErrorValue::From(sum.status(), context.arena());
44
10.9k
  }
45
29.0k
  return IntValue(*sum);
46
40.0k
}
47
48
template <>
49
Value Add<uint64_t>(uint64_t v0, uint64_t v1,
50
144k
                    const Function::InvokeContext& context) {
51
144k
  auto sum = cel::internal::CheckedAdd(v0, v1);
52
144k
  if (!sum.ok()) {
53
144k
    return ErrorValue::From(sum.status(), context.arena());
54
144k
  }
55
222
  return UintValue(*sum);
56
144k
}
57
58
template <>
59
1.12k
Value Add<double>(double v0, double v1, const Function::InvokeContext&) {
60
1.12k
  return DoubleValue(v0 + v1);
61
1.12k
}
62
63
template <class Type>
64
Value Sub(Type v0, Type v1, const Function::InvokeContext& context);
65
66
template <>
67
Value Sub<int64_t>(int64_t v0, int64_t v1,
68
361k
                   const Function::InvokeContext& context) {
69
361k
  auto diff = cel::internal::CheckedSub(v0, v1);
70
361k
  if (!diff.ok()) {
71
10.8k
    return ErrorValue::From(diff.status(), context.arena());
72
10.8k
  }
73
350k
  return IntValue(*diff);
74
361k
}
75
76
template <>
77
Value Sub<uint64_t>(uint64_t v0, uint64_t v1,
78
196k
                    const Function::InvokeContext& context) {
79
196k
  auto diff = cel::internal::CheckedSub(v0, v1);
80
196k
  if (!diff.ok()) {
81
193k
    return ErrorValue::From(diff.status(), context.arena());
82
193k
  }
83
2.19k
  return UintValue(*diff);
84
196k
}
85
86
template <>
87
15.0k
Value Sub<double>(double v0, double v1, const Function::InvokeContext&) {
88
15.0k
  return DoubleValue(v0 - v1);
89
15.0k
}
90
91
template <class Type>
92
Value Mul(Type v0, Type v1, const Function::InvokeContext& context);
93
94
template <>
95
Value Mul<int64_t>(int64_t v0, int64_t v1,
96
64.6k
                   const Function::InvokeContext& context) {
97
64.6k
  auto prod = cel::internal::CheckedMul(v0, v1);
98
64.6k
  if (!prod.ok()) {
99
17.9k
    return ErrorValue::From(prod.status(), context.arena());
100
17.9k
  }
101
46.7k
  return IntValue(*prod);
102
64.6k
}
103
104
template <>
105
Value Mul<uint64_t>(uint64_t v0, uint64_t v1,
106
74.2k
                    const Function::InvokeContext& context) {
107
74.2k
  auto prod = cel::internal::CheckedMul(v0, v1);
108
74.2k
  if (!prod.ok()) {
109
71.8k
    return ErrorValue::From(prod.status(), context.arena());
110
71.8k
  }
111
2.42k
  return UintValue(*prod);
112
74.2k
}
113
114
template <>
115
1.81k
Value Mul<double>(double v0, double v1, const Function::InvokeContext&) {
116
1.81k
  return DoubleValue(v0 * v1);
117
1.81k
}
118
119
template <class Type>
120
Value Div(Type v0, Type v1, const Function::InvokeContext& context);
121
122
// Division operations for integer types should check for
123
// division by 0
124
template <>
125
Value Div<int64_t>(int64_t v0, int64_t v1,
126
272k
                   const Function::InvokeContext& context) {
127
272k
  auto quot = cel::internal::CheckedDiv(v0, v1);
128
272k
  if (!quot.ok()) {
129
59.3k
    return ErrorValue::From(quot.status(), context.arena());
130
59.3k
  }
131
212k
  return IntValue(*quot);
132
272k
}
133
134
// Division operations for integer types should check for
135
// division by 0
136
template <>
137
Value Div<uint64_t>(uint64_t v0, uint64_t v1,
138
1.18M
                    const Function::InvokeContext& context) {
139
1.18M
  auto quot = cel::internal::CheckedDiv(v0, v1);
140
1.18M
  if (!quot.ok()) {
141
417k
    return ErrorValue::From(quot.status(), context.arena());
142
417k
  }
143
767k
  return UintValue(*quot);
144
1.18M
}
145
146
template <>
147
73.1k
Value Div<double>(double v0, double v1, const Function::InvokeContext&) {
148
73.1k
  static_assert(std::numeric_limits<double>::is_iec559,
149
73.1k
                "Division by zero for doubles must be supported");
150
151
  // For double, division will result in +/- inf
152
73.1k
  return DoubleValue(v0 / v1);
153
73.1k
}
154
155
// Modulo operation
156
template <class Type>
157
Value Modulo(Type v0, Type v1, const Function::InvokeContext& context);
158
159
// Modulo operations for integer types should check for
160
// division by 0
161
template <>
162
Value Modulo<int64_t>(int64_t v0, int64_t v1,
163
151k
                      const Function::InvokeContext& context) {
164
151k
  auto mod = cel::internal::CheckedMod(v0, v1);
165
151k
  if (!mod.ok()) {
166
9.41k
    return ErrorValue::From(mod.status(), context.arena());
167
9.41k
  }
168
141k
  return IntValue(*mod);
169
151k
}
170
171
template <>
172
Value Modulo<uint64_t>(uint64_t v0, uint64_t v1,
173
78.8k
                       const Function::InvokeContext& context) {
174
78.8k
  auto mod = cel::internal::CheckedMod(v0, v1);
175
78.8k
  if (!mod.ok()) {
176
62.3k
    return ErrorValue::From(mod.status(), context.arena());
177
62.3k
  }
178
16.5k
  return UintValue(*mod);
179
78.8k
}
180
181
// Helper method
182
// Registers all arithmetic functions for template parameter type.
183
template <class Type>
184
68.1k
absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) {
185
68.1k
  using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>;
186
68.1k
  CEL_RETURN_IF_ERROR(registry.Register(
187
68.1k
      FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false),
188
68.1k
      FunctionAdapter::WrapFunction(&Add<Type>)));
189
190
68.1k
  CEL_RETURN_IF_ERROR(registry.Register(
191
68.1k
      FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false),
192
68.1k
      FunctionAdapter::WrapFunction(&Sub<Type>)));
193
194
68.1k
  CEL_RETURN_IF_ERROR(registry.Register(
195
68.1k
      FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false),
196
68.1k
      FunctionAdapter::WrapFunction(&Mul<Type>)));
197
198
68.1k
  return registry.Register(
199
68.1k
      FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false),
200
68.1k
      FunctionAdapter::WrapFunction(&Div<Type>));
201
68.1k
}
arithmetic_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterArithmeticFunctionsForType<long>(cel::FunctionRegistry&)
Line
Count
Source
184
22.7k
absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) {
185
22.7k
  using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>;
186
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
187
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false),
188
22.7k
      FunctionAdapter::WrapFunction(&Add<Type>)));
189
190
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
191
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false),
192
22.7k
      FunctionAdapter::WrapFunction(&Sub<Type>)));
193
194
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
195
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false),
196
22.7k
      FunctionAdapter::WrapFunction(&Mul<Type>)));
197
198
22.7k
  return registry.Register(
199
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false),
200
22.7k
      FunctionAdapter::WrapFunction(&Div<Type>));
201
22.7k
}
arithmetic_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterArithmeticFunctionsForType<unsigned long>(cel::FunctionRegistry&)
Line
Count
Source
184
22.7k
absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) {
185
22.7k
  using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>;
186
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
187
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false),
188
22.7k
      FunctionAdapter::WrapFunction(&Add<Type>)));
189
190
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
191
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false),
192
22.7k
      FunctionAdapter::WrapFunction(&Sub<Type>)));
193
194
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
195
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false),
196
22.7k
      FunctionAdapter::WrapFunction(&Mul<Type>)));
197
198
22.7k
  return registry.Register(
199
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false),
200
22.7k
      FunctionAdapter::WrapFunction(&Div<Type>));
201
22.7k
}
arithmetic_functions.cc:absl::lts_20260526::Status cel::(anonymous namespace)::RegisterArithmeticFunctionsForType<double>(cel::FunctionRegistry&)
Line
Count
Source
184
22.7k
absl::Status RegisterArithmeticFunctionsForType(FunctionRegistry& registry) {
185
22.7k
  using FunctionAdapter = cel::BinaryFunctionAdapter<Value, Type, Type>;
186
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
187
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kAdd, false),
188
22.7k
      FunctionAdapter::WrapFunction(&Add<Type>)));
189
190
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
191
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kSubtract, false),
192
22.7k
      FunctionAdapter::WrapFunction(&Sub<Type>)));
193
194
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
195
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kMultiply, false),
196
22.7k
      FunctionAdapter::WrapFunction(&Mul<Type>)));
197
198
22.7k
  return registry.Register(
199
22.7k
      FunctionAdapter::CreateDescriptor(cel::builtin::kDivide, false),
200
22.7k
      FunctionAdapter::WrapFunction(&Div<Type>));
201
22.7k
}
202
203
}  // namespace
204
205
absl::Status RegisterArithmeticFunctions(FunctionRegistry& registry,
206
22.7k
                                         const RuntimeOptions& options) {
207
22.7k
  CEL_RETURN_IF_ERROR(RegisterArithmeticFunctionsForType<int64_t>(registry));
208
22.7k
  CEL_RETURN_IF_ERROR(RegisterArithmeticFunctionsForType<uint64_t>(registry));
209
22.7k
  CEL_RETURN_IF_ERROR(RegisterArithmeticFunctionsForType<double>(registry));
210
211
  // Modulo
212
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
213
22.7k
      BinaryFunctionAdapter<Value, int64_t, int64_t>::CreateDescriptor(
214
22.7k
          cel::builtin::kModulo, false),
215
22.7k
      BinaryFunctionAdapter<Value, int64_t, int64_t>::WrapFunction(
216
22.7k
          &Modulo<int64_t>)));
217
218
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
219
22.7k
      BinaryFunctionAdapter<Value, uint64_t, uint64_t>::CreateDescriptor(
220
22.7k
          cel::builtin::kModulo, false),
221
22.7k
      BinaryFunctionAdapter<Value, uint64_t, uint64_t>::WrapFunction(
222
22.7k
          &Modulo<uint64_t>)));
223
224
  // Negation group
225
22.7k
  CEL_RETURN_IF_ERROR(registry.Register(
226
22.7k
      UnaryFunctionAdapter<Value, int64_t>::CreateDescriptor(cel::builtin::kNeg,
227
22.7k
                                                             false),
228
22.7k
      UnaryFunctionAdapter<Value, int64_t>::WrapFunction(
229
22.7k
          [](int64_t value, const Function::InvokeContext& context) -> Value {
230
22.7k
            auto inv = cel::internal::CheckedNegation(value);
231
22.7k
            if (!inv.ok()) {
232
22.7k
              return ErrorValue::From(inv.status(), context.arena());
233
22.7k
            }
234
22.7k
            return IntValue(*inv);
235
22.7k
          })));
236
237
22.7k
  return registry.Register(
238
22.7k
      UnaryFunctionAdapter<double, double>::CreateDescriptor(cel::builtin::kNeg,
239
22.7k
                                                             false),
240
22.7k
      UnaryFunctionAdapter<double, double>::WrapFunction(
241
31.9k
          [](double value) -> double { return -value; }));
242
22.7k
}
243
244
}  // namespace cel