Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2017 Andrew Kelley
3 : : *
4 : : * This file is part of zig, which is MIT licensed.
5 : : * See http://opensource.org/licenses/MIT
6 : : */
7 : :
8 : : #include "bigfloat.hpp"
9 : : #include "bigint.hpp"
10 : : #include "buffer.hpp"
11 : : #include "softfloat.hpp"
12 : : #include "parse_f128.h"
13 : : #include <stdio.h>
14 : : #include <math.h>
15 : : #include <errno.h>
16 : :
17 : :
18 : 0 : void bigfloat_init_128(BigFloat *dest, float128_t x) {
19 : 0 : dest->value = x;
20 : 0 : }
21 : :
22 : 0 : void bigfloat_init_16(BigFloat *dest, float16_t x) {
23 : 0 : f16_to_f128M(x, &dest->value);
24 : 0 : }
25 : :
26 : 18535 : void bigfloat_init_32(BigFloat *dest, float x) {
27 : : float32_t f32_val;
28 : 18535 : memcpy(&f32_val, &x, sizeof(float));
29 : 18535 : f32_to_f128M(f32_val, &dest->value);
30 : 18535 : }
31 : :
32 : 0 : void bigfloat_init_64(BigFloat *dest, double x) {
33 : : float64_t f64_val;
34 : 0 : memcpy(&f64_val, &x, sizeof(double));
35 : 0 : f64_to_f128M(f64_val, &dest->value);
36 : 0 : }
37 : :
38 : 86337 : void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x) {
39 : 86337 : memcpy(&dest->value, &x->value, sizeof(float128_t));
40 : 86337 : }
41 : :
42 : 10000 : void bigfloat_init_bigint(BigFloat *dest, const BigInt *op) {
43 : 10000 : ui32_to_f128M(0, &dest->value);
44 [ + + ]: 10000 : if (op->digit_count == 0)
45 : 542 : return;
46 : :
47 : : float128_t base;
48 : 9458 : ui64_to_f128M(UINT64_MAX, &base);
49 : 9458 : const uint64_t *digits = bigint_ptr(op);
50 : :
51 : 9458 : for (size_t i = op->digit_count - 1;;) {
52 : : float128_t digit_f128;
53 : 9474 : ui64_to_f128M(digits[i], &digit_f128);
54 : :
55 : 9474 : f128M_mulAdd(&dest->value, &base, &digit_f128, &dest->value);
56 : :
57 [ + + ]: 9474 : if (i == 0) {
58 [ + + ]: 9458 : if (op->is_negative) {
59 : : float128_t zero_f128;
60 : 3910 : ui32_to_f128M(0, &zero_f128);
61 : 3910 : f128M_sub(&zero_f128, &dest->value, &dest->value);
62 : : }
63 : 10000 : return;
64 : : }
65 : 16 : i -= 1;
66 : 16 : }
67 : : }
68 : :
69 : 18535 : Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len) {
70 : 18535 : char *str_begin = (char *)buf_ptr;
71 : : char *str_end;
72 : :
73 : 18535 : errno = 0;
74 : 18535 : dest->value = parse_f128(str_begin, &str_end);
75 [ - + ]: 18535 : if (errno) {
76 : 0 : return ErrorOverflow;
77 : : }
78 : :
79 : 18535 : assert(str_end <= ((char*)buf_ptr) + buf_len);
80 : 18535 : return ErrorNone;
81 : : }
82 : :
83 : 18 : void bigfloat_add(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
84 : 18 : f128M_add(&op1->value, &op2->value, &dest->value);
85 : 18 : }
86 : :
87 : 11308 : void bigfloat_negate(BigFloat *dest, const BigFloat *op) {
88 : : float128_t zero_f128;
89 : 11308 : ui32_to_f128M(0, &zero_f128);
90 : 11308 : f128M_sub(&zero_f128, &op->value, &dest->value);
91 : 11308 : }
92 : :
93 : 0 : void bigfloat_sub(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
94 : 0 : f128M_sub(&op1->value, &op2->value, &dest->value);
95 : 0 : }
96 : :
97 : 32 : void bigfloat_mul(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
98 : 32 : f128M_mul(&op1->value, &op2->value, &dest->value);
99 : 32 : }
100 : :
101 : 12 : void bigfloat_div(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
102 : 12 : f128M_div(&op1->value, &op2->value, &dest->value);
103 : 12 : }
104 : :
105 : 0 : void bigfloat_div_trunc(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
106 : 0 : f128M_div(&op1->value, &op2->value, &dest->value);
107 : 0 : f128M_roundToInt(&dest->value, softfloat_round_minMag, false, &dest->value);
108 : 0 : }
109 : :
110 : 0 : void bigfloat_div_floor(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
111 : 0 : f128M_div(&op1->value, &op2->value, &dest->value);
112 : 0 : f128M_roundToInt(&dest->value, softfloat_round_min, false, &dest->value);
113 : 0 : }
114 : :
115 : 0 : void bigfloat_rem(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
116 : 0 : f128M_rem(&op1->value, &op2->value, &dest->value);
117 : 0 : }
118 : :
119 : 0 : void bigfloat_mod(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) {
120 : 0 : f128M_rem(&op1->value, &op2->value, &dest->value);
121 : 0 : f128M_add(&dest->value, &op2->value, &dest->value);
122 : 0 : f128M_rem(&dest->value, &op2->value, &dest->value);
123 : 0 : }
124 : :
125 : 0 : void bigfloat_append_buf(Buf *buf, const BigFloat *op) {
126 : 0 : const size_t extra_len = 100;
127 : 0 : size_t old_len = buf_len(buf);
128 : 0 : buf_resize(buf, old_len + extra_len);
129 : :
130 : : // TODO actually print f128
131 : 0 : float64_t f64_value = f128M_to_f64(&op->value);
132 : : double double_value;
133 : 0 : memcpy(&double_value, &f64_value, sizeof(double));
134 : :
135 : 0 : int len = snprintf(buf_ptr(buf) + old_len, extra_len, "%f", double_value);
136 : 0 : assert(len > 0);
137 : 0 : buf_resize(buf, old_len + len);
138 : 0 : }
139 : :
140 : 56 : Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2) {
141 [ - + ]: 56 : if (f128M_lt(&op1->value, &op2->value)) {
142 : 0 : return CmpLT;
143 [ + - ]: 56 : } else if (f128M_eq(&op1->value, &op2->value)) {
144 : 56 : return CmpEQ;
145 : : } else {
146 : 0 : return CmpGT;
147 : : }
148 : : }
149 : :
150 : 648 : float16_t bigfloat_to_f16(const BigFloat *bigfloat) {
151 : 648 : return f128M_to_f16(&bigfloat->value);
152 : : }
153 : :
154 : 2186 : float bigfloat_to_f32(const BigFloat *bigfloat) {
155 : 2186 : float32_t f32_value = f128M_to_f32(&bigfloat->value);
156 : : float result;
157 : 2186 : memcpy(&result, &f32_value, sizeof(float));
158 : 2186 : return result;
159 : : }
160 : :
161 : 70410 : double bigfloat_to_f64(const BigFloat *bigfloat) {
162 : 70410 : float64_t f64_value = f128M_to_f64(&bigfloat->value);
163 : : double result;
164 : 70410 : memcpy(&result, &f64_value, sizeof(double));
165 : 70410 : return result;
166 : : }
167 : :
168 : 550 : float128_t bigfloat_to_f128(const BigFloat *bigfloat) {
169 : 550 : return bigfloat->value;
170 : : }
171 : :
172 : 186 : Cmp bigfloat_cmp_zero(const BigFloat *bigfloat) {
173 : : float128_t zero_float;
174 : 186 : ui32_to_f128M(0, &zero_float);
175 [ - + ]: 186 : if (f128M_lt(&bigfloat->value, &zero_float)) {
176 : 0 : return CmpLT;
177 [ - + ]: 186 : } else if (f128M_eq(&bigfloat->value, &zero_float)) {
178 : 0 : return CmpEQ;
179 : : } else {
180 : 186 : return CmpGT;
181 : : }
182 : : }
183 : :
184 : 24 : bool bigfloat_has_fraction(const BigFloat *bigfloat) {
185 : : float128_t floored;
186 : 24 : f128M_roundToInt(&bigfloat->value, softfloat_round_minMag, false, &floored);
187 : 24 : return !f128M_eq(&floored, &bigfloat->value);
188 : : }
189 : :
190 : 0 : void bigfloat_sqrt(BigFloat *dest, const BigFloat *op) {
191 : 0 : f128M_sqrt(&op->value, &dest->value);
192 : 0 : }
193 : :
194 : 112 : bool bigfloat_is_nan(const BigFloat *op) {
195 : 112 : return f128M_isSignalingNaN(&op->value);
196 : : }
|