blob: babc0c479b0adf833c364a363d1e1c61cce4586c [file] [log] [blame]
Damiend99b0522013-12-21 18:17:45 +00001#include <stdlib.h>
Damiend99b0522013-12-21 18:17:45 +00002#include <assert.h>
Rachel Dowdall300c8bd2014-03-20 22:40:38 +00003#include <math.h>
Damiend99b0522013-12-21 18:17:45 +00004
5#include "nlr.h"
6#include "misc.h"
7#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +00008#include "qstr.h"
Damiend99b0522013-12-21 18:17:45 +00009#include "obj.h"
Damien George20773972014-02-22 18:12:43 +000010#include "parsenum.h"
Damiend99b0522013-12-21 18:17:45 +000011#include "runtime0.h"
12
13#if MICROPY_ENABLE_FLOAT
Damien George8bfec2b2014-03-10 13:27:02 +000014
Dave Hylandsca5a2412014-03-10 00:10:01 -070015#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
Damien George8bfec2b2014-03-10 13:27:02 +000016#include "formatfloat.h"
Dave Hylandsca5a2412014-03-10 00:10:01 -070017#endif
Damiend99b0522013-12-21 18:17:45 +000018
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020019STATIC void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
Damiend99b0522013-12-21 18:17:45 +000020 mp_obj_float_t *o = o_in;
Dave Hylandsca5a2412014-03-10 00:10:01 -070021#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
22 char buf[32];
23 format_float(o->value, buf, sizeof(buf), 'g', 6, '\0');
24 print(env, "%s", buf);
25#else
mux00a4da92014-01-27 10:21:42 +020026 print(env, "%.8g", (double) o->value);
Dave Hylandsca5a2412014-03-10 00:10:01 -070027#endif
Damiend99b0522013-12-21 18:17:45 +000028}
29
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020030STATIC mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
Damien George20006db2014-01-18 14:10:48 +000031 // TODO check n_kw == 0
32
Damien George71c51812014-01-04 20:21:15 +000033 switch (n_args) {
34 case 0:
35 return mp_obj_new_float(0);
36
37 case 1:
Damien George20773972014-02-22 18:12:43 +000038 if (MP_OBJ_IS_STR(args[0])) {
39 // a string, parse it
40 uint l;
41 const char *s = mp_obj_str_get_data(args[0], &l);
Damien George6e48f7f2014-03-21 11:45:46 +000042 return mp_parse_num_decimal(s, l, false, false);
Damien George0c36da02014-03-08 15:24:39 +000043 } else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) {
Damien George6e48f7f2014-03-21 11:45:46 +000044 // a float, just return it
Damien George71c51812014-01-04 20:21:15 +000045 return args[0];
46 } else {
Damien George6e48f7f2014-03-21 11:45:46 +000047 // something else, try to cast it to a float
Damien George71c51812014-01-04 20:21:15 +000048 return mp_obj_new_float(mp_obj_get_float(args[0]));
49 }
50
51 default:
Damien Georgec5966122014-02-15 16:10:44 +000052 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "float takes at most 1 argument, %d given", n_args));
Damien George71c51812014-01-04 20:21:15 +000053 }
54}
55
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020056STATIC mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
Damiend99b0522013-12-21 18:17:45 +000057 mp_obj_float_t *o = o_in;
58 switch (op) {
Damien Georged17926d2014-03-30 13:35:08 +010059 case MP_UNARY_OP_BOOL: return MP_BOOL(o->value != 0);
60 case MP_UNARY_OP_POSITIVE: return o_in;
61 case MP_UNARY_OP_NEGATIVE: return mp_obj_new_float(-o->value);
Damiend99b0522013-12-21 18:17:45 +000062 default: return NULL; // op not supported
63 }
64}
65
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020066STATIC mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
Damien Georgee2e3d112014-01-06 22:13:00 +000067 mp_obj_float_t *lhs = lhs_in;
Damien George0c36da02014-03-08 15:24:39 +000068 if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
Damien Georgee2e3d112014-01-06 22:13:00 +000069 return mp_obj_complex_binary_op(op, lhs->value, 0, rhs_in);
70 } else {
71 return mp_obj_float_binary_op(op, lhs->value, rhs_in);
Damiend99b0522013-12-21 18:17:45 +000072 }
Damiend99b0522013-12-21 18:17:45 +000073}
74
Damien George0c36da02014-03-08 15:24:39 +000075const mp_obj_type_t mp_type_float = {
Damien Georgec5966122014-02-15 16:10:44 +000076 { &mp_type_type },
Damien Georgea71c83a2014-02-15 11:34:50 +000077 .name = MP_QSTR_float,
Paul Sokolovsky860ffb02014-01-05 22:34:09 +020078 .print = float_print,
79 .make_new = float_make_new,
80 .unary_op = float_unary_op,
81 .binary_op = float_binary_op,
Damiend99b0522013-12-21 18:17:45 +000082};
83
84mp_obj_t mp_obj_new_float(mp_float_t value) {
85 mp_obj_float_t *o = m_new(mp_obj_float_t, 1);
Damien George0c36da02014-03-08 15:24:39 +000086 o->base.type = &mp_type_float;
Damiend99b0522013-12-21 18:17:45 +000087 o->value = value;
88 return (mp_obj_t)o;
89}
90
91mp_float_t mp_obj_float_get(mp_obj_t self_in) {
Damien George0c36da02014-03-08 15:24:39 +000092 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_float));
Damiend99b0522013-12-21 18:17:45 +000093 mp_obj_float_t *self = self_in;
94 return self->value;
95}
96
Damien Georgee2e3d112014-01-06 22:13:00 +000097mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) {
98 mp_float_t rhs_val = mp_obj_get_float(rhs_in); // can be any type, this function will convert to float (if possible)
99 switch (op) {
Damien Georged17926d2014-03-30 13:35:08 +0100100 case MP_BINARY_OP_ADD:
101 case MP_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
102 case MP_BINARY_OP_SUBTRACT:
103 case MP_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
104 case MP_BINARY_OP_MULTIPLY:
105 case MP_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
Damien Georgee2e3d112014-01-06 22:13:00 +0000106 /* TODO floor(?) the value
Damien Georged17926d2014-03-30 13:35:08 +0100107 case MP_BINARY_OP_FLOOR_DIVIDE:
108 case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
Damien Georgee2e3d112014-01-06 22:13:00 +0000109 */
Damien Georged17926d2014-03-30 13:35:08 +0100110 case MP_BINARY_OP_TRUE_DIVIDE:
111 case MP_BINARY_OP_INPLACE_TRUE_DIVIDE:
Rachel Dowdall300c8bd2014-03-20 22:40:38 +0000112 lhs_val /= rhs_val;
113 if (isinf(lhs_val)){ // check for division by zero
114 nlr_jump(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "float division by zero"));
115 }
116 break;
Damien Georged17926d2014-03-30 13:35:08 +0100117 case MP_BINARY_OP_LESS: return MP_BOOL(lhs_val < rhs_val);
118 case MP_BINARY_OP_MORE: return MP_BOOL(lhs_val > rhs_val);
119 case MP_BINARY_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val);
120 case MP_BINARY_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val);
John R. Lentonb8698fc2014-01-11 00:58:59 +0000121
Damien Georgee2e3d112014-01-06 22:13:00 +0000122 return NULL; // op not supported
123 }
124 return mp_obj_new_float(lhs_val);
125}
126
Damien George8bfec2b2014-03-10 13:27:02 +0000127#endif // MICROPY_ENABLE_FLOAT