2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 private unit private.show;
21 fn integer_to_bytes_base(n : int, b : int) : bytes;
22 fn integer_to_bytes(n : int) : bytes;
23 fn bytes_to_integer_base(a : bytes, b : int) : int;
24 fn bytes_to_integer(a : bytes) : int;
26 fn real_to_bytes_base_precision(t : type, c : class_real_number(t), n : t, b : int, digits : int) : bytes;
27 fn real_to_bytes(t : type, c : class_real_number(t), n : t) : bytes;
28 fn bytes_to_real_base(t : type, implicit c : class_real_number(t), a : bytes, b : int) : t;
29 fn bytes_to_real_hex(t : type, implicit c : class_real_number(t), a : bytes) : t;
30 fn bytes_to_real(t : type, c : class_real_number(t), a : bytes) : t;
32 fn real_to_rational(t : type, implicit c : class_real_number(t), n : t) : rational;
33 fn rational_to_real(t : type, implicit c : class_real_number(t), a : rational) : t;
39 fn byte_to_num(c : byte, b : int) : int
42 if c >= #30 and c < #3a then
44 else if c >= #41 and c < #5b then
46 else if c >= #61 and c < #7b then
50 abort exception_make(int, ec_sync, error_invalid_operation, 0, true);
57 fn integer_to_bytes_base(n : int, b : int) : bytes
59 if b < 2 or b > 36 then
60 abort exception_make(bytes, ec_sync, error_invalid_operation, 0, true);
63 return "-" + integer_to_bytes_base(-n, b);
65 var result := empty(byte);
67 if (b and b - 1) = 0 then [
73 if (bb and bb - 1) = 0 then
112 fn integer_to_bytes(n : int) : bytes
114 return integer_to_bytes_base~inline(n, 10);
117 fn bytes_to_integer_base(a : bytes, b : int) : int
119 if b < 2 or b > 36 then [
121 abort exception_make(bytes, ec_sync, error_invalid_operation, 0, true);
124 if len_greater_than(a, 0) and a[0] = '-' then [
127 ] else if len_greater_than(a, 0) and a[0] = '+' then [
130 if not len_greater_than(a, 0) then
133 for i := 0 to len(a) do [
135 var v := byte_to_num(c, b);
136 result := result * b + v;
138 return result * sign;
141 fn bytes_to_integer(a : bytes) : int
143 return bytes_to_integer_base~inline(a, 10);
147 fn real_to_bytes_base_precision(t : type, implicit c : class_real_number(t), n : t, b : int, digits : int) : bytes
149 if b < 2 or b > 36 or digits < 0 then
150 abort exception_make(bytes, ec_sync, error_invalid_operation, 0, true);
152 if is_negative n then [
156 if is_infinity n then [
163 for i := 0 to digits do [
166 frac := frac * b + inn;
171 var imul := ipower(b, digits);
172 if frac >= imul then [
179 fracstr := integer_to_bytes_base(frac, b);
182 if len(fracstr) < digits then
183 fracstr := fill(byte, '0', digits - len(fracstr)) + fracstr;
184 result += integer_to_bytes_base(inx, b);
190 fn real_to_bytes(t : type, implicit c : class_real_number(t), n : t) : bytes
192 return real_to_bytes_base_precision~inline(t, c, n, 10, 10);
195 fn bytes_to_real_base(t : type, implicit c : class_real_number(t), a : bytes, b : int) : t
197 if b < 2 or b > 36 then
198 abort exception_make(bytes, ec_sync, error_invalid_operation, 0, true);
200 var negative := false;
201 if len_greater_than(a, 0), a[0] = '-' then [
204 ] else if len_greater_than(a, 0), a[0] = '+' then [
212 var ex := select(b > 10, 'E', 'P');
213 var ex_pos := list_search(a, ex);
215 ex_pos := list_search(a, ex + #20);
217 if ex_pos <> -1 then [
218 e := bytes_to_integer(a[ex_pos + 1 .. ]);
222 var before_dot after_dot : bytes;
223 var dot := list_search(a, '.');
228 before_dot := a[ .. dot];
229 after_dot := a[dot + 1 .. ];
233 if e > len(after_dot) then [
234 after_dot += fill(byte, '0', e - len(after_dot));
236 var t := after_dot[ .. e];
238 after_dot := after_dot[e .. ];
239 ] else if e < 0 then [
241 if e > len(before_dot) then [
242 before_dot := fill(byte, '0', e - len(before_dot)) + before_dot;
244 var t := before_dot[len(before_dot) - e .. ];
245 after_dot := t + after_dot;
246 before_dot := before_dot[ .. len(before_dot) - e];
249 //eval debug("before_dot: '" + before_dot + "', after_dot: '" + after_dot + "'");
251 while len(before_dot) > 0 do [
252 var d : t := byte_to_num(before_dot[0], b);
254 before_dot := before_dot[1 .. ];
257 while len(after_dot) > 0 do [
258 var d : t := byte_to_num(after_dot[0], b);
259 r := r + d * digits / b;
261 after_dot := after_dot[1 .. ];
270 fn bytes_to_real_hex(t : type, implicit c : class_real_number(t), a : bytes) : t
272 var b := empty(byte);
273 for i := 0 to len(a) do [
274 if a[i] = 'p' or a[i] = 'P' then [
284 var bin := ntos_base(ston_base(str, 16), 2);
285 b += fill(byte, '0', 4 - len(bin));
288 //eval debug("bytes_to_real_hex: " + a + " -> " + b + ".");
289 return bytes_to_real_base(t, c, b, 2);
292 fn bytes_to_real(t : type, implicit c : class_real_number(t), a : bytes) : t
294 return bytes_to_real_base(t, c, a, 10);
297 fn real_to_rational(t : type, implicit c : class_real_number(t), n : t) : rational
299 if is_infinity n then [
300 if not is_negative n then [
301 return instance_real_number_rational.from_int(1) / instance_real_number_rational.from_int(0);
303 return instance_real_number_rational.from_int(-1) / instance_real_number_rational.from_int(0);
307 if n = 0, is_negative n then
311 return instance_real_number_rational.from_int(n) / instance_real_number_rational.from_int(den);
316 var nn := ldexp(n, q);
317 if fract(nn) = 0 then
324 var qq := q - (1 shl bit);
325 var nn := ldexp(n, qq);
326 if fract(nn) = 0 then
329 var num := ldexp(n, q);
331 return instance_real_number_rational.from_int(num) / instance_real_number_rational.from_int(den);
334 fn int_to_real(t : type, implicit c : class_real_number(t), i : int) : (t, int)
336 var num := c.from_int(i);
337 if not is_infinity num then
343 num := c.from_int(i shr q);
344 if not is_infinity num then
351 var qq := q - (1 shl bit);
352 num := c.from_int(i shr qq);
353 if not is_infinity num then
357 num := c.from_int(i shr q);
361 fn rational_to_real(t : type, implicit c : class_real_number(t), a : rational) : t
365 var num_t, adj_p := int_to_real(t, c, num);
366 var den_t, adj_m := int_to_real(t, c, den);
367 var adj := adj_p - adj_m;
368 //return num_t / den_t * ldexp(c.one, adj);
369 return ldexp(num_t / den_t, adj);