llfix
Low-latency FIX engine
fixed_point.h
1 /*
2 MIT License
3 
4 Copyright (c) 2026 Coreware Limited
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 #pragma once
25 
26 #include <cassert>
27 #include <cstdint>
28 #include <cstddef>
29 #include <string>
30 
31 #include "../../core/utilities/converters.h"
32 
33 namespace llfix
34 {
35 
82 {
83 public:
84 
89  void set_decimal_points(uint32_t n)
90  {
91  assert(n>0 && n <= MAX_ALLOWED_DECIMAL_POINTS);
92  m_decimal_points = n;
93  }
94 
99  uint32_t get_decimal_points() const
100  {
101  return m_decimal_points;
102  }
103 
108  void set_raw_value(uint64_t raw_value)
109  {
110  m_raw_value = raw_value;
111  }
112 
117  uint64_t get_raw_value() const
118  {
119  return m_raw_value;
120  }
121 
131  void set_from_chars(const char* buffer, std::size_t length)
132  {
133  assert(m_decimal_points >0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
134  assert(buffer != nullptr);
135  assert(length > 0);
136 
137  char temp_buffer[MAX_DIGITS];
138  std::size_t temp_buffer_length = 0;
139 
140  std::size_t length_fractal_part = 0;
141  bool in_fractal_part = false;
142 
143  for (std::size_t i = 0; i < length; i++)
144  {
145  char current_char = buffer[i];
146 
147  if (current_char != '.')
148  {
149  assert(temp_buffer_length < MAX_DIGITS);
150 
151  temp_buffer[temp_buffer_length] = current_char;
152  temp_buffer_length++;
153 
154  if (in_fractal_part )
155  {
156  length_fractal_part++;
157  }
158  }
159  else
160  {
161  in_fractal_part = true;
162  }
163  }
164 
165  assert(length_fractal_part <= m_decimal_points && length_fractal_part <= MAX_ALLOWED_DECIMAL_POINTS);
166 
167  uint64_t scale = POWERS_OF_TEN[m_decimal_points];
168  scale /= static_cast<uint64_t>(POWERS_OF_TEN[length_fractal_part]);
169 
170  auto value = Converters::chars_to_unsigned_int<uint64_t>(temp_buffer, temp_buffer_length);
171 
172  m_raw_value = static_cast<uint64_t>(value * scale);
173  }
174 
185  std::size_t to_chars(char* buffer) const
186  {
187  assert(m_decimal_points >0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
188  assert(buffer != nullptr);
189 
190  char temp_buffer[MAX_DIGITS];
191  Converters::unsigned_int_to_chars<uint64_t>(m_raw_value, temp_buffer);
192 
193  std::size_t length = Converters::get_chars_length_of_uint64_t(m_raw_value);
194 
195  assert(length > 0);
196 
197  if (length > m_decimal_points)
198  {
199  assert(length + 1 < MAX_DIGITS);
200 
201  std::size_t integer_part_length = length - m_decimal_points;
202 
203  // Copy integer part
204  for (std::size_t i = 0; i < integer_part_length; i++)
205  {
206  buffer[i] = temp_buffer[i];
207  }
208 
209  buffer[integer_part_length] = '.';
210 
211  // Copy fractal part
212  for (std::size_t i = 0; i < m_decimal_points; i++)
213  {
214  buffer[integer_part_length + 1 + i] = temp_buffer[integer_part_length + i];
215  }
216 
217  return length + 1; // +1 is because of '.'
218  }
219  else
220  {
221  assert(2 + m_decimal_points < MAX_DIGITS);
222 
223  buffer[0] = '0';
224  buffer[1] = '.';
225 
226  std::size_t max_buffer_index = 2 + m_decimal_points - 1;
227 
228  for (std::size_t i = 0; i < length; i++)
229  {
230  buffer[max_buffer_index - i] = temp_buffer[length-1-i];
231  }
232 
233  for (std::size_t i = 0; i < m_decimal_points-length; i++)
234  {
235  buffer[2 + i] = '0';
236  }
237 
238  return 2 + m_decimal_points; // +2 is because of "0."
239  }
240  }
241 
246  std::string to_string() const
247  {
248  assert(m_decimal_points >0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
249 
250  char temp_buffer[MAX_DIGITS];
251  auto length = to_chars(temp_buffer);
252  temp_buffer[length] = '\0';
253 
254  std::string ret = temp_buffer;
255  return ret;
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 
266  return m_raw_value == other.m_raw_value;
267  }
268 
272  bool operator !=(const FixedPoint& other) const
273  {
274  assert(m_decimal_points > 0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
275  assert(m_decimal_points == other.m_decimal_points);
276 
277  return m_raw_value != other.m_raw_value;
278  }
279 
283  bool operator >(const FixedPoint& other) const
284  {
285  assert(m_decimal_points > 0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
286  assert(m_decimal_points == other.m_decimal_points);
287  return m_raw_value > other.m_raw_value;
288  }
289 
293  bool operator >=(const FixedPoint& other) const
294  {
295  assert(m_decimal_points > 0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
296  assert(m_decimal_points == other.m_decimal_points);
297  return m_raw_value >= other.m_raw_value;
298  }
299 
303  bool operator <(const FixedPoint& other) const
304  {
305  assert(m_decimal_points > 0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
306  assert(m_decimal_points == other.m_decimal_points);
307  return m_raw_value < other.m_raw_value;
308  }
309 
313  bool operator <=(const FixedPoint& other) const
314  {
315  assert(m_decimal_points > 0 && m_decimal_points <= MAX_ALLOWED_DECIMAL_POINTS);
316  assert(m_decimal_points == other.m_decimal_points);
317  return m_raw_value <= other.m_raw_value;
318  }
319 
320 private:
321  uint64_t m_raw_value = 0;
322  uint32_t m_decimal_points = 0;
323 
324  static constexpr inline std::size_t MAX_DIGITS = 64;
325  static constexpr inline std::size_t MAX_ALLOWED_DECIMAL_POINTS = 9;
326 
327  static constexpr inline uint64_t POWERS_OF_TEN[] =
328  {
329  UINT64_C(1), UINT64_C(10), UINT64_C(100),
330  UINT64_C(1000), UINT64_C(10000), UINT64_C(100000),
331  UINT64_C(1000000), UINT64_C(10000000), UINT64_C(100000000),
332  UINT64_C(1000000000),
333  };
334 };
335 
336 } // 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:131
llfix::FixedPoint::operator!=
bool operator!=(const FixedPoint &other) const
Inequality comparison.
Definition: fixed_point.h:272
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:89
llfix::FixedPoint::get_decimal_points
uint32_t get_decimal_points() const
Get the number of decimal points for this value.
Definition: fixed_point.h:99
llfix::FixedPoint
Represents an unsigned fixed-point numeric value with a configurable number of decimal points....
Definition: fixed_point.h:81
llfix::FixedPoint::operator>
bool operator>(const FixedPoint &other) const
Greater-than comparison.
Definition: fixed_point.h:283
llfix::FixedPoint::to_string
std::string to_string() const
Convert the fixed-point value to a std::string.
Definition: fixed_point.h:246
llfix::FixedPoint::set_raw_value
void set_raw_value(uint64_t raw_value)
Set the raw integer value.
Definition: fixed_point.h:108
llfix::FixedPoint::operator<
bool operator<(const FixedPoint &other) const
Less-than comparison.
Definition: fixed_point.h:303
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:185
llfix::FixedPoint::operator<=
bool operator<=(const FixedPoint &other) const
Less-than-or-equal comparison.
Definition: fixed_point.h:313
llfix::FixedPoint::operator>=
bool operator>=(const FixedPoint &other) const
Greater-than-or-equal comparison.
Definition: fixed_point.h:293
llfix::FixedPoint::operator==
bool operator==(const FixedPoint &other) const
Equality comparison.
Definition: fixed_point.h:261
llfix::FixedPoint::get_raw_value
uint64_t get_raw_value() const
Get the raw integer value.
Definition: fixed_point.h:117