@@ -194,8 +194,6 @@ struct TDecimal {
194
194
return *this ;
195
195
}
196
196
197
- // TODO: implement '-' and '%'
198
-
199
197
friend TDecimal operator +(TDecimal left, TDecimal right) {
200
198
left += right;
201
199
return left;
@@ -212,5 +210,133 @@ struct TDecimal {
212
210
}
213
211
};
214
212
213
+ template <typename TRight>
214
+ class TDecimalMultiplicator {
215
+ protected:
216
+ const TInt128 Bound;
217
+
218
+ public:
219
+ TDecimalMultiplicator (
220
+ ui8 precision,
221
+ [[maybe_unused]] ui8 scale = 0 )
222
+ : Bound(GetDivider(precision))
223
+ {
224
+ }
225
+
226
+ TInt128 Do (TInt128 left, TRight right) const {
227
+ TInt128 mul = Mul (left, right);
228
+
229
+ if (mul > -Bound && mul < +Bound)
230
+ return mul;
231
+
232
+ return IsNan (mul) ? Nan () : (mul > 0 ? +Inf () : -Inf ());
233
+ }
234
+ };
235
+
236
+ template <>
237
+ class TDecimalMultiplicator <TInt128> {
238
+ protected:
239
+ const TInt128 Bound;
240
+ const TInt128 Divider;
241
+
242
+ public:
243
+ TDecimalMultiplicator (
244
+ ui8 precision,
245
+ ui8 scale)
246
+ : Bound(GetDivider(precision))
247
+ , Divider(GetDivider(scale))
248
+ { }
249
+
250
+ TInt128 Do (TInt128 left, TInt128 right) const {
251
+ TInt128 mul = Divider > 1 ?
252
+ MulAndDivNormalDivider (left, right, Divider):
253
+ Mul (left, right);
254
+
255
+ if (mul > -Bound && mul < +Bound)
256
+ return mul;
257
+
258
+ return IsNan (mul) ? Nan () : (mul > 0 ? +Inf () : -Inf ());
259
+ }
260
+ };
261
+
262
+ template <typename TRight>
263
+ class TDecimalDivisor {
264
+ public:
265
+ TDecimalDivisor (
266
+ [[maybe_unused]] ui8 precision = 0 ,
267
+ [[maybe_unused]] ui8 scale = 0 )
268
+ {
269
+ }
270
+
271
+ TInt128 Do (TInt128 left, TRight right) const {
272
+ return Div (left, right);
273
+ }
274
+ };
275
+
276
+ template <>
277
+ class TDecimalDivisor <TInt128> {
278
+ protected:
279
+ const TInt128 Bound;
280
+ const TInt128 Divider;
281
+
282
+ public:
283
+ TDecimalDivisor (
284
+ ui8 precision,
285
+ ui8 scale)
286
+ : Bound(GetDivider(precision))
287
+ , Divider(GetDivider(scale))
288
+ { }
289
+
290
+ TInt128 Do (TInt128 left, TInt128 right) const {
291
+ TInt128 div = MulAndDivNormalMultiplier (left, Divider, right);
292
+ if (div > -Bound && div < +Bound) {
293
+ return div ;
294
+ }
295
+
296
+ return IsNan (div ) ? Nan () : (div > 0 ? +Inf () : -Inf ());
297
+ }
298
+ };
299
+
300
+ template <typename TRight>
301
+ class TDecimalRemainder {
302
+ protected:
303
+ const TInt128 Bound;
304
+ const TInt128 Divider;
305
+
306
+ public:
307
+ TDecimalRemainder (
308
+ ui8 precision,
309
+ ui8 scale)
310
+ : Bound(NYql::NDecimal::GetDivider(precision - scale))
311
+ , Divider(NYql::NDecimal::GetDivider(scale))
312
+ { }
313
+
314
+ TInt128 Do (TInt128 left, TRight right) const {
315
+ if constexpr (std::is_signed<TRight>::value) {
316
+ if (right >= +Bound || right <= -Bound)
317
+ return left;
318
+ } else {
319
+ if (right >= Bound)
320
+ return left;
321
+ }
322
+
323
+ return Mod (left, Mul (Divider, right));
324
+ }
325
+ };
326
+
327
+ template <>
328
+ class TDecimalRemainder <TInt128> {
329
+ public:
330
+ TDecimalRemainder (
331
+ [[maybe_unused]] ui8 precision = 0 ,
332
+ [[maybe_unused]] ui8 scale = 0 )
333
+ {
334
+ }
335
+
336
+ TInt128 Do (TInt128 left, TInt128 right) const {
337
+ return NYql::NDecimal::Mod (left, right);
338
+ }
339
+ };
340
+
215
341
}
216
342
}
0 commit comments