1 1.1 mrg /* 2 1.1 mrg Name: imrat.h 3 1.1 mrg Purpose: Arbitrary precision rational arithmetic routines. 4 1.1 mrg Author: M. J. Fromberger 5 1.1 mrg 6 1.1 mrg Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved. 7 1.1 mrg 8 1.1 mrg Permission is hereby granted, free of charge, to any person obtaining a copy 9 1.1 mrg of this software and associated documentation files (the "Software"), to deal 10 1.1 mrg in the Software without restriction, including without limitation the rights 11 1.1 mrg to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 1.1 mrg copies of the Software, and to permit persons to whom the Software is 13 1.1 mrg furnished to do so, subject to the following conditions: 14 1.1 mrg 15 1.1 mrg The above copyright notice and this permission notice shall be included in 16 1.1 mrg all copies or substantial portions of the Software. 17 1.1 mrg 18 1.1 mrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 1.1 mrg IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 1.1 mrg AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 1.1 mrg LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 1.1 mrg OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 1.1 mrg SOFTWARE. 25 1.1 mrg */ 26 1.1 mrg 27 1.1 mrg #ifndef IMRAT_H_ 28 1.1 mrg #define IMRAT_H_ 29 1.1 mrg 30 1.1 mrg #include <stdbool.h> 31 1.1 mrg 32 1.1 mrg #include "imath.h" 33 1.1 mrg 34 1.1 mrg #ifdef __cplusplus 35 1.1 mrg extern "C" { 36 1.1 mrg #endif 37 1.1 mrg 38 1.1 mrg typedef struct { 39 1.1 mrg mpz_t num; /* Numerator */ 40 1.1 mrg mpz_t den; /* Denominator, <> 0 */ 41 1.1 mrg } mpq_t, *mp_rat; 42 1.1 mrg 43 1.1 mrg /* Return a pointer to the numerator. */ 44 1.1 mrg static inline mp_int MP_NUMER_P(mp_rat Q) { return &(Q->num); } 45 1.1 mrg 46 1.1 mrg /* Return a pointer to the denominator. */ 47 1.1 mrg static inline mp_int MP_DENOM_P(mp_rat Q) { return &(Q->den); } 48 1.1 mrg 49 1.1 mrg /* Rounding constants */ 50 1.1 mrg typedef enum { 51 1.1 mrg MP_ROUND_DOWN, 52 1.1 mrg MP_ROUND_HALF_UP, 53 1.1 mrg MP_ROUND_UP, 54 1.1 mrg MP_ROUND_HALF_DOWN 55 1.1 mrg } mp_round_mode; 56 1.1 mrg 57 1.1 mrg /** Initializes `r` with 1-digit precision and sets it to zero. This function 58 1.1 mrg cannot fail unless `r` is NULL. */ 59 1.1 mrg mp_result mp_rat_init(mp_rat r); 60 1.1 mrg 61 1.1 mrg /** Allocates a fresh zero-valued `mpq_t` on the heap, returning NULL in case 62 1.1 mrg of error. The only possible error is out-of-memory. */ 63 1.1 mrg mp_rat mp_rat_alloc(void); 64 1.1 mrg 65 1.1 mrg /** Reduces `r` in-place to lowest terms and canonical form. 66 1.1 mrg 67 1.1 mrg Zero is represented as 0/1, one as 1/1, and signs are adjusted so that the 68 1.1 mrg sign of the value is carried by the numerator. */ 69 1.1 mrg mp_result mp_rat_reduce(mp_rat r); 70 1.1 mrg 71 1.1 mrg /** Initializes `r` with at least `n_prec` digits of storage for the numerator 72 1.1 mrg and `d_prec` digits of storage for the denominator, and value zero. 73 1.1 mrg 74 1.1 mrg If either precision is zero, the default precision is used, rounded up to 75 1.1 mrg the nearest word size. */ 76 1.1 mrg mp_result mp_rat_init_size(mp_rat r, mp_size n_prec, mp_size d_prec); 77 1.1 mrg 78 1.1 mrg /** Initializes `r` to be a copy of an already-initialized value in `old`. The 79 1.1 mrg new copy does not share storage with the original. */ 80 1.1 mrg mp_result mp_rat_init_copy(mp_rat r, mp_rat old); 81 1.1 mrg 82 1.1 mrg /** Sets the value of `r` to the ratio of signed `numer` to signed `denom`. It 83 1.1 mrg returns `MP_UNDEF` if `denom` is zero. */ 84 1.1 mrg mp_result mp_rat_set_value(mp_rat r, mp_small numer, mp_small denom); 85 1.1 mrg 86 1.1 mrg /** Sets the value of `r` to the ratio of unsigned `numer` to unsigned 87 1.1 mrg `denom`. It returns `MP_UNDEF` if `denom` is zero. */ 88 1.1 mrg mp_result mp_rat_set_uvalue(mp_rat r, mp_usmall numer, mp_usmall denom); 89 1.1 mrg 90 1.1 mrg /** Releases the storage used by `r`. */ 91 1.1 mrg void mp_rat_clear(mp_rat r); 92 1.1 mrg 93 1.1 mrg /** Releases the storage used by `r` and also `r` itself. 94 1.1 mrg This should only be used for `r` allocated by `mp_rat_alloc()`. */ 95 1.1 mrg void mp_rat_free(mp_rat r); 96 1.1 mrg 97 1.1 mrg /** Sets `z` to a copy of the numerator of `r`. */ 98 1.1 mrg mp_result mp_rat_numer(mp_rat r, mp_int z); 99 1.1 mrg 100 1.1 mrg /** Returns a pointer to the numerator of `r`. */ 101 1.1 mrg mp_int mp_rat_numer_ref(mp_rat r); 102 1.1 mrg 103 1.1 mrg /** Sets `z` to a copy of the denominator of `r`. */ 104 1.1 mrg mp_result mp_rat_denom(mp_rat r, mp_int z); 105 1.1 mrg 106 1.1 mrg /** Returns a pointer to the denominator of `r`. */ 107 1.1 mrg mp_int mp_rat_denom_ref(mp_rat r); 108 1.1 mrg 109 1.1 mrg /** Reports the sign of `r`. */ 110 1.1 mrg mp_sign mp_rat_sign(mp_rat r); 111 1.1 mrg 112 1.1 mrg /** Sets `c` to a copy of the value of `a`. No new memory is allocated unless a 113 1.1 mrg term of `a` has more significant digits than the corresponding term of `c` 114 1.1 mrg has allocated. */ 115 1.1 mrg mp_result mp_rat_copy(mp_rat a, mp_rat c); 116 1.1 mrg 117 1.1 mrg /** Sets `r` to zero. The allocated storage of `r` is not changed. */ 118 1.1 mrg void mp_rat_zero(mp_rat r); 119 1.1 mrg 120 1.1 mrg /** Sets `c` to the absolute value of `a`. */ 121 1.1 mrg mp_result mp_rat_abs(mp_rat a, mp_rat c); 122 1.1 mrg 123 1.1 mrg /** Sets `c` to the absolute value of `a`. */ 124 1.1 mrg mp_result mp_rat_neg(mp_rat a, mp_rat c); 125 1.1 mrg 126 1.1 mrg /** Sets `c` to the reciprocal of `a` if the reciprocal is defined. 127 1.1 mrg It returns `MP_UNDEF` if `a` is zero. */ 128 1.1 mrg mp_result mp_rat_recip(mp_rat a, mp_rat c); 129 1.1 mrg 130 1.1 mrg /** Sets `c` to the sum of `a` and `b`. */ 131 1.1 mrg mp_result mp_rat_add(mp_rat a, mp_rat b, mp_rat c); 132 1.1 mrg 133 1.1 mrg /** Sets `c` to the difference of `a` less `b`. */ 134 1.1 mrg mp_result mp_rat_sub(mp_rat a, mp_rat b, mp_rat c); 135 1.1 mrg 136 1.1 mrg /** Sets `c` to the product of `a` and `b`. */ 137 1.1 mrg mp_result mp_rat_mul(mp_rat a, mp_rat b, mp_rat c); 138 1.1 mrg 139 1.1 mrg /** Sets `c` to the ratio `a / b` if that ratio is defined. 140 1.1 mrg It returns `MP_UNDEF` if `b` is zero. */ 141 1.1 mrg mp_result mp_rat_div(mp_rat a, mp_rat b, mp_rat c); 142 1.1 mrg 143 1.1 mrg /** Sets `c` to the sum of `a` and integer `b`. */ 144 1.1 mrg mp_result mp_rat_add_int(mp_rat a, mp_int b, mp_rat c); 145 1.1 mrg 146 1.1 mrg /** Sets `c` to the difference of `a` less integer `b`. */ 147 1.1 mrg mp_result mp_rat_sub_int(mp_rat a, mp_int b, mp_rat c); 148 1.1 mrg 149 1.1 mrg /** Sets `c` to the product of `a` and integer `b`. */ 150 1.1 mrg mp_result mp_rat_mul_int(mp_rat a, mp_int b, mp_rat c); 151 1.1 mrg 152 1.1 mrg /** Sets `c` to the ratio `a / b` if that ratio is defined. 153 1.1 mrg It returns `MP_UNDEF` if `b` is zero. */ 154 1.1 mrg mp_result mp_rat_div_int(mp_rat a, mp_int b, mp_rat c); 155 1.1 mrg 156 1.1 mrg /** Sets `c` to the value of `a` raised to the `b` power. 157 1.1 mrg It returns `MP_RANGE` if `b < 0`. */ 158 1.1 mrg mp_result mp_rat_expt(mp_rat a, mp_small b, mp_rat c); 159 1.1 mrg 160 1.1 mrg /** Returns the comparator of `a` and `b`. */ 161 1.1 mrg int mp_rat_compare(mp_rat a, mp_rat b); 162 1.1 mrg 163 1.1 mrg /** Returns the comparator of the magnitudes of `a` and `b`, disregarding their 164 1.1 mrg signs. Neither `a` nor `b` is modified by the comparison. */ 165 1.1 mrg int mp_rat_compare_unsigned(mp_rat a, mp_rat b); 166 1.1 mrg 167 1.1 mrg /** Returns the comparator of `r` and zero. */ 168 1.1 mrg int mp_rat_compare_zero(mp_rat r); 169 1.1 mrg 170 1.1 mrg /** Returns the comparator of `r` and the signed ratio `n / d`. 171 1.1 mrg It returns `MP_UNDEF` if `d` is zero. */ 172 1.1 mrg int mp_rat_compare_value(mp_rat r, mp_small n, mp_small d); 173 1.1 mrg 174 1.1 mrg /** Reports whether `r` is an integer, having canonical denominator 1. */ 175 1.1 mrg bool mp_rat_is_integer(mp_rat r); 176 1.1 mrg 177 1.1 mrg /** Reports whether the numerator and denominator of `r` can be represented as 178 1.1 mrg small signed integers, and if so stores the corresponding values to `num` 179 1.1 mrg and `den`. It returns `MP_RANGE` if either cannot be so represented. */ 180 1.1 mrg mp_result mp_rat_to_ints(mp_rat r, mp_small *num, mp_small *den); 181 1.1 mrg 182 1.1 mrg /** Converts `r` to a zero-terminated string of the format `"n/d"` with `n` and 183 1.1 mrg `d` in the specified radix and writing no more than `limit` bytes to the 184 1.1 mrg given output buffer `str`. The output of the numerator includes a sign flag 185 1.1 mrg if `r` is negative. Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`. */ 186 1.1 mrg mp_result mp_rat_to_string(mp_rat r, mp_size radix, char *str, int limit); 187 1.1 mrg 188 1.1 mrg /** Converts the value of `r` to a string in decimal-point notation with the 189 1.1 mrg specified radix, writing no more than `limit` bytes of data to the given 190 1.1 mrg output buffer. It generates `prec` digits of precision, and requires 191 1.1 mrg `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`. 192 1.1 mrg 193 1.1 mrg Ratios usually must be rounded when they are being converted for output as 194 1.1 mrg a decimal value. There are four rounding modes currently supported: 195 1.1 mrg 196 1.1 mrg MP_ROUND_DOWN 197 1.1 mrg Truncates the value toward zero. 198 1.1 mrg Example: 12.009 to 2dp becomes 12.00 199 1.1 mrg 200 1.1 mrg MP_ROUND_UP 201 1.1 mrg Rounds the value away from zero: 202 1.1 mrg Example: 12.001 to 2dp becomes 12.01, but 203 1.1 mrg 12.000 to 2dp remains 12.00 204 1.1 mrg 205 1.1 mrg MP_ROUND_HALF_DOWN 206 1.1 mrg Rounds the value to nearest digit, half goes toward zero. 207 1.1 mrg Example: 12.005 to 2dp becomes 12.00, but 208 1.1 mrg 12.006 to 2dp becomes 12.01 209 1.1 mrg 210 1.1 mrg MP_ROUND_HALF_UP 211 1.1 mrg Rounds the value to nearest digit, half rounds upward. 212 1.1 mrg Example: 12.005 to 2dp becomes 12.01, but 213 1.1 mrg 12.004 to 2dp becomes 12.00 214 1.1 mrg */ 215 1.1 mrg mp_result mp_rat_to_decimal(mp_rat r, mp_size radix, mp_size prec, 216 1.1 mrg mp_round_mode round, char *str, int limit); 217 1.1 mrg 218 1.1 mrg /** Reports the minimum number of characters required to represent `r` as a 219 1.1 mrg zero-terminated string in the given `radix`. 220 1.1 mrg Requires `MP_MIN_RADIX <= radix <= MP_MAX_RADIX`. */ 221 1.1 mrg mp_result mp_rat_string_len(mp_rat r, mp_size radix); 222 1.1 mrg 223 1.1 mrg /** Reports the length in bytes of the buffer needed to convert `r` using the 224 1.1 mrg `mp_rat_to_decimal()` function with the specified `radix` and `prec`. The 225 1.1 mrg buffer size estimate may slightly exceed the actual required capacity. */ 226 1.1 mrg mp_result mp_rat_decimal_len(mp_rat r, mp_size radix, mp_size prec); 227 1.1 mrg 228 1.1 mrg /** Sets `r` to the value represented by a zero-terminated string `str` in the 229 1.1 mrg format `"n/d"` including a sign flag. It returns `MP_UNDEF` if the encoded 230 1.1 mrg denominator has value zero. */ 231 1.1 mrg mp_result mp_rat_read_string(mp_rat r, mp_size radix, const char *str); 232 1.1 mrg 233 1.1 mrg /** Sets `r` to the value represented by a zero-terminated string `str` in the 234 1.1 mrg format `"n/d"` including a sign flag. It returns `MP_UNDEF` if the encoded 235 1.1 mrg denominator has value zero. If `end` is not NULL then `*end` is set to 236 1.1 mrg point to the first unconsumed character in the string, after parsing. 237 1.1 mrg */ 238 1.1 mrg mp_result mp_rat_read_cstring(mp_rat r, mp_size radix, const char *str, 239 1.1 mrg char **end); 240 1.1 mrg 241 1.1 mrg /** Sets `r` to the value represented by a zero-terminated string `str` having 242 1.1 mrg one of the following formats, each with an optional leading sign flag: 243 1.1 mrg 244 1.1 mrg n : integer format, e.g. "123" 245 1.1 mrg n/d : ratio format, e.g., "-12/5" 246 1.1 mrg z.ffff : decimal format, e.g., "1.627" 247 1.1 mrg 248 1.1 mrg It returns `MP_UNDEF` if the effective denominator is zero. If `end` is not 249 1.1 mrg NULL then `*end` is set to point to the first unconsumed character in the 250 1.1 mrg string, after parsing. 251 1.1 mrg */ 252 1.1 mrg mp_result mp_rat_read_ustring(mp_rat r, mp_size radix, const char *str, 253 1.1 mrg char **end); 254 1.1 mrg 255 1.1 mrg /** Sets `r` to the value represented by a zero-terminated string `str` in the 256 1.1 mrg format `"z.ffff"` including a sign flag. It returns `MP_UNDEF` if the 257 1.1 mrg effective denominator. */ 258 1.1 mrg mp_result mp_rat_read_decimal(mp_rat r, mp_size radix, const char *str); 259 1.1 mrg 260 1.1 mrg /** Sets `r` to the value represented by a zero-terminated string `str` in the 261 1.1 mrg format `"z.ffff"` including a sign flag. It returns `MP_UNDEF` if the 262 1.1 mrg effective denominator. If `end` is not NULL then `*end` is set to point to 263 1.1 mrg the first unconsumed character in the string, after parsing. */ 264 1.1 mrg mp_result mp_rat_read_cdecimal(mp_rat r, mp_size radix, const char *str, 265 1.1 mrg char **end); 266 1.1 mrg 267 1.1 mrg #ifdef __cplusplus 268 1.1 mrg } 269 1.1 mrg #endif 270 1.1 mrg #endif /* IMRAT_H_ */ 271