llfix
Low-latency FIX engine
fixed_point.h
1 // DISCLAIMER_PLACEHOLDER
2 #pragma once
3 
4 #include <cassert>
5 #include <cstdint>
6 #include <cstddef>
7 #include <string>
8 
9 #include "../../core/utilities/converters.h"
10 
11 namespace llfix
12 {
13 
60 {
61 public:
62 
67  void set_decimal_points(uint32_t n)
68  {
69  assert(n>0 && n <= MAX_ALLOWED_DECIMAL_POINTS);
70  m_decimal_points = n;
71  }
72 
77  uint32_t get_decimal_points() const
78  {
79  return m_decimal_points;
80  }
81 
86  void set_raw_value(uint64_t raw_value)
87  {
88  m_raw_value = raw_value;
89  }
90 
95  uint64_t get_raw_value() const
96  {
97  return m_raw_value;
98  }
99 
109  void set_from_chars(const char* buffer, std::size_t length)
110  {
111  assert(m_decimal_points >0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
112  assert(buffer != nullptr);
113  assert(length > 0);
114 
115  char temp_buffer[MAX_DIGITS];
116  std::size_t temp_buffer_length = 0;
117 
118  std::size_t length_fractal_part = 0;
119  bool in_fractal_part = false;
120 
121  for (std::size_t i = 0; i < length; i++)
122  {
123  char current_char = buffer[i];
124 
125  if (current_char != '.')
126  {
127  assert(temp_buffer_length < MAX_DIGITS);
128 
129  temp_buffer[temp_buffer_length] = current_char;
130  temp_buffer_length++;
131 
132  if (in_fractal_part )
133  {
134  length_fractal_part++;
135  }
136  }
137  else
138  {
139  in_fractal_part = true;
140  }
141  }
142 
143  assert(length_fractal_part <= m_decimal_points && length_fractal_part <= MAX_ALLOWED_DECIMAL_POINTS);
144 
145  uint64_t scale = POWERS_OF_TEN[m_decimal_points];
146  scale /= static_cast<uint64_t>(POWERS_OF_TEN[length_fractal_part]);
147 
148  auto value = Converters::chars_to_unsigned_int<uint64_t>(temp_buffer, temp_buffer_length);
149 
150  m_raw_value = static_cast<uint64_t>(value * scale);
151  }
152 
163  std::size_t to_chars(char* buffer) const
164  {
165  assert(m_decimal_points >0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
166  assert(buffer != nullptr);
167 
168  char temp_buffer[MAX_DIGITS];
169  Converters::unsigned_int_to_chars<uint64_t>(m_raw_value, temp_buffer);
170 
171  std::size_t length = Converters::get_chars_length_of_uint64_t(m_raw_value);
172 
173  assert(length > 0);
174 
175  if (length > m_decimal_points)
176  {
177  assert(length + 1 < MAX_DIGITS);
178 
179  std::size_t integer_part_length = length - m_decimal_points;
180 
181  // Copy integer part
182  for (std::size_t i = 0; i < integer_part_length; i++)
183  {
184  buffer[i] = temp_buffer[i];
185  }
186 
187  buffer[integer_part_length] = '.';
188 
189  // Copy fractal part
190  for (std::size_t i = 0; i < m_decimal_points; i++)
191  {
192  buffer[integer_part_length + 1 + i] = temp_buffer[integer_part_length + i];
193  }
194 
195  return length + 1; // +1 is because of '.'
196  }
197  else
198  {
199  assert(2 + m_decimal_points < MAX_DIGITS);
200 
201  buffer[0] = '0';
202  buffer[1] = '.';
203 
204  std::size_t max_buffer_index = 2 + m_decimal_points - 1;
205 
206  for (std::size_t i = 0; i < length; i++)
207  {
208  buffer[max_buffer_index - i] = temp_buffer[length-1-i];
209  }
210 
211  for (std::size_t i = 0; i < m_decimal_points-length; i++)
212  {
213  buffer[2 + i] = '0';
214  }
215 
216  return 2 + m_decimal_points; // +2 is because of "0."
217  }
218  }
219 
224  std::string to_string() const
225  {
226  assert(m_decimal_points >0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
227 
228  char temp_buffer[MAX_DIGITS];
229  auto length = to_chars(temp_buffer);
230  temp_buffer[length] = '\0';
231 
232  std::string ret = temp_buffer;
233  return ret;
234  }
235 
239  bool operator ==(const FixedPoint& other) const
240  {
241  assert(m_decimal_points > 0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
242  assert(m_decimal_points == other.m_decimal_points);
243 
244  return m_raw_value == other.m_raw_value;
245  }
246 
250  bool operator !=(const FixedPoint& other) const
251  {
252  assert(m_decimal_points > 0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
253  assert(m_decimal_points == other.m_decimal_points);
254 
255  return m_raw_value != other.m_raw_value;
256  }
257 
261  bool operator >(const FixedPoint& other) const
262  {
263  assert(m_decimal_points > 0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
264  assert(m_decimal_points == other.m_decimal_points);
265  return m_raw_value > other.m_raw_value;
266  }
267 
271  bool operator >=(const FixedPoint& other) const
272  {
273  assert(m_decimal_points > 0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
274  assert(m_decimal_points == other.m_decimal_points);
275  return m_raw_value >= other.m_raw_value;
276  }
277 
281  bool operator <(const FixedPoint& other) const
282  {
283  assert(m_decimal_points > 0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
284  assert(m_decimal_points == other.m_decimal_points);
285  return m_raw_value < other.m_raw_value;
286  }
287 
291  bool operator <=(const FixedPoint& other) const
292  {
293  assert(m_decimal_points > 0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
294  assert(m_decimal_points == other.m_decimal_points);
295  return m_raw_value <= other.m_raw_value;
296  }
297 
298 private:
299  uint64_t m_raw_value = 0;
300  uint32_t m_decimal_points = 0;
301 
302  static constexpr inline std::size_t MAX_DIGITS = 64;
303  static constexpr inline std::size_t MAX_ALLOWED_DECIMAL_POINTS = 9;
304 
305  static constexpr inline uint64_t POWERS_OF_TEN[] =
306  {
307  UINT64_C(1), UINT64_C(10), UINT64_C(100),
308  UINT64_C(1000), UINT64_C(10000), UINT64_C(100000),
309  UINT64_C(1000000), UINT64_C(10000000), UINT64_C(100000000),
310  UINT64_C(1000000000),
311  };
312 };
313 
314 } // namespace
llfix::FixedPoint::set_from_chars
void set_from_chars(const char *buffer, std::size_t length)
Set value from a character buffer representing a decimal number.
Definition: fixed_point.h:109
llfix::FixedPoint::operator!=
bool operator!=(const FixedPoint &other) const
Inequality comparison.
Definition: fixed_point.h:250
llfix::FixedPoint::set_decimal_points
void set_decimal_points(uint32_t n)
Set the number of decimal points for this value.
Definition: fixed_point.h:67
llfix::FixedPoint::get_decimal_points
uint32_t get_decimal_points() const
Get the number of decimal points for this value.
Definition: fixed_point.h:77
llfix::FixedPoint
Represents an unsigned fixed-point numeric value with a configurable number of decimal points....
Definition: fixed_point.h:59
llfix::FixedPoint::operator>
bool operator>(const FixedPoint &other) const
Greater-than comparison.
Definition: fixed_point.h:261
llfix::FixedPoint::to_string
std::string to_string() const
Convert the fixed-point value to a std::string.
Definition: fixed_point.h:224
llfix::FixedPoint::set_raw_value
void set_raw_value(uint64_t raw_value)
Set the raw integer value.
Definition: fixed_point.h:86
llfix::FixedPoint::operator<
bool operator<(const FixedPoint &other) const
Less-than comparison.
Definition: fixed_point.h:281
llfix::FixedPoint::to_chars
std::size_t to_chars(char *buffer) const
Convert the fixed-point value into characters in buffer.
Definition: fixed_point.h:163
llfix::FixedPoint::operator<=
bool operator<=(const FixedPoint &other) const
Less-than-or-equal comparison.
Definition: fixed_point.h:291
llfix::FixedPoint::operator>=
bool operator>=(const FixedPoint &other) const
Greater-than-or-equal comparison.
Definition: fixed_point.h:271
llfix::FixedPoint::operator==
bool operator==(const FixedPoint &other) const
Equality comparison.
Definition: fixed_point.h:239
llfix::FixedPoint::get_raw_value
uint64_t get_raw_value() const
Get the raw integer value.
Definition: fixed_point.h:95