blob 3986efc1 (4073B) - Raw
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 <math.h> 12 #include <errno.h> 13 14 void bigfloat_init_float(BigFloat *dest, long double x) { 15 dest->value = x; 16 } 17 18 void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x) { 19 dest->value = x->value; 20 } 21 22 void bigfloat_init_bigint(BigFloat *dest, const BigInt *op) { 23 dest->value = 0.0; 24 if (op->digit_count == 0) 25 return; 26 27 long double base = (long double)UINT64_MAX; 28 const uint64_t *digits = bigint_ptr(op); 29 30 for (size_t i = op->digit_count - 1;;) { 31 uint64_t digit = digits[i]; 32 dest->value *= base; 33 dest->value += (long double)digit; 34 35 if (i == 0) { 36 if (op->is_negative) { 37 dest->value = -dest->value; 38 } 39 return; 40 } 41 i -= 1; 42 } 43 } 44 45 int bigfloat_init_buf_base10(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len) { 46 char *str_begin = (char *)buf_ptr; 47 char *str_end; 48 errno = 0; 49 dest->value = strtold(str_begin, &str_end); 50 if (errno) { 51 return ErrorOverflow; 52 } 53 assert(str_end <= ((char*)buf_ptr) + buf_len); 54 return 0; 55 } 56 57 void bigfloat_add(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { 58 dest->value = op1->value + op2->value; 59 } 60 61 void bigfloat_negate(BigFloat *dest, const BigFloat *op) { 62 dest->value = -op->value; 63 } 64 65 void bigfloat_sub(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { 66 dest->value = op1->value - op2->value; 67 } 68 69 void bigfloat_mul(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { 70 dest->value = op1->value * op2->value; 71 } 72 73 void bigfloat_div(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { 74 dest->value = op1->value / op2->value; 75 } 76 77 void bigfloat_div_trunc(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { 78 dest->value = op1->value / op2->value; 79 if (dest->value >= 0.0) { 80 dest->value = floorl(dest->value); 81 } else { 82 dest->value = ceill(dest->value); 83 } 84 } 85 86 void bigfloat_div_floor(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { 87 dest->value = floorl(op1->value / op2->value); 88 } 89 90 void bigfloat_rem(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { 91 dest->value = fmodl(op1->value, op2->value); 92 } 93 94 void bigfloat_mod(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { 95 dest->value = fmodl(fmodl(op1->value, op2->value) + op2->value, op2->value); 96 } 97 98 void bigfloat_write_buf(Buf *buf, const BigFloat *op) { 99 buf_appendf(buf, "%Lf", op->value); 100 } 101 102 Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2) { 103 if (op1->value > op2->value) { 104 return CmpGT; 105 } else if (op1->value < op2->value) { 106 return CmpLT; 107 } else { 108 return CmpEQ; 109 } 110 } 111 112 // TODO this is wrong when compiler running on big endian systems. caught by tests 113 void bigfloat_write_ieee597(const BigFloat *op, uint8_t *buf, size_t bit_count, bool is_big_endian) { 114 if (bit_count == 32) { 115 float f32 = op->value; 116 memcpy(buf, &f32, 4); 117 } else if (bit_count == 64) { 118 double f64 = op->value; 119 memcpy(buf, &f64, 8); 120 } else { 121 zig_unreachable(); 122 } 123 } 124 125 // TODO this is wrong when compiler running on big endian systems. caught by tests 126 void bigfloat_read_ieee597(BigFloat *dest, const uint8_t *buf, size_t bit_count, bool is_big_endian) { 127 if (bit_count == 32) { 128 float f32; 129 memcpy(&f32, buf, 4); 130 dest->value = f32; 131 } else if (bit_count == 64) { 132 double f64; 133 memcpy(&f64, buf, 8); 134 dest->value = f64; 135 } else { 136 zig_unreachable(); 137 } 138 } 139 140 double bigfloat_to_double(const BigFloat *bigfloat) { 141 return bigfloat->value; 142 } 143 144 Cmp bigfloat_cmp_zero(const BigFloat *bigfloat) { 145 if (bigfloat->value < 0.0) { 146 return CmpLT; 147 } else if (bigfloat->value > 0.0) { 148 return CmpGT; 149 } else { 150 return CmpEQ; 151 } 152 }