mirror of
https://github.com/micropython/micropython.git
synced 2025-12-16 09:50:15 +01:00
py/parse: Add support for math module constants and float folding.
Add a new MICROPY_COMP_CONST_FLOAT feature, enabled by in mpy-cross and
when compiling with MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES. The new
feature leverages the code of MICROPY_COMP_CONST_FOLDING to support folding
of floating point constants.
If MICROPY_COMP_MODULE_CONST is defined as well, math module constants are
made available at compile time. For example:
_DEG_TO_GRADIANT = const(math.pi / 180)
_INVALID_VALUE = const(math.nan)
A few corner cases had to be handled:
- The float const folding code should not fold expressions resulting into
complex results, as the mpy parser for complex immediates has
limitations.
- The constant generation code must distinguish between -0.0 and 0.0, which
are different even if C consider them as ==.
This change removes previous limitations on the use of `const()`
expressions that would result in floating point number, so the test cases
of micropython/const_error have to be updated.
Additional test cases have been added to cover the new repr() code (from a
previous commit). A few other simple test cases have been added to handle
the use of floats in `const()` expressions, but the float folding code
itself is also tested when running general float test cases, as float
expressions often get resolved at compile-time (with this change).
Signed-off-by: Yoctopuce dev <dev@yoctopuce.com>
This commit is contained in:
committed by
Damien George
parent
f67a370311
commit
69ead7d98e
@@ -55,6 +55,7 @@
|
|||||||
#define MICROPY_COMP_CONST_FOLDING (1)
|
#define MICROPY_COMP_CONST_FOLDING (1)
|
||||||
#define MICROPY_COMP_MODULE_CONST (1)
|
#define MICROPY_COMP_MODULE_CONST (1)
|
||||||
#define MICROPY_COMP_CONST (1)
|
#define MICROPY_COMP_CONST (1)
|
||||||
|
#define MICROPY_COMP_CONST_FLOAT (1)
|
||||||
#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1)
|
#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1)
|
||||||
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
|
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
|
||||||
#define MICROPY_COMP_RETURN_IF_EXPR (1)
|
#define MICROPY_COMP_RETURN_IF_EXPR (1)
|
||||||
@@ -88,7 +89,8 @@
|
|||||||
#define MICROPY_PY_ARRAY (0)
|
#define MICROPY_PY_ARRAY (0)
|
||||||
#define MICROPY_PY_ATTRTUPLE (0)
|
#define MICROPY_PY_ATTRTUPLE (0)
|
||||||
#define MICROPY_PY_COLLECTIONS (0)
|
#define MICROPY_PY_COLLECTIONS (0)
|
||||||
#define MICROPY_PY_MATH (0)
|
#define MICROPY_PY_MATH (MICROPY_COMP_CONST_FLOAT)
|
||||||
|
#define MICROPY_PY_MATH_CONSTANTS (MICROPY_COMP_CONST_FLOAT)
|
||||||
#define MICROPY_PY_CMATH (0)
|
#define MICROPY_PY_CMATH (0)
|
||||||
#define MICROPY_PY_GC (0)
|
#define MICROPY_PY_GC (0)
|
||||||
#define MICROPY_PY_IO (0)
|
#define MICROPY_PY_IO (0)
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ extern const mp_obj_module_t mp_module_sys;
|
|||||||
extern const mp_obj_module_t mp_module_errno;
|
extern const mp_obj_module_t mp_module_errno;
|
||||||
extern const mp_obj_module_t mp_module_uctypes;
|
extern const mp_obj_module_t mp_module_uctypes;
|
||||||
extern const mp_obj_module_t mp_module_machine;
|
extern const mp_obj_module_t mp_module_machine;
|
||||||
|
extern const mp_obj_module_t mp_module_math;
|
||||||
|
|
||||||
extern const char MICROPY_PY_BUILTINS_HELP_TEXT[];
|
extern const char MICROPY_PY_BUILTINS_HELP_TEXT[];
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "py/emit.h"
|
#include "py/emit.h"
|
||||||
#include "py/nativeglue.h"
|
#include "py/nativeglue.h"
|
||||||
@@ -72,7 +73,21 @@ static bool strictly_equal(mp_obj_t a, mp_obj_t b) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return mp_obj_equal(a, b);
|
if (!mp_obj_equal(a, b)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#if MICROPY_PY_BUILTINS_FLOAT && MICROPY_COMP_CONST_FLOAT
|
||||||
|
if (a_type == &mp_type_float) {
|
||||||
|
mp_float_t a_val = mp_obj_float_get(a);
|
||||||
|
if (a_val == (mp_float_t)0.0) {
|
||||||
|
// Although 0.0 == -0.0, they are not strictly_equal and
|
||||||
|
// must be stored as two different constants in .mpy files
|
||||||
|
mp_float_t b_val = mp_obj_float_get(b);
|
||||||
|
return signbit(a_val) == signbit(b_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -490,6 +490,13 @@
|
|||||||
#define MICROPY_COMP_CONST (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES)
|
#define MICROPY_COMP_CONST (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Whether to enable float constant folding like 1.2+3.4 (when MICROPY_COMP_CONST_FOLDING is also enabled)
|
||||||
|
// and constant optimisation like id = const(1.2) (when MICROPY_COMP_CONST is also enabled)
|
||||||
|
// and constant lookup like math.inf (when MICROPY_COMP_MODULE_CONST is also enabled)
|
||||||
|
#ifndef MICROPY_COMP_CONST_FLOAT
|
||||||
|
#define MICROPY_COMP_CONST_FLOAT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Whether to enable optimisation of: a, b = c, d
|
// Whether to enable optimisation of: a, b = c, d
|
||||||
// Costs 124 bytes (Thumb2)
|
// Costs 124 bytes (Thumb2)
|
||||||
#ifndef MICROPY_COMP_DOUBLE_TUPLE_ASSIGN
|
#ifndef MICROPY_COMP_DOUBLE_TUPLE_ASSIGN
|
||||||
|
|||||||
91
py/parse.c
91
py/parse.c
@@ -336,18 +336,34 @@ static uint8_t peek_rule(parser_t *parser, size_t n) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) {
|
#if MICROPY_COMP_CONST_FOLDING || MICROPY_EMIT_INLINE_ASM
|
||||||
|
static bool mp_parse_node_get_number_maybe(mp_parse_node_t pn, mp_obj_t *o) {
|
||||||
if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
|
if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
|
||||||
*o = MP_OBJ_NEW_SMALL_INT(MP_PARSE_NODE_LEAF_SMALL_INT(pn));
|
*o = MP_OBJ_NEW_SMALL_INT(MP_PARSE_NODE_LEAF_SMALL_INT(pn));
|
||||||
return true;
|
return true;
|
||||||
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_const_object)) {
|
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_const_object)) {
|
||||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
|
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
|
||||||
*o = mp_parse_node_extract_const_object(pns);
|
*o = mp_parse_node_extract_const_object(pns);
|
||||||
return mp_obj_is_int(*o);
|
return mp_obj_is_int(*o)
|
||||||
|
#if MICROPY_COMP_CONST_FLOAT
|
||||||
|
|| mp_obj_is_float(*o)
|
||||||
|
#endif
|
||||||
|
;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MICROPY_EMIT_INLINE_ASM
|
||||||
|
bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) {
|
||||||
|
return mp_parse_node_get_number_maybe(pn, o)
|
||||||
|
#if MICROPY_COMP_CONST_FLOAT
|
||||||
|
&& mp_obj_is_int(*o)
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if MICROPY_COMP_CONST_TUPLE || MICROPY_COMP_CONST
|
#if MICROPY_COMP_CONST_TUPLE || MICROPY_COMP_CONST
|
||||||
static bool mp_parse_node_is_const(mp_parse_node_t pn) {
|
static bool mp_parse_node_is_const(mp_parse_node_t pn) {
|
||||||
@@ -642,12 +658,32 @@ static const mp_rom_map_elem_t mp_constants_table[] = {
|
|||||||
#if MICROPY_PY_UCTYPES
|
#if MICROPY_PY_UCTYPES
|
||||||
{ MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },
|
{ MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },
|
||||||
#endif
|
#endif
|
||||||
|
#if MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_MATH && MICROPY_COMP_CONST_FLOAT
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_math), MP_ROM_PTR(&mp_module_math) },
|
||||||
|
#endif
|
||||||
// Extra constants as defined by a port
|
// Extra constants as defined by a port
|
||||||
MICROPY_PORT_CONSTANTS
|
MICROPY_PORT_CONSTANTS
|
||||||
};
|
};
|
||||||
static MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table);
|
static MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool binary_op_maybe(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs, mp_obj_t *res) {
|
||||||
|
nlr_buf_t nlr;
|
||||||
|
if (nlr_push(&nlr) == 0) {
|
||||||
|
mp_obj_t tmp = mp_binary_op(op, lhs, rhs);
|
||||||
|
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||||
|
if (mp_obj_is_type(tmp, &mp_type_complex)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
*res = tmp;
|
||||||
|
nlr_pop();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *num_args) {
|
static bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *num_args) {
|
||||||
if (rule_id == RULE_or_test
|
if (rule_id == RULE_or_test
|
||||||
|| rule_id == RULE_and_test) {
|
|| rule_id == RULE_and_test) {
|
||||||
@@ -706,7 +742,7 @@ static bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *nu
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
|
static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
|
||||||
// this code does folding of arbitrary integer expressions, eg 1 + 2 * 3 + 4
|
// this code does folding of arbitrary numeric expressions, eg 1 + 2 * 3 + 4
|
||||||
// it does not do partial folding, eg 1 + 2 + x -> 3 + x
|
// it does not do partial folding, eg 1 + 2 + x -> 3 + x
|
||||||
|
|
||||||
mp_obj_t arg0;
|
mp_obj_t arg0;
|
||||||
@@ -716,7 +752,7 @@ static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
|
|||||||
|| rule_id == RULE_power) {
|
|| rule_id == RULE_power) {
|
||||||
// folding for binary ops: | ^ & **
|
// folding for binary ops: | ^ & **
|
||||||
mp_parse_node_t pn = peek_result(parser, num_args - 1);
|
mp_parse_node_t pn = peek_result(parser, num_args - 1);
|
||||||
if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
|
if (!mp_parse_node_get_number_maybe(pn, &arg0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mp_binary_op_t op;
|
mp_binary_op_t op;
|
||||||
@@ -732,58 +768,61 @@ static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
|
|||||||
for (ssize_t i = num_args - 2; i >= 0; --i) {
|
for (ssize_t i = num_args - 2; i >= 0; --i) {
|
||||||
pn = peek_result(parser, i);
|
pn = peek_result(parser, i);
|
||||||
mp_obj_t arg1;
|
mp_obj_t arg1;
|
||||||
if (!mp_parse_node_get_int_maybe(pn, &arg1)) {
|
if (!mp_parse_node_get_number_maybe(pn, &arg1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#if !MICROPY_COMP_CONST_FLOAT
|
||||||
if (op == MP_BINARY_OP_POWER && mp_obj_int_sign(arg1) < 0) {
|
if (op == MP_BINARY_OP_POWER && mp_obj_int_sign(arg1) < 0) {
|
||||||
// ** can't have negative rhs
|
// ** can't have negative rhs
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
arg0 = mp_binary_op(op, arg0, arg1);
|
#endif
|
||||||
|
if (!binary_op_maybe(op, arg0, arg1, &arg0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (rule_id == RULE_shift_expr
|
} else if (rule_id == RULE_shift_expr
|
||||||
|| rule_id == RULE_arith_expr
|
|| rule_id == RULE_arith_expr
|
||||||
|| rule_id == RULE_term) {
|
|| rule_id == RULE_term) {
|
||||||
// folding for binary ops: << >> + - * @ / % //
|
// folding for binary ops: << >> + - * @ / % //
|
||||||
mp_parse_node_t pn = peek_result(parser, num_args - 1);
|
mp_parse_node_t pn = peek_result(parser, num_args - 1);
|
||||||
if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
|
if (!mp_parse_node_get_number_maybe(pn, &arg0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (ssize_t i = num_args - 2; i >= 1; i -= 2) {
|
for (ssize_t i = num_args - 2; i >= 1; i -= 2) {
|
||||||
pn = peek_result(parser, i - 1);
|
pn = peek_result(parser, i - 1);
|
||||||
mp_obj_t arg1;
|
mp_obj_t arg1;
|
||||||
if (!mp_parse_node_get_int_maybe(pn, &arg1)) {
|
if (!mp_parse_node_get_number_maybe(pn, &arg1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, i));
|
mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, i));
|
||||||
if (tok == MP_TOKEN_OP_AT || tok == MP_TOKEN_OP_SLASH) {
|
if (tok == MP_TOKEN_OP_AT) {
|
||||||
// Can't fold @ or /
|
// Can't fold @
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mp_binary_op_t op = MP_BINARY_OP_LSHIFT + (tok - MP_TOKEN_OP_DBL_LESS);
|
#if !MICROPY_COMP_CONST_FLOAT
|
||||||
int rhs_sign = mp_obj_int_sign(arg1);
|
if (tok == MP_TOKEN_OP_SLASH) {
|
||||||
if (op <= MP_BINARY_OP_RSHIFT) {
|
// Can't fold /
|
||||||
// << and >> can't have negative rhs
|
return false;
|
||||||
if (rhs_sign < 0) {
|
}
|
||||||
return false;
|
#endif
|
||||||
}
|
mp_binary_op_t op = MP_BINARY_OP_LSHIFT + (tok - MP_TOKEN_OP_DBL_LESS);
|
||||||
} else if (op >= MP_BINARY_OP_FLOOR_DIVIDE) {
|
if (!binary_op_maybe(op, arg0, arg1, &arg0)) {
|
||||||
// % and // can't have zero rhs
|
return false;
|
||||||
if (rhs_sign == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
arg0 = mp_binary_op(op, arg0, arg1);
|
|
||||||
}
|
}
|
||||||
} else if (rule_id == RULE_factor_2) {
|
} else if (rule_id == RULE_factor_2) {
|
||||||
// folding for unary ops: + - ~
|
// folding for unary ops: + - ~
|
||||||
mp_parse_node_t pn = peek_result(parser, 0);
|
mp_parse_node_t pn = peek_result(parser, 0);
|
||||||
if (!mp_parse_node_get_int_maybe(pn, &arg0)) {
|
if (!mp_parse_node_get_number_maybe(pn, &arg0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, 1));
|
mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, 1));
|
||||||
mp_unary_op_t op;
|
mp_unary_op_t op;
|
||||||
if (tok == MP_TOKEN_OP_TILDE) {
|
if (tok == MP_TOKEN_OP_TILDE) {
|
||||||
|
if (!mp_obj_is_int(arg0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
op = MP_UNARY_OP_INVERT;
|
op = MP_UNARY_OP_INVERT;
|
||||||
} else {
|
} else {
|
||||||
assert(tok == MP_TOKEN_OP_PLUS || tok == MP_TOKEN_OP_MINUS); // should be
|
assert(tok == MP_TOKEN_OP_PLUS || tok == MP_TOKEN_OP_MINUS); // should be
|
||||||
@@ -855,7 +894,7 @@ static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// id1.id2
|
// id1.id2
|
||||||
// look it up in constant table, see if it can be replaced with an integer
|
// look it up in constant table, see if it can be replaced with an integer or a float
|
||||||
mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pn1;
|
mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pn1;
|
||||||
assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
|
assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
|
||||||
qstr q_base = MP_PARSE_NODE_LEAF_ARG(pn0);
|
qstr q_base = MP_PARSE_NODE_LEAF_ARG(pn0);
|
||||||
@@ -866,7 +905,7 @@ static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) {
|
|||||||
}
|
}
|
||||||
mp_obj_t dest[2];
|
mp_obj_t dest[2];
|
||||||
mp_load_method_maybe(elem->value, q_attr, dest);
|
mp_load_method_maybe(elem->value, q_attr, dest);
|
||||||
if (!(dest[0] != MP_OBJ_NULL && mp_obj_is_int(dest[0]) && dest[1] == MP_OBJ_NULL)) {
|
if (!(dest[0] != MP_OBJ_NULL && (mp_obj_is_int(dest[0]) || mp_obj_is_float(dest[0])) && dest[1] == MP_OBJ_NULL)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
arg0 = dest[0];
|
arg0 = dest[0];
|
||||||
|
|||||||
@@ -19,3 +19,9 @@ print("%.14e" % float("." + "0" * 400 + "9e400"))
|
|||||||
print(float("1.00000000000000000000e-307"))
|
print(float("1.00000000000000000000e-307"))
|
||||||
print(float("10.0000000000000000000e-308"))
|
print(float("10.0000000000000000000e-308"))
|
||||||
print(float("100.000000000000000000e-309"))
|
print(float("100.000000000000000000e-309"))
|
||||||
|
|
||||||
|
# ensure repr() adds an extra digit when needed for accurate parsing
|
||||||
|
print(float(repr(float("2.0") ** 100)) == float("2.0") ** 100)
|
||||||
|
|
||||||
|
# ensure repr does not add meaningless extra digits (1.234999999999)
|
||||||
|
print(repr(1.2345))
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ test_syntax("A = const(1); A = const(2)")
|
|||||||
|
|
||||||
# these operations are not supported within const
|
# these operations are not supported within const
|
||||||
test_syntax("A = const(1 @ 2)")
|
test_syntax("A = const(1 @ 2)")
|
||||||
test_syntax("A = const(1 / 2)")
|
|
||||||
test_syntax("A = const(1 ** -2)")
|
|
||||||
test_syntax("A = const(1 << -2)")
|
test_syntax("A = const(1 << -2)")
|
||||||
test_syntax("A = const(1 >> -2)")
|
test_syntax("A = const(1 >> -2)")
|
||||||
test_syntax("A = const(1 % 0)")
|
test_syntax("A = const(1 % 0)")
|
||||||
|
|||||||
@@ -5,5 +5,3 @@ SyntaxError
|
|||||||
SyntaxError
|
SyntaxError
|
||||||
SyntaxError
|
SyntaxError
|
||||||
SyntaxError
|
SyntaxError
|
||||||
SyntaxError
|
|
||||||
SyntaxError
|
|
||||||
|
|||||||
23
tests/micropython/const_float.py
Normal file
23
tests/micropython/const_float.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# test constant optimisation, with consts that are floats
|
||||||
|
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
# check we can make consts from floats
|
||||||
|
F1 = const(2.5)
|
||||||
|
F2 = const(-0.3)
|
||||||
|
print(type(F1), F1)
|
||||||
|
print(type(F2), F2)
|
||||||
|
|
||||||
|
# check arithmetic with floats
|
||||||
|
F3 = const(F1 + F2)
|
||||||
|
F4 = const(F1**2)
|
||||||
|
print(F3, F4)
|
||||||
|
|
||||||
|
# check int operations with float results
|
||||||
|
F5 = const(1 / 2)
|
||||||
|
F6 = const(2**-2)
|
||||||
|
print(F5, F6)
|
||||||
|
|
||||||
|
# note: we also test float expression folding when
|
||||||
|
# we're compiling test cases in tests/float, as
|
||||||
|
# many expressions are resolved at compile time.
|
||||||
4
tests/micropython/const_float.py.exp
Normal file
4
tests/micropython/const_float.py.exp
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<class 'float'> 2.5
|
||||||
|
<class 'float'> -0.3
|
||||||
|
2.2 6.25
|
||||||
|
0.5 0.25
|
||||||
18
tests/micropython/const_math.py
Normal file
18
tests/micropython/const_math.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Test expressions based on math module constants
|
||||||
|
try:
|
||||||
|
import math
|
||||||
|
except ImportError:
|
||||||
|
print("SKIP")
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
# check that we can make consts from math constants
|
||||||
|
# (skip if the target has MICROPY_COMP_MODULE_CONST disabled)
|
||||||
|
try:
|
||||||
|
exec("two_pi = const(2.0 * math.pi)")
|
||||||
|
except SyntaxError:
|
||||||
|
print("SKIP")
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
|
print(math.cos(two_pi))
|
||||||
1
tests/micropython/const_math.py.exp
Normal file
1
tests/micropython/const_math.py.exp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1.0
|
||||||
Reference in New Issue
Block a user