@@ -199,77 +199,6 @@ enum class RoundingMode
199199#endif
200200};
201201
202- /* * Rounding functions for decimal values
203- */
204-
205- template <typename T, RoundingMode rounding_mode, ScaleMode scale_mode, typename OutputType>
206- struct DecimalRoundingComputation
207- {
208- static_assert (IsDecimal<T>);
209- static const size_t data_count = 1 ;
210- static size_t prepare (size_t scale) { return scale; }
211- // compute need decimal_scale to interpret decimals
212- static inline void compute (
213- const T * __restrict in,
214- size_t scale,
215- OutputType * __restrict out,
216- ScaleType decimal_scale)
217- {
218- static_assert (std::is_same_v<T, OutputType> || std::is_same_v<OutputType, Int64>);
219- Float64 val = in->template toFloat <Float64>(decimal_scale);
220-
221- if constexpr (scale_mode == ScaleMode::Positive)
222- {
223- val = val * scale;
224- }
225- else if constexpr (scale_mode == ScaleMode::Negative)
226- {
227- val = val / scale;
228- }
229-
230- if constexpr (rounding_mode == RoundingMode::Round)
231- {
232- val = round (val);
233- }
234- else if constexpr (rounding_mode == RoundingMode::Floor)
235- {
236- val = floor (val);
237- }
238- else if constexpr (rounding_mode == RoundingMode::Ceil)
239- {
240- val = ceil (val);
241- }
242- else if constexpr (rounding_mode == RoundingMode::Trunc)
243- {
244- val = trunc (val);
245- }
246-
247-
248- if constexpr (scale_mode == ScaleMode::Positive)
249- {
250- val = val / scale;
251- }
252- else if constexpr (scale_mode == ScaleMode::Negative)
253- {
254- val = val * scale;
255- }
256-
257- if constexpr (std::is_same_v<T, OutputType>)
258- {
259- *out = ToDecimal<Float64, T>(val, decimal_scale);
260- }
261- else if constexpr (std::is_same_v<OutputType, Int64>)
262- {
263- *out = static_cast <Int64>(val);
264- }
265- else
266- {
267- ; // never arrived here
268- }
269- }
270- };
271-
272-
273202/* * Rounding functions for integer values.
274203 */
275204template <typename T, RoundingMode rounding_mode, ScaleMode scale_mode>
@@ -333,6 +262,88 @@ struct IntegerRoundingComputation
333262 }
334263};
335264
265+ /* * Rounding functions for decimal values
266+ */
267+
268+ template <typename T, RoundingMode rounding_mode, ScaleMode scale_mode, typename OutputType>
269+ struct DecimalRoundingComputation
270+ {
271+ static_assert (IsDecimal<T>);
272+ static const size_t data_count = 1 ;
273+ static size_t prepare (size_t scale) { return scale; }
274+ // compute need decimal_scale to interpret decimals
275+ static inline void compute (
276+ const T * __restrict in,
277+ size_t scale,
278+ OutputType * __restrict out,
279+ ScaleType decimal_scale)
280+ {
281+ static_assert (std::is_same_v<T, OutputType> || std::is_same_v<OutputType, Int64>);
282+
283+ using NativeType = T::NativeType;
284+ using Op = IntegerRoundingComputation<NativeType, rounding_mode, ScaleMode::Negative>;
285+ size_t scale_factor = pow (10 , decimal_scale);
286+
287+ if constexpr (scale_mode == ScaleMode::Zero)
288+ {
289+ if (scale != 1 )
290+ {
291+ throw Exception (
292+ " Logical error: unexpected 'scale' parameter passed to DecimalRoundingComputation" ,
293+ ErrorCodes::LOGICAL_ERROR);
294+ }
295+
296+ if constexpr (std::is_same_v<T, OutputType>)
297+ {
298+ Op::compute (&in->value , scale_factor, &out->value );
299+ }
300+ else if constexpr (std::is_same_v<OutputType, Int64>)
301+ {
302+ if constexpr (!std::is_same_v<T, Decimal256>)
303+ {
304+ if constexpr (rounding_mode == RoundingMode::Floor)
305+ {
306+ auto x = in->value ;
307+ if (x < 0 )
308+ x -= scale_factor - 1 ;
309+ *out = x / scale_factor;
310+ }
311+ else if constexpr (rounding_mode == RoundingMode::Ceil)
312+ {
313+ auto x = in->value ;
314+ if (x >= 0 )
315+ x += scale_factor - 1 ;
316+ *out = x / scale_factor;
317+ }
318+ else
319+ {
320+ throw Exception (
321+ " Logical error: unexpected 'rounding_mode' parameter passed to DecimalRoundingComputation" ,
322+ ErrorCodes::LOGICAL_ERROR);
323+ }
324+ }
325+ else
326+ {
327+ throw Exception (
328+ " Logical error: unexpected Type of DecimalRoundingComputation for INT result" ,
329+ ErrorCodes::LOGICAL_ERROR);
330+ }
331+ }
332+ else
333+ {
334+ throw Exception (
335+ " Logical error: unexpected OutputType of DecimalRoundingComputation" ,
336+ ErrorCodes::LOGICAL_ERROR);
337+ }
338+ }
339+ else
340+ {
341+ throw Exception (
342+ " Logical error: unexpected 'scale_mode' parameter passed to DecimalRoundingComputation" ,
343+ ErrorCodes::LOGICAL_ERROR);
344+ }
345+ }
346+ };
336347
337348#if __SSE4_1__
338349
0 commit comments