diff --git a/apps/calculation/additional_outputs/integer_list_controller.cpp b/apps/calculation/additional_outputs/integer_list_controller.cpp index 634c24f3a96..45578b6c151 100644 --- a/apps/calculation/additional_outputs/integer_list_controller.cpp +++ b/apps/calculation/additional_outputs/integer_list_controller.cpp @@ -5,6 +5,9 @@ #include #include "../app.h" #include "../../shared/poincare_helpers.h" +#include "poincare/decimal.h" +#include "apps/apps_container.h" +#include "poincare/layout_helper.h" using namespace Poincare; using namespace Shared; @@ -28,9 +31,47 @@ void IntegerListController::setExpression(Poincare::Expression e) { static_assert(k_maxNumberOfRows >= k_indexOfFactorExpression + 1, "k_maxNumberOfRows must be greater than k_indexOfFactorExpression"); assert(!m_expression.isUninitialized() && m_expression.type() == ExpressionNode::Type::BasedInteger); Integer integer = static_cast(m_expression).integer(); - for (int index = 0; index < k_indexOfFactorExpression; ++index) { + for (int index = 0; index < k_indexOfFactorExpression - 1; ++index) { m_layouts[index] = integer.createLayout(baseAtIndex(index)); } + + const int * value = (int *)integer.digits(); + int shift = GlobalPreferences::sharedGlobalPreferences()->getDecimalShift(); + m_exponent = (int)log10(abs(*value)); + + Decimal decimal = Decimal::Builder(integer, m_exponent); + + char buffer[Poincare::DecimalNode::k_maxBufferSize]; + int numberOfChars = decimal.serialize(buffer, Poincare::DecimalNode::k_maxBufferSize, Preferences::PrintFloatMode::Scientific); + + if (*(UTF8Helper::CodePointSearch(buffer, Ion::InternalStorage::k_dotChar)) != 0) { + int originalNumber = numberOfChars; + int maxShift = originalNumber - 3 - (int)log10(abs(m_exponent)) - 1 - 2; + if (shift > maxShift) { + shift = maxShift; + GlobalPreferences::sharedGlobalPreferences()->setDecimalShift(maxShift); + } + decimal = Decimal::Builder(integer, m_exponent-shift); + numberOfChars = decimal.serialize(buffer, Poincare::DecimalNode::k_maxBufferSize, Preferences::PrintFloatMode::Scientific); + + for (int i = 0; i < shift; i++) { + char c = buffer[i+1]; + buffer[i+1] = buffer[i+2]; + buffer[i+2] = c; + } + + if (m_exponent - shift == 0) { + buffer[numberOfChars-1] = '\0'; + } + + if (shift == maxShift && m_exponent - shift != 0) { + strlcpy(&buffer[shift + 1], &buffer[shift + 2], strlen(&buffer[shift + 1])); + } + } + + Layout layout = LayoutHelper::String(buffer, numberOfChars); + + m_layouts[k_indexOfFactorExpression - 1] = layout; // Computing factorExpression Expression factor = Factor::Builder(m_expression.clone()); PoincareHelpers::Simplify(&factor, App::app()->localContext(), ExpressionNode::ReductionTarget::User); @@ -47,9 +88,44 @@ I18n::Message IntegerListController::messageAtIndex(int index) { return I18n::Message::HexadecimalBase; case 2: return I18n::Message::BinaryBase; + case 3: + return I18n::Message::Scientific; default: return I18n::Message::PrimeFactors; } } + bool IntegerListController::handleEvent(Ion::Events::Event event) { + if (m_listController.selectableTableView()->selectedRow() == 3) { + int decimalShift = GlobalPreferences::sharedGlobalPreferences()->getDecimalShift(); + if (event == Ion::Events::Left) { + if (decimalShift > 0 && Preferences::sharedPreferences()->displayMode() != Preferences::PrintFloatMode::Engineering) { + GlobalPreferences::sharedGlobalPreferences()->setDecimalShift(decimalShift - 1); + refreshScientificDisplay(); + } else if (decimalShift > 3 && Preferences::sharedPreferences()->displayMode() == Preferences::PrintFloatMode::Engineering) { + GlobalPreferences::sharedGlobalPreferences()->setDecimalShift(decimalShift - 3); + refreshScientificDisplay(); + } + return true; + } else if (event == Ion::Events::Right) { + if (Preferences::sharedPreferences()->displayMode() == Preferences::PrintFloatMode::Engineering && m_exponent - decimalShift - 3 >= 0) { + GlobalPreferences::sharedGlobalPreferences()->setDecimalShift(decimalShift + 3); + } else if (m_exponent - decimalShift - 1 >= 0) { + GlobalPreferences::sharedGlobalPreferences()->setDecimalShift(decimalShift + 1); + } + refreshScientificDisplay(); + return true; + } + } + return ListController::handleEvent(event); + } + + void IntegerListController::refreshScientificDisplay() { + Expression e = m_expression; + Container::activeApp()->dismissModalViewController(); + setExpression(e); + Container::activeApp()->displayModalViewController(this, 0.f, 0.f, Metric::CommonTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); + m_listController.selectableTableView()->selectCellAtLocation(0, 3); + } + } diff --git a/apps/calculation/additional_outputs/integer_list_controller.h b/apps/calculation/additional_outputs/integer_list_controller.h index e052632f906..e1b6318eaab 100644 --- a/apps/calculation/additional_outputs/integer_list_controller.h +++ b/apps/calculation/additional_outputs/integer_list_controller.h @@ -8,13 +8,17 @@ namespace Calculation { class IntegerListController : public ExpressionsListController { public: IntegerListController(EditExpressionController * editExpressionController) : - ExpressionsListController(editExpressionController) {} + ExpressionsListController(editExpressionController), m_exponent(0) {} void setExpression(Poincare::Expression e) override; + bool handleEvent(Ion::Events::Event event) override; + private: - static constexpr int k_indexOfFactorExpression = 3; + void refreshScientificDisplay(); + static constexpr int k_indexOfFactorExpression = 4; I18n::Message messageAtIndex(int index) override; + int m_exponent; }; } diff --git a/apps/calculation/history_controller.cpp b/apps/calculation/history_controller.cpp index 9a868730973..6fe5710cd45 100644 --- a/apps/calculation/history_controller.cpp +++ b/apps/calculation/history_controller.cpp @@ -76,6 +76,7 @@ bool HistoryController::handleEvent(Ion::Events::Event event) { return true; } if (event == Ion::Events::OK || event == Ion::Events::EXE) { + GlobalPreferences::sharedGlobalPreferences()->setDecimalShift(0); int focusRow = selectedRow(); HistoryViewCell * selectedCell = (HistoryViewCell *)m_selectableTableView.selectedCell(); SubviewType subviewType = selectedSubviewType(); diff --git a/apps/global_preferences.h b/apps/global_preferences.h index bcfa324ea21..41d3ac21782 100644 --- a/apps/global_preferences.h +++ b/apps/global_preferences.h @@ -42,6 +42,8 @@ class GlobalPreferences { void setCursorSaving(bool cursorsave) { m_cursorSaving = cursorsave; } int brightnessLevel() const { return m_brightnessLevel; } void setBrightnessLevel(int brightnessLevel); + int getDecimalShift() const { return m_decimalShift; } + void setDecimalShift(int shift) { m_decimalShift = shift; } const KDFont * font() const { return m_font; } void setFont(const KDFont * font) { m_font = font; } constexpr static int NumberOfBrightnessStates = 15; @@ -60,6 +62,7 @@ class GlobalPreferences { m_syntaxhighlighting(true), m_cursorSaving(true), m_brightnessLevel(Ion::Backlight::MaxBrightness), + m_decimalShift(0), m_font(KDFont::LargeFont) {} I18n::Language m_language; I18n::Country m_country; @@ -74,6 +77,7 @@ class GlobalPreferences { bool m_syntaxhighlighting; bool m_cursorSaving; int m_brightnessLevel; + int m_decimalShift; const KDFont * m_font; }; diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index f1c0db8489c..76844f901ec 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -70,9 +70,9 @@ class DecimalNode final : public NumberNode { // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; -private: // Worst case is -1.2345678901234E-1000 constexpr static int k_maxBufferSize = PrintFloat::k_numberOfStoredSignificantDigits+1+1+1+1+4+1; + private: int convertToText(char * buffer, int bufferSize, Preferences::PrintFloatMode mode, int numberOfSignificantDigits) const; template T templatedApproximate() const; void setNegative(bool negative) { m_negative = negative; } diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 1d27e50c508..0560b38516b 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -160,8 +160,8 @@ class Integer final : public TreeHandle { static Expression CreateEuclideanDivision(const Integer & num, const Integer & denom); constexpr static int k_maxNumberOfDigits = 32; -private: constexpr static int k_maxNumberOfDigitsBase10 = 308; // (2^32)^k_maxNumberOfDigits ~ 1E308 + private: constexpr static int k_maxExtractableInteger = 0x7FFFFFFF; // Constructors