MySQL 9.2.0
Source Code Documentation
my_decimal.h
Go to the documentation of this file.
1/* Copyright (c) 2005, 2024, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is designed to work with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef MY_DECIMAL_INCLUDED
25#define MY_DECIMAL_INCLUDED
26
27/**
28 @file
29
30 It is interface module to fixed precision decimals library.
31
32 Most functions use 'uint mask' as parameter, if during operation error
33 which fit in this mask is detected then it will be processed automatically
34 here. (errors are E_DEC_* constants, see include/decimal.h)
35
36 Most function are just inline wrappers around library calls
37*/
38
39#include <assert.h>
40#include <stdlib.h>
41#include <sys/types.h>
42#include <algorithm>
43#include <array>
44
45#include "decimal.h"
46
47#include "my_inttypes.h"
48#include "my_macros.h"
49#include "my_time_t.h"
50#include "mysql/strings/dtoa.h"
52
53class String;
54struct MYSQL_TIME;
55
56static constexpr int DECIMAL_LONGLONG_DIGITS{22};
57
58/** maximum length of buffer in our big digits (uint32). */
59static constexpr int DECIMAL_BUFF_LENGTH{9};
60
61/** the number of digits that my_decimal can possibly contain */
63
64/**
65 maximum guaranteed precision of number in decimal digits (number of our
66 digits * number of decimal digits in one our big digit - number of decimal
67 digits in one our big digit decreased by 1 (because we always put decimal
68 point on the border of our big digits))
69*/
71 8 * 2};
72
73/**
74 maximum length of string representation (number of maximum decimal
75 digits + 1 position for sign + 1 position for decimal point, no terminator)
76*/
78
79/**
80 maximum size of packet length.
81*/
83
84inline int my_decimal_int_part(uint precision, uint decimals) {
85 return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals);
86}
87
88/**
89 my_decimal class limits 'decimal_t' type to what we need in MySQL.
90
91 It contains internally all necessary space needed by the instance so
92 no extra memory is needed. Objects should be moved using copy CTOR
93 or assignment operator, rather than memcpy/memmove.
94*/
95
96class my_decimal : public decimal_t {
97 std::array<decimal_digit_t, DECIMAL_BUFF_LENGTH> buffer;
98
99 public:
100 my_decimal(const my_decimal &rhs) : decimal_t(rhs), buffer(rhs.buffer) {
101 rhs.sanity_check();
102 buf = buffer.data();
103 }
104
106 sanity_check();
107 rhs.sanity_check();
108 if (this == &rhs) return *this;
109 decimal_t::intg = rhs.intg;
110 decimal_t::frac = rhs.frac;
111 decimal_t::len = rhs.len;
112 decimal_t::sign = rhs.sign();
113 buffer = rhs.buffer;
114 decimal_t::buf = buffer.data();
115 return *this;
116 }
117
118 void init() {
120 buf = buffer.data();
121 decimal_make_zero(this);
122 }
123
125
126#ifndef NDEBUG
128#endif // NDEBUG
129
130 void sanity_check() const { assert(buf == buffer.data()); }
131
132 bool sign() const { return decimal_t::sign; }
133 void sign(bool s) { decimal_t::sign = s; }
134 uint precision() const { return intg + frac; }
135
136 /** Swap two my_decimal values */
137 void swap(my_decimal &rhs) { std::swap(*this, rhs); }
138
139#ifndef MYSQL_SERVER
140 // Error reporting in server code only.
141 int check_result(uint, int result) const { return result; }
142#else
143 int check_result(uint, int result) const;
144#endif
145};
146
147#ifndef NDEBUG
148void print_decimal(const my_decimal *dec);
149void print_decimal_buff(const my_decimal *dec, const uchar *ptr, int length);
150const char *dbug_decimal_as_string(char *buff, const my_decimal *val);
151#else
152#define dbug_decimal_as_string(A) NULL
153#endif
154
155bool str_set_decimal(uint mask, const my_decimal *val, String *str,
156 const CHARSET_INFO *cs, uint decimals);
157
158inline void max_my_decimal(my_decimal *to, int precision, int frac) {
159 assert((precision <= DECIMAL_MAX_PRECISION) && (frac <= DECIMAL_MAX_SCALE));
160 max_decimal(precision, frac, to);
161}
162
165}
166
167inline int check_result_and_overflow(uint mask, int result, my_decimal *val) {
168 if (val->check_result(mask, result) & E_DEC_OVERFLOW) {
169 const bool sign = val->sign();
170 val->sanity_check();
172 val->sign(sign);
173 }
174 /*
175 Avoid returning negative zero, cfr. decimal_cmp()
176 For result == E_DEC_DIV_ZERO *val has not been assigned.
177 */
178 if (result != E_DEC_DIV_ZERO && val->sign() && decimal_is_zero(val))
179 val->sign(false);
180 return result;
181}
182
183inline uint my_decimal_length_to_precision(uint length, uint scale,
184 bool unsigned_flag) {
185 /* Precision can't be negative thus ignore unsigned_flag when length is 0. */
186 assert(length || !scale);
187 const uint retval =
188 (uint)(length - (scale > 0 ? 1 : 0) - (unsigned_flag || !length ? 0 : 1));
189 return retval;
190}
191
193 uint8 scale,
194 bool unsigned_flag) {
195 /*
196 When precision is 0 it means that original length was also 0. Thus
197 unsigned_flag is ignored in this case.
198 */
199 assert(precision || !scale);
200 const uint32 retval = (uint32)(precision + (scale > 0 ? 1 : 0) +
201 (unsigned_flag || !precision ? 0 : 1));
202 if (retval == 0) return 1;
203 return retval;
204}
205
206inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
207 bool unsigned_flag) {
208 /*
209 When precision is 0 it means that original length was also 0. Thus
210 unsigned_flag is ignored in this case.
211 */
212 assert(precision || !scale);
213 precision = std::min(precision, uint(DECIMAL_MAX_PRECISION));
214 return my_decimal_precision_to_length_no_truncation(precision, scale,
215 unsigned_flag);
216}
217
219 /* length of string representation including terminating '\0' */
220 return decimal_string_size(d);
221}
222
223inline int my_decimal_get_binary_size(uint precision, uint scale) {
224 return decimal_bin_size((int)precision, (int)scale);
225}
226
227inline void my_decimal2decimal(const my_decimal *from, my_decimal *to) {
228 *to = *from;
229}
230
231int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec,
232 int scale);
233
234inline int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d,
235 int prec, int scale) {
236 return d->check_result(mask, bin2decimal(bin, d, prec, scale, false));
237}
238
239/**
240 Decode DECIMAL from binary form
241
242 @param mask Error mask
243 @param bin Binary string to decode
244 @param d [out] DECIMAL buffer
245 @param prec Precision of stored value
246 @param scale Scale of stored value
247 @param keep_prec Whether to keep stored value's precision
248
249 @returns
250 conversion error
251*/
252
253inline int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d,
254 int prec, int scale, bool keep_prec) {
255 return d->check_result(mask, bin2decimal(bin, d, prec, scale, keep_prec));
256}
257
259 /*
260 We need the up-cast here, since my_decimal has sign() member functions,
261 which conflicts with decimal_t::size
262 (and decimal_make_zero is a macro, rather than a function).
263 */
264 decimal_make_zero(static_cast<decimal_t *>(d));
265 return 0;
266}
267
268inline bool my_decimal_is_zero(const my_decimal *decimal_value) {
269 return decimal_is_zero(decimal_value);
270}
271
272inline int my_decimal_round(uint mask, const my_decimal *from, int scale,
273 bool truncate, my_decimal *to) {
274 return from->check_result(
275 mask, decimal_round(from, to, scale, (truncate ? TRUNCATE : HALF_UP)));
276}
277
278inline int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to) {
279 return from->check_result(mask, decimal_round(from, to, 0, FLOOR));
280}
281
282inline int my_decimal_ceiling(uint mask, const my_decimal *from,
283 my_decimal *to) {
284 return from->check_result(mask, decimal_round(from, to, 0, CEILING));
285}
286
287int my_decimal2string(uint mask, const my_decimal *d, uint fixed_prec,
288 uint fixed_dec, String *str);
289
290inline int my_decimal2string(uint mask, const my_decimal *d, String *str) {
291 return my_decimal2string(mask, d, 0, 0, str);
292}
293
294inline int my_decimal2int(uint mask, const my_decimal *d, bool unsigned_flag,
295 longlong *l) {
296 my_decimal rounded;
297 /* decimal_round can return only E_DEC_TRUNCATED */
298 decimal_round(d, &rounded, 0, HALF_UP);
299 return d->check_result(
300 mask, (unsigned_flag ? decimal2ulonglong(&rounded, (ulonglong *)l)
301 : decimal2longlong(&rounded, l)));
302}
303
304inline int my_decimal2double(uint, const my_decimal *d, double *result) {
305 /* No need to call check_result as this will always succeed */
306 return decimal2double(d, result);
307}
308
309inline int my_decimal2lldiv_t(uint mask, const my_decimal *d, lldiv_t *to) {
310 return d->check_result(mask, decimal2lldiv_t(d, to));
311}
312
313inline int str2my_decimal(uint mask, const char *str, my_decimal *d,
314 const char **end) {
316}
317
318int str2my_decimal(uint mask, const char *from, size_t length,
319 const CHARSET_INFO *charset, my_decimal *decimal_value);
320
324
325inline int double2my_decimal(uint mask, double val, my_decimal *d) {
327}
328
329inline int int2my_decimal(uint mask, longlong i, bool unsigned_flag,
330 my_decimal *d) {
331 return d->check_result(mask,
332 (unsigned_flag ? ulonglong2decimal((ulonglong)i, d)
333 : longlong2decimal(i, d)));
334}
335
336inline void my_decimal_neg(decimal_t *arg) {
337 // Avoid returning negative zero, cfr. decimal_cmp()
338 if (decimal_is_zero(arg)) {
339 arg->sign = false;
340 return;
341 }
342 arg->sign ^= 1;
343}
344
345inline int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a,
346 const my_decimal *b) {
347 return check_result_and_overflow(mask, decimal_add(a, b, res), res);
348}
349
350inline int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a,
351 const my_decimal *b) {
352 return check_result_and_overflow(mask, decimal_sub(a, b, res), res);
353}
354
355inline int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a,
356 const my_decimal *b) {
357 return check_result_and_overflow(mask, decimal_mul(a, b, res), res);
358}
359
360inline int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a,
361 const my_decimal *b, int div_scale_inc) {
362 return check_result_and_overflow(mask, decimal_div(a, b, res, div_scale_inc),
363 res);
364}
365
366inline int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a,
367 const my_decimal *b) {
368 return check_result_and_overflow(mask, decimal_mod(a, b, res), res);
369}
370
371/**
372 @retval -1 if a @< b
373 @retval 1 if a @> b
374 @retval 0 if a == b
375*/
376inline int my_decimal_cmp(const my_decimal *a, const my_decimal *b) {
377 return decimal_cmp(a, b);
378}
379
380inline bool operator<(const my_decimal &lhs, const my_decimal &rhs) {
381 return my_decimal_cmp(&lhs, &rhs) < 0;
382}
383
384inline bool operator!=(const my_decimal &lhs, const my_decimal &rhs) {
385 return my_decimal_cmp(&lhs, &rhs) != 0;
386}
387
388inline int my_decimal_intg(const my_decimal *a) { return decimal_intg(a); }
389
390void my_decimal_trim(ulong *precision, uint *scale);
391
392#endif // MY_DECIMAL_INCLUDED
Using this class is fraught with peril, and you need to be very careful when doing so.
Definition: sql_string.h:167
my_decimal class limits 'decimal_t' type to what we need in MySQL.
Definition: my_decimal.h:96
int check_result(uint, int result) const
report result of decimal operation.
Definition: my_decimal.cc:61
void sign(bool s)
Definition: my_decimal.h:133
my_decimal()
Definition: my_decimal.h:124
void init()
Definition: my_decimal.h:118
my_decimal & operator=(const my_decimal &rhs)
Definition: my_decimal.h:105
void sanity_check() const
Definition: my_decimal.h:130
my_decimal(const my_decimal &rhs)
Definition: my_decimal.h:100
uint precision() const
Definition: my_decimal.h:134
~my_decimal()
Definition: my_decimal.h:127
bool sign() const
Definition: my_decimal.h:132
void swap(my_decimal &rhs)
Swap two my_decimal values.
Definition: my_decimal.h:137
std::array< decimal_digit_t, DECIMAL_BUFF_LENGTH > buffer
Definition: my_decimal.h:97
int decimal_round(const decimal_t *from, decimal_t *to, int new_scale, decimal_round_mode mode)
Definition: decimal.cc:1653
int decimal_bin_size(int precision, int scale)
Definition: decimal.cc:1631
int decimal2longlong(const decimal_t *from, longlong *to)
Definition: decimal.cc:1175
int ulonglong2decimal(ulonglong from, decimal_t *to)
Definition: decimal.cc:1139
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
Definition: decimal.cc:2083
static int decimal_string_size(const decimal_t *dec)
Returns the length of the buffer to hold string representation of the decimal (including decimal dot,...
Definition: decimal.h:135
int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale, bool keep_prec=false)
Definition: decimal.cc:1486
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
Definition: decimal.cc:2510
@ CEILING
Definition: decimal.h:38
@ FLOOR
Definition: decimal.h:39
@ HALF_UP
Definition: decimal.h:37
@ TRUNCATE
Definition: decimal.h:35
int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
Definition: decimal.cc:2034
int decimal_is_zero(const decimal_t *from)
Definition: decimal.cc:2054
#define E_DEC_DIV_ZERO
Definition: decimal.h:151
int longlong2decimal(longlong from, decimal_t *to)
Definition: decimal.cc:1144
int decimal2lldiv_t(const decimal_t *from, lldiv_t *to)
Convert decimal to lldiv_t.
Definition: decimal.cc:1222
void max_decimal(int precision, int frac, decimal_t *to)
Definition: decimal.cc:432
int decimal2ulonglong(const decimal_t *from, ulonglong *to)
Definition: decimal.cc:1151
int decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to, int scale_incr)
Definition: decimal.cc:2478
int string2decimal(const char *from, decimal_t *to, const char **end)
Definition: decimal.cc:932
static void decimal_make_zero(decimal_t *dec)
Definition: decimal.h:124
int decimal2double(const decimal_t *from, double *to)
Definition: decimal.cc:1075
int decimal_cmp(const decimal_t *from1, const decimal_t *from2)
Definition: decimal.cc:2044
int decimal_intg(const decimal_t *from)
Returns the number of decimal digits before the decimal point in a decimal_t, with any insignificant ...
Definition: decimal.cc:2028
int double2decimal(double from, decimal_t *to)
Definition: decimal.cc:1100
int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to)
Definition: decimal.cc:2039
#define E_DEC_OVERFLOW
Definition: decimal.h:150
static constexpr int DECIMAL_NOT_SPECIFIED
Definition: dtoa.h:54
static constexpr int DECIMAL_MAX_SCALE
Definition: dtoa.h:53
static const std::string dec("DECRYPTION")
A better implementation of the UNIX ctype(3) library.
static mi_bit_type mask[]
Definition: mi_packrec.cc:141
int my_decimal_int_part(uint precision, uint decimals)
Definition: my_decimal.h:84
int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec, int scale)
Definition: my_decimal.cc:223
void max_internal_decimal(my_decimal *to)
Definition: my_decimal.h:163
int check_result_and_overflow(uint mask, int result, my_decimal *val)
Definition: my_decimal.h:167
int my_decimal_sub(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b)
Definition: my_decimal.h:350
int int2my_decimal(uint mask, longlong i, bool unsigned_flag, my_decimal *d)
Definition: my_decimal.h:329
void print_decimal_buff(const my_decimal *dec, const uchar *ptr, int length)
Definition: my_decimal.cc:370
my_decimal * timeval2my_decimal(const my_timeval *tm, my_decimal *dec)
Convert timeval value to my_decimal.
Definition: my_decimal.cc:335
int double2my_decimal(uint mask, double val, my_decimal *d)
Definition: my_decimal.h:325
bool operator!=(const my_decimal &lhs, const my_decimal &rhs)
Definition: my_decimal.h:384
void max_my_decimal(my_decimal *to, int precision, int frac)
Definition: my_decimal.h:158
int my_decimal2string(uint mask, const my_decimal *d, uint fixed_prec, uint fixed_dec, String *str)
Converting decimal to string.
Definition: my_decimal.cc:126
static constexpr int DECIMAL_MAX_FIELD_SIZE
maximum size of packet length.
Definition: my_decimal.h:82
int my_decimal_get_binary_size(uint precision, uint scale)
Definition: my_decimal.h:223
static constexpr int DECIMAL_LONGLONG_DIGITS
Definition: my_decimal.h:56
int my_decimal2lldiv_t(uint mask, const my_decimal *d, lldiv_t *to)
Definition: my_decimal.h:309
bool str_set_decimal(uint mask, const my_decimal *val, String *str, const CHARSET_INFO *cs, uint decimals)
Converting decimal to string with character set conversion.
Definition: my_decimal.cc:172
int my_decimal_add(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b)
Definition: my_decimal.h:345
static constexpr int DECIMAL_BUFF_LENGTH
maximum length of buffer in our big digits (uint32).
Definition: my_decimal.h:59
int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b)
Definition: my_decimal.h:366
void my_decimal_neg(decimal_t *arg)
Definition: my_decimal.h:336
int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to)
Definition: my_decimal.h:278
int my_decimal2double(uint, const my_decimal *d, double *result)
Definition: my_decimal.h:304
bool my_decimal_is_zero(const my_decimal *decimal_value)
Definition: my_decimal.h:268
void print_decimal(const my_decimal *dec)
Definition: my_decimal.cc:357
uint my_decimal_length_to_precision(uint length, uint scale, bool unsigned_flag)
Definition: my_decimal.h:183
int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d, int prec, int scale)
Definition: my_decimal.h:234
uint32 my_decimal_precision_to_length(uint precision, uint8 scale, bool unsigned_flag)
Definition: my_decimal.h:206
void my_decimal_trim(ulong *precision, uint *scale)
Definition: my_decimal.cc:342
int my_decimal_cmp(const my_decimal *a, const my_decimal *b)
Definition: my_decimal.h:376
my_decimal * date2my_decimal(const MYSQL_TIME *ltime, my_decimal *dec)
Convert datetime value to my_decimal in format YYYYMMDDhhmmss.ffffff.
Definition: my_decimal.cc:311
bool operator<(const my_decimal &lhs, const my_decimal &rhs)
Definition: my_decimal.h:380
int my_decimal_intg(const my_decimal *a)
Definition: my_decimal.h:388
int my_decimal_set_zero(my_decimal *d)
Definition: my_decimal.h:258
int my_decimal_div(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b, int div_scale_inc)
Definition: my_decimal.h:360
int my_decimal_round(uint mask, const my_decimal *from, int scale, bool truncate, my_decimal *to)
Definition: my_decimal.h:272
my_decimal * time2my_decimal(const MYSQL_TIME *ltime, my_decimal *dec)
Convert time value to my_decimal in format hhmmss.ffffff.
Definition: my_decimal.cc:325
void my_decimal2decimal(const my_decimal *from, my_decimal *to)
Definition: my_decimal.h:227
static constexpr int DECIMAL_MAX_PRECISION
maximum guaranteed precision of number in decimal digits (number of our digits * number of decimal di...
Definition: my_decimal.h:70
int my_decimal2int(uint mask, const my_decimal *d, bool unsigned_flag, longlong *l)
Definition: my_decimal.h:294
static constexpr int DECIMAL_MAX_STR_LENGTH
maximum length of string representation (number of maximum decimal digits + 1 position for sign + 1 p...
Definition: my_decimal.h:77
int my_decimal_string_length(const my_decimal *d)
Definition: my_decimal.h:218
int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to)
Definition: my_decimal.h:282
static constexpr int DECIMAL_MAX_POSSIBLE_PRECISION
the number of digits that my_decimal can possibly contain
Definition: my_decimal.h:62
int my_decimal_mul(uint mask, my_decimal *res, const my_decimal *a, const my_decimal *b)
Definition: my_decimal.h:355
int str2my_decimal(uint mask, const char *str, my_decimal *d, const char **end)
Definition: my_decimal.h:313
const char * dbug_decimal_as_string(char *buff, const my_decimal *val)
Definition: my_decimal.cc:379
uint32 my_decimal_precision_to_length_no_truncation(uint precision, uint8 scale, bool unsigned_flag)
Definition: my_decimal.h:192
Some integer typedefs for easier portability.
unsigned long long int ulonglong
Definition: my_inttypes.h:56
uint8_t uint8
Definition: my_inttypes.h:63
unsigned char uchar
Definition: my_inttypes.h:52
long long int longlong
Definition: my_inttypes.h:55
uint32_t uint32
Definition: my_inttypes.h:67
Some common macros.
std::string str(const mysqlrouter::ConfigGenerator::Options::Endpoint &ep)
Definition: config_generator.cc:1117
Definition: buf0block_hint.cc:30
const std::string charset("charset")
Definition: commit_order_queue.h:34
bool length(const dd::Spatial_reference_system *srs, const Geometry *g1, double *length, bool *null) noexcept
Computes the length of linestrings and multilinestrings.
Definition: length.cc:76
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:192
struct result result
Definition: result.h:34
static void swap(String &a, String &b) noexcept
Definition: sql_string.h:663
Definition: m_ctype.h:421
Definition: mysql_time.h:82
Base struct used to represent decimal data type.
Definition: decimal.h:49
int frac
The number of decimal digits after the point.
Definition: decimal.h:54
decimal_digit_t * buf
An array of decimal_digit_t's.
Definition: decimal.h:61
int intg
The number of decimal digits (NOT number of decimal_digit_t's !) before the point.
Definition: decimal.h:52
bool sign
False means positive, true means negative.
Definition: decimal.h:59
int len
The length of buf (length of allocated space) in decimal_digit_t's, not in bytes.
Definition: decimal.h:57
Replacement of system's struct timeval to ensure we can carry 64 bit values even on a platform which ...
Definition: my_time_t.h:45
Definition: result.h:30