objfloat.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2013, 2014 Damien P. George
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <assert.h>
  30. #include "py/parsenum.h"
  31. #include "py/runtime.h"
  32. #if MICROPY_PY_BUILTINS_FLOAT
  33. #include <math.h>
  34. #include "py/formatfloat.h"
  35. #if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D
  36. // M_E and M_PI are not part of the math.h standard and may not be defined
  37. #ifndef M_E
  38. #define M_E (2.7182818284590452354)
  39. #endif
  40. #ifndef M_PI
  41. #define M_PI (3.14159265358979323846)
  42. #endif
  43. typedef struct _mp_obj_float_t {
  44. mp_obj_base_t base;
  45. mp_float_t value;
  46. } mp_obj_float_t;
  47. const mp_obj_float_t mp_const_float_e_obj = {{&mp_type_float}, M_E};
  48. const mp_obj_float_t mp_const_float_pi_obj = {{&mp_type_float}, M_PI};
  49. #endif
  50. #if MICROPY_FLOAT_HIGH_QUALITY_HASH
  51. // must return actual integer value if it fits in mp_int_t
  52. mp_int_t mp_float_hash(mp_float_t src) {
  53. #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
  54. typedef uint64_t mp_float_uint_t;
  55. #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
  56. typedef uint32_t mp_float_uint_t;
  57. #endif
  58. union {
  59. mp_float_t f;
  60. #if MP_ENDIANNESS_LITTLE
  61. struct { mp_float_uint_t frc:MP_FLOAT_FRAC_BITS, exp:MP_FLOAT_EXP_BITS, sgn:1; } p;
  62. #else
  63. struct { mp_float_uint_t sgn:1, exp:MP_FLOAT_EXP_BITS, frc:MP_FLOAT_FRAC_BITS; } p;
  64. #endif
  65. mp_float_uint_t i;
  66. } u = {.f = src};
  67. mp_int_t val;
  68. const int adj_exp = (int)u.p.exp - MP_FLOAT_EXP_BIAS;
  69. if (adj_exp < 0) {
  70. // value < 1; must be sure to handle 0.0 correctly (ie return 0)
  71. val = u.i;
  72. } else {
  73. // if adj_exp is max then: u.p.frc==0 indicates inf, else NaN
  74. // else: 1 <= value
  75. mp_float_uint_t frc = u.p.frc | ((mp_float_uint_t)1 << MP_FLOAT_FRAC_BITS);
  76. if (adj_exp <= MP_FLOAT_FRAC_BITS) {
  77. // number may have a fraction; xor the integer part with the fractional part
  78. val = (frc >> (MP_FLOAT_FRAC_BITS - adj_exp))
  79. ^ (frc & (((mp_float_uint_t)1 << (MP_FLOAT_FRAC_BITS - adj_exp)) - 1));
  80. } else if ((unsigned int)adj_exp < BITS_PER_BYTE * sizeof(mp_int_t) - 1) {
  81. // the number is a (big) whole integer and will fit in val's signed-width
  82. val = (mp_int_t)frc << (adj_exp - MP_FLOAT_FRAC_BITS);
  83. } else {
  84. // integer part will overflow val's width so just use what bits we can
  85. val = frc;
  86. }
  87. }
  88. if (u.p.sgn) {
  89. val = -(mp_uint_t)val;
  90. }
  91. return val;
  92. }
  93. #endif
  94. STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
  95. (void)kind;
  96. mp_float_t o_val = mp_obj_float_get(o_in);
  97. #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
  98. char buf[16];
  99. #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C
  100. const int precision = 6;
  101. #else
  102. const int precision = 7;
  103. #endif
  104. #else
  105. char buf[32];
  106. const int precision = 16;
  107. #endif
  108. mp_format_float(o_val, buf, sizeof(buf), 'g', precision, '\0');
  109. mp_print_str(print, buf);
  110. if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL && strchr(buf, 'n') == NULL) {
  111. // Python floats always have decimal point (unless inf or nan)
  112. mp_print_str(print, ".0");
  113. }
  114. }
  115. STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
  116. (void)type_in;
  117. mp_arg_check_num(n_args, n_kw, 0, 1, false);
  118. switch (n_args) {
  119. case 0:
  120. return mp_obj_new_float(0);
  121. case 1:
  122. default: {
  123. mp_buffer_info_t bufinfo;
  124. if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) {
  125. // a textual representation, parse it
  126. return mp_parse_num_decimal(bufinfo.buf, bufinfo.len, false, false, NULL);
  127. } else if (mp_obj_is_float(args[0])) {
  128. // a float, just return it
  129. return args[0];
  130. } else {
  131. // something else, try to cast it to a float
  132. return mp_obj_new_float(mp_obj_get_float(args[0]));
  133. }
  134. }
  135. }
  136. }
  137. STATIC mp_obj_t float_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
  138. mp_float_t val = mp_obj_float_get(o_in);
  139. switch (op) {
  140. case MP_UNARY_OP_BOOL: return mp_obj_new_bool(val != 0);
  141. case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(val));
  142. case MP_UNARY_OP_POSITIVE: return o_in;
  143. case MP_UNARY_OP_NEGATIVE: return mp_obj_new_float(-val);
  144. case MP_UNARY_OP_ABS: {
  145. // TODO check for NaN etc
  146. if (val < 0) {
  147. return mp_obj_new_float(-val);
  148. } else {
  149. return o_in;
  150. }
  151. }
  152. default: return MP_OBJ_NULL; // op not supported
  153. }
  154. }
  155. STATIC mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
  156. mp_float_t lhs_val = mp_obj_float_get(lhs_in);
  157. #if MICROPY_PY_BUILTINS_COMPLEX
  158. if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
  159. return mp_obj_complex_binary_op(op, lhs_val, 0, rhs_in);
  160. } else
  161. #endif
  162. {
  163. return mp_obj_float_binary_op(op, lhs_val, rhs_in);
  164. }
  165. }
  166. const mp_obj_type_t mp_type_float = {
  167. { &mp_type_type },
  168. .name = MP_QSTR_float,
  169. .print = float_print,
  170. .make_new = float_make_new,
  171. .unary_op = float_unary_op,
  172. .binary_op = float_binary_op,
  173. };
  174. #if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D
  175. mp_obj_t mp_obj_new_float(mp_float_t value) {
  176. mp_obj_float_t *o = m_new(mp_obj_float_t, 1);
  177. o->base.type = &mp_type_float;
  178. o->value = value;
  179. return MP_OBJ_FROM_PTR(o);
  180. }
  181. mp_float_t mp_obj_float_get(mp_obj_t self_in) {
  182. assert(mp_obj_is_float(self_in));
  183. mp_obj_float_t *self = MP_OBJ_TO_PTR(self_in);
  184. return self->value;
  185. }
  186. #endif
  187. STATIC void mp_obj_float_divmod(mp_float_t *x, mp_float_t *y) {
  188. // logic here follows that of CPython
  189. // https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations
  190. // x == (x//y)*y + (x%y)
  191. // divmod(x, y) == (x//y, x%y)
  192. mp_float_t mod = MICROPY_FLOAT_C_FUN(fmod)(*x, *y);
  193. mp_float_t div = (*x - mod) / *y;
  194. // Python specs require that mod has same sign as second operand
  195. if (mod == 0.0) {
  196. mod = MICROPY_FLOAT_C_FUN(copysign)(0.0, *y);
  197. } else {
  198. if ((mod < 0.0) != (*y < 0.0)) {
  199. mod += *y;
  200. div -= 1.0;
  201. }
  202. }
  203. mp_float_t floordiv;
  204. if (div == 0.0) {
  205. // if division is zero, take the correct sign of zero
  206. floordiv = MICROPY_FLOAT_C_FUN(copysign)(0.0, *x / *y);
  207. } else {
  208. // Python specs require that x == (x//y)*y + (x%y)
  209. floordiv = MICROPY_FLOAT_C_FUN(floor)(div);
  210. if (div - floordiv > 0.5) {
  211. floordiv += 1.0;
  212. }
  213. }
  214. // return results
  215. *x = floordiv;
  216. *y = mod;
  217. }
  218. mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t rhs_in) {
  219. mp_float_t rhs_val;
  220. if (!mp_obj_get_float_maybe(rhs_in, &rhs_val)) {
  221. return MP_OBJ_NULL; // op not supported
  222. }
  223. switch (op) {
  224. case MP_BINARY_OP_ADD:
  225. case MP_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
  226. case MP_BINARY_OP_SUBTRACT:
  227. case MP_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
  228. case MP_BINARY_OP_MULTIPLY:
  229. case MP_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
  230. case MP_BINARY_OP_FLOOR_DIVIDE:
  231. case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:
  232. if (rhs_val == 0) {
  233. zero_division_error:
  234. mp_raise_msg(&mp_type_ZeroDivisionError, "division by zero");
  235. }
  236. // Python specs require that x == (x//y)*y + (x%y) so we must
  237. // call divmod to compute the correct floor division, which
  238. // returns the floor divide in lhs_val.
  239. mp_obj_float_divmod(&lhs_val, &rhs_val);
  240. break;
  241. case MP_BINARY_OP_TRUE_DIVIDE:
  242. case MP_BINARY_OP_INPLACE_TRUE_DIVIDE:
  243. if (rhs_val == 0) {
  244. goto zero_division_error;
  245. }
  246. lhs_val /= rhs_val;
  247. break;
  248. case MP_BINARY_OP_MODULO:
  249. case MP_BINARY_OP_INPLACE_MODULO:
  250. if (rhs_val == 0) {
  251. goto zero_division_error;
  252. }
  253. lhs_val = MICROPY_FLOAT_C_FUN(fmod)(lhs_val, rhs_val);
  254. // Python specs require that mod has same sign as second operand
  255. if (lhs_val == 0.0) {
  256. lhs_val = MICROPY_FLOAT_C_FUN(copysign)(0.0, rhs_val);
  257. } else {
  258. if ((lhs_val < 0.0) != (rhs_val < 0.0)) {
  259. lhs_val += rhs_val;
  260. }
  261. }
  262. break;
  263. case MP_BINARY_OP_POWER:
  264. case MP_BINARY_OP_INPLACE_POWER:
  265. if (lhs_val == 0 && rhs_val < 0 && !isinf(rhs_val)) {
  266. goto zero_division_error;
  267. }
  268. if (lhs_val < 0 && rhs_val != MICROPY_FLOAT_C_FUN(floor)(rhs_val)) {
  269. #if MICROPY_PY_BUILTINS_COMPLEX
  270. return mp_obj_complex_binary_op(MP_BINARY_OP_POWER, lhs_val, 0, rhs_in);
  271. #else
  272. mp_raise_ValueError("complex values not supported");
  273. #endif
  274. }
  275. lhs_val = MICROPY_FLOAT_C_FUN(pow)(lhs_val, rhs_val);
  276. break;
  277. case MP_BINARY_OP_DIVMOD: {
  278. if (rhs_val == 0) {
  279. goto zero_division_error;
  280. }
  281. mp_obj_float_divmod(&lhs_val, &rhs_val);
  282. mp_obj_t tuple[2] = {
  283. mp_obj_new_float(lhs_val),
  284. mp_obj_new_float(rhs_val),
  285. };
  286. return mp_obj_new_tuple(2, tuple);
  287. }
  288. case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val);
  289. case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val);
  290. case MP_BINARY_OP_EQUAL: return mp_obj_new_bool(lhs_val == rhs_val);
  291. case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val);
  292. case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val);
  293. default:
  294. return MP_OBJ_NULL; // op not supported
  295. }
  296. return mp_obj_new_float(lhs_val);
  297. }
  298. #endif // MICROPY_PY_BUILTINS_FLOAT