diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index c6e16365e..ca2a372bc 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -189,8 +189,24 @@ T Sequence::approximateToNextRank(int n, SequenceContext * sqctx) const { } Expression Sequence::sumBetweenBounds(double start, double end, Poincare::Context * context) const { - assert(std::round(start) == start && std::round(end) == end); - return Poincare::Sum::Builder(expressionReduced(context).clone(), Poincare::Symbol::Builder(UCodePointUnknownX), Poincare::Float::Builder(start), Poincare::Float::Builder(end)); // Sum takes ownership of args + /* Here, we cannot just create the expression sum(u(n), start, end) because + * the approximation of u(n) is not handled by Poincare (but only by + * Sequence). */ + double result = 0.0; + if (end-start > ExpressionNode::k_maxNumberOfSteps || start + 1.0 == start) { + return Float::Builder(NAN); + } + start = std::round(start); + end = std::round(end); + for (double i = start; i <= end; i = i + 1.0) { + /* When |start| >> 1.0, start + 1.0 = start. In that case, quit the + * infinite loop. */ + if (i == i-1.0 || i == i+1.0) { + return Float::Builder(NAN); + } + result += evaluateXYAtParameter(i, context).x2(); + } + return Float::Builder(result); } Sequence::RecordDataBuffer * Sequence::recordData() const { diff --git a/apps/sequence/test/sequence.cpp b/apps/sequence/test/sequence.cpp index be31c5681..02aaddec9 100644 --- a/apps/sequence/test/sequence.cpp +++ b/apps/sequence/test/sequence.cpp @@ -5,8 +5,10 @@ #include #include "../sequence_store.h" #include "../sequence_context.h" +#include "../../shared/poincare_helpers.h" using namespace Poincare; +using namespace Shared; namespace Sequence { @@ -48,6 +50,19 @@ void check_sequences_defined_by(double result[MaxNumberOfSequences][10], Sequenc store.removeAll(); } +void check_sum_of_sequence_between_bounds(double result, double start, double end, Sequence::Type type, const char * definition, const char * condition1, const char * condition2) { + Shared::GlobalContext globalContext; + SequenceStore store; + SequenceContext sequenceContext(&globalContext, &store); + + Sequence * seq = addSequence(&store, type, definition, condition1, condition2); + + double sum = PoincareHelpers::ApproximateToScalar(seq->sumBetweenBounds(start, end, &sequenceContext), &globalContext); + quiz_assert(std::fabs(sum - result) < 0.00000001); + + store.removeAll(); +} + QUIZ_CASE(sequence_evaluation) { Sequence::Type types[MaxNumberOfSequences] = {Sequence::Type::Explicit, Sequence::Type::Explicit, Sequence::Type::Explicit}; const char * definitions[MaxNumberOfSequences] = {nullptr, nullptr, nullptr}; @@ -323,4 +338,10 @@ QUIZ_CASE(sequence_evaluation) { check_sequences_defined_by(results28, types, definitions, conditions1, conditions2); } +QUIZ_CASE(sequence_sum_evaluation) { + check_sum_of_sequence_between_bounds(33.0, 3.0, 8.0, Sequence::Type::Explicit, "n", nullptr, nullptr); + check_sum_of_sequence_between_bounds(70.0, 2.0, 8.0, Sequence::Type::SingleRecurrence, "u(n)+2", "0", nullptr); + check_sum_of_sequence_between_bounds(92.0, 2.0, 7.0, Sequence::Type::DoubleRecurrence, "u(n)+u(n+1)+2", "0", "0"); +} + } diff --git a/ion/src/simulator/web/simulator.html b/ion/src/simulator/web/simulator.html index d733dac5e..393edf3a5 100644 --- a/ion/src/simulator/web/simulator.html +++ b/ion/src/simulator/web/simulator.html @@ -290,13 +290,6 @@ document.getElementById("action-fullscreen").addEventListener("click", function( document.getElementById("action-screenshot").addEventListener("click", function(e) { screenshot(); }); - -window.addEventListener("keydown", function(e) { - // space and arrow keys - if([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) { - e.preventDefault(); - } -}, false); diff --git a/poincare/src/tree_pool.cpp b/poincare/src/tree_pool.cpp index 9769f299a..66b385fa4 100644 --- a/poincare/src/tree_pool.cpp +++ b/poincare/src/tree_pool.cpp @@ -11,7 +11,7 @@ namespace Poincare { -TreePool * TreePool::SharedStaticPool; +TreePool * TreePool::SharedStaticPool = nullptr; void TreePool::freeIdentifier(int identifier) { if (identifier >= 0 && identifier < MaxNumberOfNodes) { diff --git a/python/Makefile b/python/Makefile index f2afa3b24..dc917fab1 100644 --- a/python/Makefile +++ b/python/Makefile @@ -130,12 +130,14 @@ port_src += $(addprefix python/port/,\ port.c \ builtins.c \ helpers.c \ + mod/ion/modion.cpp \ + mod/ion/modion_table.cpp \ mod/kandinsky/modkandinsky.cpp \ - mod/kandinsky/modkandinsky_table.cpp \ + mod/kandinsky/modkandinsky_table.c \ mod/time/modtime.c \ mod/time/modtime_table.c \ mod/turtle/modturtle.cpp \ - mod/turtle/modturtle_table.cpp \ + mod/turtle/modturtle_table.c \ mod/turtle/turtle.cpp \ mphalport.c \ ) diff --git a/python/port/genhdr/qstrdefs.in.h b/python/port/genhdr/qstrdefs.in.h index 769a6df66..58c36bc71 100644 --- a/python/port/genhdr/qstrdefs.in.h +++ b/python/port/genhdr/qstrdefs.in.h @@ -15,6 +15,56 @@ QCFG(BYTES_IN_LEN, (1)) QCFG(BYTES_IN_HASH, (2)) +// Ion QSTR +Q(ion) +Q(keydown) +Q(KEY_LEFT) +Q(KEY_UP) +Q(KEY_DOWN) +Q(KEY_RIGHT) +Q(KEY_OK) +Q(KEY_BACK) +Q(KEY_HOME) +Q(KEY_ONOFF) +Q(KEY_SHIFT) +Q(KEY_ALPHA) +Q(KEY_XNT) +Q(KEY_VAR) +Q(KEY_TOOLBOX) +Q(KEY_BACKSPACE) +Q(KEY_EXP) +Q(KEY_LN) +Q(KEY_LOG) +Q(KEY_IMAGINARY) +Q(KEY_COMMA) +Q(KEY_POWER) +Q(KEY_SINE) +Q(KEY_COSINE) +Q(KEY_TANGENT) +Q(KEY_PI) +Q(KEY_SQRT) +Q(KEY_SQUARE) +Q(KEY_SEVEN) +Q(KEY_EIGHT) +Q(KEY_NINE) +Q(KEY_LEFTPARENTHESIS) +Q(KEY_RIGHTPARENTHESIS) +Q(KEY_FOUR) +Q(KEY_FIVE) +Q(KEY_SIX) +Q(KEY_MULTIPLICATION) +Q(KEY_DIVISION) +Q(KEY_ONE) +Q(KEY_TWO) +Q(KEY_THREE) +Q(KEY_PLUS) +Q(KEY_MINUS) +Q(KEY_ZERO) +Q(KEY_DOT) +Q(KEY_EE) +Q(KEY_ANS) +Q(KEY_EXE) + // Kandinsky QSTRs Q(kandinsky) Q(color) diff --git a/python/port/mod/ion/modion.cpp b/python/port/mod/ion/modion.cpp new file mode 100644 index 000000000..69118a103 --- /dev/null +++ b/python/port/mod/ion/modion.cpp @@ -0,0 +1,13 @@ +extern "C" { +#include "modion.h" +#include +#include +} +#include +#include "port.h" + +mp_obj_t modion_keyboard_keydown(mp_obj_t key_o) { + Ion::Keyboard::Key key = static_cast(mp_obj_get_int(key_o)); + Ion::Keyboard::State state = Ion::Keyboard::scan(); + return mp_obj_new_bool(state.keyDown(key)); +} diff --git a/python/port/mod/ion/modion.h b/python/port/mod/ion/modion.h new file mode 100644 index 000000000..d8ffe219b --- /dev/null +++ b/python/port/mod/ion/modion.h @@ -0,0 +1,3 @@ +#include + +mp_obj_t modion_keyboard_keydown(mp_obj_t key_o); diff --git a/python/port/mod/ion/modion_table.cpp b/python/port/mod/ion/modion_table.cpp new file mode 100644 index 000000000..235c2c3ae --- /dev/null +++ b/python/port/mod/ion/modion_table.cpp @@ -0,0 +1,77 @@ +extern "C" { +#include "modion.h" +} + +#include + +/* We cannot use C99-style struct initizalition in C++. As a result, we cannot + * use the macros that micropython recommends, and we have to hand build those + * structs. To avoid errors, we drop in a few static_asserts. */ + +static_assert(sizeof(mp_fun_1_t) == sizeof(mp_fun_0_t)); +static_assert(sizeof(mp_obj_fun_builtin_fixed_t) == sizeof(mp_obj_base_t) + sizeof(mp_fun_1_t)); + +const mp_obj_fun_builtin_fixed_t modion_keyboard_keydown_obj = { + {&mp_type_fun_builtin_1}, + (mp_fun_0_t)modion_keyboard_keydown +}; + +STATIC const mp_rom_map_elem_t modion_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ion) }, + { MP_ROM_QSTR(MP_QSTR_keydown), MP_ROM_PTR(&modion_keyboard_keydown_obj) }, + { MP_ROM_QSTR(MP_QSTR_KEY_LEFT), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Left) }, + { MP_ROM_QSTR(MP_QSTR_KEY_UP), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Up) }, + { MP_ROM_QSTR(MP_QSTR_KEY_DOWN), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Down) }, + { MP_ROM_QSTR(MP_QSTR_KEY_RIGHT), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Right) }, + { MP_ROM_QSTR(MP_QSTR_KEY_OK), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::OK) }, + { MP_ROM_QSTR(MP_QSTR_KEY_BACK), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Back) }, + { MP_ROM_QSTR(MP_QSTR_KEY_HOME), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Home) }, + { MP_ROM_QSTR(MP_QSTR_KEY_ONOFF), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::OnOff) }, + { MP_ROM_QSTR(MP_QSTR_KEY_SHIFT), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Shift) }, + { MP_ROM_QSTR(MP_QSTR_KEY_ALPHA), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Alpha) }, + { MP_ROM_QSTR(MP_QSTR_KEY_XNT), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::XNT) }, + { MP_ROM_QSTR(MP_QSTR_KEY_VAR), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Var) }, + { MP_ROM_QSTR(MP_QSTR_KEY_TOOLBOX), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Toolbox) }, + { MP_ROM_QSTR(MP_QSTR_KEY_BACKSPACE), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Backspace) }, + { MP_ROM_QSTR(MP_QSTR_KEY_EXP), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Exp) }, + { MP_ROM_QSTR(MP_QSTR_KEY_LN), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Ln) }, + { MP_ROM_QSTR(MP_QSTR_KEY_LOG), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Log) }, + { MP_ROM_QSTR(MP_QSTR_KEY_IMAGINARY), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Imaginary) }, + { MP_ROM_QSTR(MP_QSTR_KEY_COMMA), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Comma) }, + { MP_ROM_QSTR(MP_QSTR_KEY_POWER), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Power) }, + { MP_ROM_QSTR(MP_QSTR_KEY_SINE), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Sine) }, + { MP_ROM_QSTR(MP_QSTR_KEY_COSINE), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Cosine) }, + { MP_ROM_QSTR(MP_QSTR_KEY_TANGENT), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Tangent) }, + { MP_ROM_QSTR(MP_QSTR_KEY_PI), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Pi) }, + { MP_ROM_QSTR(MP_QSTR_KEY_SQRT), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Sqrt) }, + { MP_ROM_QSTR(MP_QSTR_KEY_SQUARE), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Square) }, + { MP_ROM_QSTR(MP_QSTR_KEY_SEVEN), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Seven) }, + { MP_ROM_QSTR(MP_QSTR_KEY_EIGHT), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Eight) }, + { MP_ROM_QSTR(MP_QSTR_KEY_NINE), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Nine) }, + { MP_ROM_QSTR(MP_QSTR_KEY_LEFTPARENTHESIS), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::LeftParenthesis) }, + { MP_ROM_QSTR(MP_QSTR_KEY_RIGHTPARENTHESIS), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::RightParenthesis) }, + { MP_ROM_QSTR(MP_QSTR_KEY_FOUR), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Four) }, + { MP_ROM_QSTR(MP_QSTR_KEY_FIVE), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Five) }, + { MP_ROM_QSTR(MP_QSTR_KEY_SIX), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Six) }, + { MP_ROM_QSTR(MP_QSTR_KEY_MULTIPLICATION), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Multiplication) }, + { MP_ROM_QSTR(MP_QSTR_KEY_DIVISION), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Division) }, + { MP_ROM_QSTR(MP_QSTR_KEY_ONE), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::One) }, + { MP_ROM_QSTR(MP_QSTR_KEY_TWO), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Two) }, + { MP_ROM_QSTR(MP_QSTR_KEY_THREE), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Three) }, + { MP_ROM_QSTR(MP_QSTR_KEY_PLUS), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Plus) }, + { MP_ROM_QSTR(MP_QSTR_KEY_MINUS), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Minus) }, + { MP_ROM_QSTR(MP_QSTR_KEY_ZERO), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Zero) }, + { MP_ROM_QSTR(MP_QSTR_KEY_DOT), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Dot) }, + { MP_ROM_QSTR(MP_QSTR_KEY_EE), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::EE) }, + { MP_ROM_QSTR(MP_QSTR_KEY_ANS), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Ans) }, + { MP_ROM_QSTR(MP_QSTR_KEY_EXE), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::EXE) }, +}; + +STATIC MP_DEFINE_CONST_DICT(modion_module_globals, modion_module_globals_table); + +static_assert(sizeof(mp_obj_module_t) == sizeof(mp_obj_base_t) + sizeof(mp_obj_dict_t *)); + +extern "C" const mp_obj_module_t modion_module = { + { &mp_type_module }, + (mp_obj_dict_t*)&modion_module_globals, +}; diff --git a/python/port/mpconfigport.h b/python/port/mpconfigport.h index dae99b6f2..77348f656 100644 --- a/python/port/mpconfigport.h +++ b/python/port/mpconfigport.h @@ -112,11 +112,13 @@ typedef long mp_off_t; #define MP_STATE_PORT MP_STATE_VM +extern const struct _mp_obj_module_t modion_module; extern const struct _mp_obj_module_t modkandinsky_module; extern const struct _mp_obj_module_t modtime_module; extern const struct _mp_obj_module_t modturtle_module; #define MICROPY_PORT_BUILTIN_MODULES \ + { MP_ROM_QSTR(MP_QSTR_ion), MP_ROM_PTR(&modion_module) }, \ { MP_ROM_QSTR(MP_QSTR_kandinsky), MP_ROM_PTR(&modkandinsky_module) }, \ { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&modtime_module) }, \ { MP_ROM_QSTR(MP_QSTR_turtle), MP_ROM_PTR(&modturtle_module) }, \