sparrow
2.4.0
C++20 idiomatic APIs for the Apache Arrow Columnar Format
Toggle main menu visibility
Loading...
Searching...
No Matches
decimal.hpp
Go to the documentation of this file.
1
#pragma once
2
3
#include <cmath>
4
#include <iostream>
5
#include <sstream>
6
7
#if defined(__cpp_lib_format)
8
# include <format>
9
#endif
10
11
#include "
sparrow/utils/large_int.hpp
"
12
#include "
sparrow/utils/mp_utils.hpp
"
13
14
namespace
sparrow
15
{
23
template
<
typename
T>
24
concept
decimal_integer_type
= std::is_same_v<T, std::int32_t> || std::is_same_v<T, std::int64_t>
25
|| std::is_same_v<T, int128_t> || std::is_same_v<T, int256_t>;
26
60
template
<decimal_
int
eger_type T>
61
class
decimal
62
{
63
public
:
64
65
using
integer_type
= T;
66
77
constexpr
decimal
()
78
requires
(!
is_int_placeholder_v<T>
);
79
90
constexpr
decimal
()
91
requires
(
is_int_placeholder_v<T>
);
92
105
constexpr
decimal
(T value,
int
scale
);
106
120
constexpr
bool
operator==
(
const
decimal
& other)
const
;
121
137
constexpr
explicit
operator
float() const
138
requires(!
is_int_placeholder_v
<T>);
139
155
constexpr explicit operator
double
() const
156
requires(!
is_int_placeholder_v
<T>);
157
173
constexpr explicit operator
long
double
() const
174
requires(!
is_int_placeholder_v
<T>);
175
191
[[nodiscard]] explicit operator
std
::
string
() const
192
requires(!
is_int_placeholder_v
<T>);
193
201
[[nodiscard]] constexpr T
storage
() const;
202
212
[[nodiscard]] constexpr
int
scale
() const;
213
214
private:
215
231
template <class FLOAT_TYPE>
232
[[nodiscard]] constexpr FLOAT_TYPE convert_to_floating_point() const
233
requires(!
is_int_placeholder_v
<T>);
234
235
T m_value;
236
int
m_scale;
237
};
238
244
template <typename T>
245
constexpr
bool
is_decimal_v
=
mpl
::is_type_instance_of_v<T,
decimal
>;
246
255
template <typename T>
256
concept
decimal_type
=
is_decimal_v
<T> &&
decimal_integer_type
<typename T::
integer_type
>;
257
258
template <
decimal_integer_type
T>
259
constexpr
decimal
<T>::
decimal
()
260
requires(!
is_int_placeholder_v
<T>)
261
: m_value(0)
262
, m_scale()
263
{
264
}
265
266
template
<decimal_
int
eger_type T>
267
constexpr
decimal<T>::decimal
()
268
requires
(
is_int_placeholder_v<T>
)
269
: m_value()
270
, m_scale()
271
{
272
}
273
274
template
<decimal_
int
eger_type T>
275
constexpr
decimal<T>::decimal
(T value,
int
scale
)
276
: m_value(value)
277
, m_scale(
scale
)
278
{
279
}
280
281
template
<decimal_
int
eger_type T>
282
constexpr
bool
decimal<T>::operator==
(
const
decimal
& other)
const
283
{
284
return
m_value == other.m_value && m_scale == other.m_scale;
285
}
286
287
template
<decimal_
int
eger_type T>
288
constexpr
decimal<T>::operator
float() const
289
requires(!
is_int_placeholder_v
<T>)
290
{
291
return
convert_to_floating_point<float>();
292
}
293
294
template
<decimal_
int
eger_type T>
295
constexpr
decimal<T>::operator
double() const
296
requires(!
is_int_placeholder_v
<T>)
297
{
298
return
convert_to_floating_point<double>();
299
}
300
301
template
<decimal_
int
eger_type T>
302
constexpr
decimal<T>::operator
long
double() const
303
requires(!
is_int_placeholder_v
<T>)
304
{
305
return
convert_to_floating_point<long double>();
306
}
307
308
template
<decimal_
int
eger_type T>
309
decimal<T>::operator
std::string() const
310
requires(!
is_int_placeholder_v
<T>)
311
{
312
std::stringstream ss;
313
ss << m_value;
314
std::string result = ss.str();
315
if
(m_scale == 0)
316
{
317
return
result;
318
}
319
if
(result[0] ==
'0'
)
320
{
321
return
"0"
;
322
}
323
// remove - (we handle it later)
324
if
(result[0] ==
'-'
)
325
{
326
result = result.substr(1);
327
}
328
329
if
(m_scale > 0)
330
{
331
if
(result.length() <=
static_cast<
std::size_t
>
(m_scale))
332
{
333
result.insert(
334
0,
335
std::string(
static_cast<
std::size_t
>
(m_scale) + 1 - result.length(),
'0'
)
336
);
// Pad with leading zeros
337
}
338
std::size_t int_part_len = result.length() -
static_cast<
std::size_t
>
(m_scale);
339
std::string int_part = result.substr(0, int_part_len);
340
std::string frac_part = result.substr(int_part_len);
341
result = int_part +
"."
+ frac_part;
342
}
343
else
344
{
345
result += std::string(
static_cast<
std::size_t
>
(-m_scale),
'0'
);
// Append zeros
346
}
347
// handle negative values
348
if
(m_value < 0)
349
{
350
result.insert(0, 1,
'-'
);
351
}
352
return
result;
353
}
354
355
template
<decimal_
int
eger_type T>
356
constexpr
T
decimal<T>::storage
()
const
357
{
358
return
m_value;
359
}
360
361
template
<decimal_
int
eger_type T>
362
constexpr
int
decimal<T>::scale
()
const
363
{
364
return
m_scale;
365
}
366
367
template
<decimal_
int
eger_type T>
368
template
<
class
FLOAT_TYPE>
369
constexpr
FLOAT_TYPE decimal<T>::convert_to_floating_point() const
370
requires(!
is_int_placeholder_v
<T>)
371
{
372
using
to_type = FLOAT_TYPE;
373
if
constexpr
(std::is_same_v<T, int256_t>)
374
{
375
// danger zone
376
auto
val =
static_cast<
int128_t
>
(m_value);
377
return
static_cast<
to_type
>
(val) /
static_cast<
to_type
>
(std::pow(10, m_scale));
378
}
379
else
380
{
381
return
static_cast<
to_type
>
(m_value) /
static_cast<
to_type
>
(std::pow(10, m_scale));
382
}
383
}
384
385
}
// namespace sparrow
386
387
#if defined(__cpp_lib_format)
388
389
template
<
typename
T>
390
struct
std::formatter<
sparrow
::decimal<T>>
391
{
392
constexpr
auto
parse(std::format_parse_context& ctx)
393
{
394
return
ctx.begin();
395
}
396
397
auto
format(
const
sparrow::decimal<T>& d, std::format_context& ctx)
const
398
{
399
return
std::format_to(ctx.out(),
"Decimal({}, {})"
, d.
storage
(), d.
scale
());
400
}
401
};
402
403
namespace
sparrow
404
{
405
template
<
typename
T>
406
std::ostream&
operator<<
(std::ostream& os,
const
decimal<T>
& value)
407
{
408
os << std::format(
"{}"
, value);
409
return
os;
410
}
411
}
412
413
#endif
sparrow::decimal
Definition
decimal.hpp:62
sparrow::decimal::decimal
constexpr decimal()
Default constructor for placeholder integer types.
sparrow::decimal< std::int32_t >::integer_type
T integer_type
Definition
decimal.hpp:65
sparrow::decimal::decimal
constexpr decimal(T value, int scale)
Constructor from value and scale.
Definition
decimal.hpp:275
sparrow::decimal< std::int32_t >::scale
constexpr int scale() const
sparrow::decimal::operator==
constexpr bool operator==(const decimal &other) const
Equality comparison operator.
Definition
decimal.hpp:282
sparrow::decimal< std::int32_t >::storage
constexpr T storage() const
sparrow::decimal::decimal
constexpr decimal()
Default constructor for non-placeholder integer types.
Definition
decimal.hpp:259
sparrow::decimal_integer_type
Concept for valid decimal integer backing types.
Definition
decimal.hpp:24
sparrow::decimal_type
Concept for valid decimal types.
Definition
decimal.hpp:256
large_int.hpp
mp_utils.hpp
sparrow::mpl
Definition
mp_utils.hpp:26
sparrow
Definition
array.hpp:21
sparrow::int128_t
primesum::int128_t int128_t
Definition
large_int.hpp:84
sparrow::is_int_placeholder_v
constexpr bool is_int_placeholder_v
Definition
large_int.hpp:82
sparrow::operator<<
std::ostream & operator<<(std::ostream &os, const nullval_t &)
Definition
nullable.hpp:1597
sparrow::is_decimal_v
constexpr bool is_decimal_v
Type trait to check if a type is a decimal instantiation.
Definition
decimal.hpp:245
std
Extensions to the C++ standard library.
Definition
float16_t.hpp:1916
sparrow
utils
decimal.hpp
Generated by
1.17.0