[1.15.5] Updated Epsilon

This commit is contained in:
Quentin Guidée
2019-11-15 18:04:13 +01:00
13 changed files with 77 additions and 25 deletions

View File

@@ -237,10 +237,10 @@ int ValuesController::numberOfValuesColumns() {
ContinuousFunction::PlotType ValuesController::plotTypeAtColumn(int * i) const {
int plotTypeIndex = 0;
while (plotTypeIndex < ContinuousFunction::k_numberOfPlotTypes && *i >= numberOfColumnsForPlotType(plotTypeIndex)) {
while (*i >= numberOfColumnsForPlotType(plotTypeIndex)) {
*i -= numberOfColumnsForPlotType(plotTypeIndex++);
assert(plotTypeIndex < ContinuousFunction::k_numberOfPlotTypes);
}
assert(plotTypeIndex < ContinuousFunction::k_numberOfPlotTypes);
return static_cast<ContinuousFunction::PlotType>(plotTypeIndex);
}
@@ -255,9 +255,10 @@ int ValuesController::absoluteColumnForValuesColumn(int column) {
int valuesColumns = 0;
int plotTypeIndex = 0;
do {
abscissaColumns++;
assert(plotTypeIndex < Shared::ContinuousFunction::k_numberOfPlotTypes);
valuesColumns += m_numberOfValuesColumnsForType[plotTypeIndex++];
const int numberOfValuesColumnsForType = m_numberOfValuesColumnsForType[plotTypeIndex++];
valuesColumns += numberOfValuesColumnsForType;
abscissaColumns += (numberOfValuesColumnsForType > 0);
} while (valuesColumns <= column);
return column + abscissaColumns;
}

View File

@@ -237,14 +237,13 @@ void ValuesController::didChangeCell(int column, int row) {
// the first row is never reloaded as it corresponds to title row
assert(row > 0);
// Conversion of coordinates from absolute table to values table
int valuesRow = valuesRowForAbsoluteRow(row);
if (m_firstMemoizedRow > valuesRow || valuesRow >= m_firstMemoizedRow + k_maxNumberOfDisplayableRows) {
int memoizedRow = valuesRowForAbsoluteRow(row) - m_firstMemoizedRow;
if (0 > memoizedRow || memoizedRow >= k_maxNumberOfDisplayableRows) {
// The changed row is out of the memoized table
return;
}
// Update the memoization of rows linked to the changed cell
int memoizedRow = valuesRow - m_firstMemoizedRow;
int nbOfMemoizedColumns = numberOfMemoizedColumn();
for (int i = column+1; i < column+numberOfColumnsForAbscissaColumn(column); i++) {
int memoizedI = valuesColumnForAbsoluteColumn(i) - m_firstMemoizedColumn;
@@ -291,10 +290,10 @@ void ValuesController::resetMemoization() {
}
char * ValuesController::memoizedBufferForCell(int i, int j) {
const int nbOfMemoizedColumns = numberOfMemoizedColumn();
// Conversion of coordinates from absolute table to values table
int valuesI = valuesColumnForAbsoluteColumn(i);
int valuesJ = valuesRowForAbsoluteRow(j);
int nbOfMemoizedColumns = numberOfMemoizedColumn();
/* Compute the required offset to apply to the memoized table in order to
* display cell (i,j) */
int offsetI = 0;
@@ -316,7 +315,7 @@ char * ValuesController::memoizedBufferForCell(int i, int j) {
m_firstMemoizedColumn = m_firstMemoizedColumn + offsetI;
m_firstMemoizedRow = m_firstMemoizedRow + offsetJ;
// Shift already memoized cells
int numberOfMemoizedCell = k_maxNumberOfDisplayableRows*numberOfMemoizedColumn();
const int numberOfMemoizedCell = k_maxNumberOfDisplayableRows * nbOfMemoizedColumns;
size_t moveLength = (numberOfMemoizedCell - absInt(offset))*valuesCellBufferSize()*sizeof(char);
if (offset > 0 && offset < numberOfMemoizedCell) {
memmove(memoizedBufferAtIndex(offset), memoizedBufferAtIndex(0), moveLength);

View File

@@ -9,20 +9,26 @@ endif
NDK_TOOLCHAIN_PATH = $(NDK_PATH)/toolchains/llvm/prebuilt/$(NDK_HOST_TAG)/bin
# No 64 bit device has ever shipped with an API level < 21. Consequently, there
# is no toolchain for those archs on those API levels. Let's enforce NDK_VERSION
# at 21 for these archs, and 16 for the others.
ifeq ($(NDK_ABI),armeabi-v7a)
NDK_TARGET = armv7a-linux-androideabi
NDK_VERSION = 16
else ifeq ($(NDK_ABI),arm64-v8a)
NDK_TARGET = aarch64-linux-android
NDK_VERSION = 21
else ifeq ($(NDK_ABI),x86)
NDK_TARGET = i686-linux-android
NDK_VERSION = 16
else ifeq ($(NDK_ABI),x86_64)
NDK_TARGET = x86_64-linux-android
NDK_VERSION = 21
endif
ifdef NDK_TARGET
NDK_VERSION ?= 21
CC = $(NDK_TOOLCHAIN_PATH)/$(NDK_TARGET)$(NDK_VERSION)-clang
CXX = $(NDK_TOOLCHAIN_PATH)/$(NDK_TARGET)$(NDK_VERSION)-clang++
LD = $(NDK_TOOLCHAIN_PATH)/$(NDK_TARGET)$(NDK_VERSION)-clang++

View File

@@ -10,7 +10,6 @@ _IonEventsEmscriptenKeyUp \
_IonEventsEmscriptenPushEvent \
_IonSimulatorCallbackDidScanKeyboard \
__Z8ion_mainiPKPKc \
__Z8ion_mainiPPc \
__ZN10Invocation7performEPv \
__ZN11MicroPython20ExecutionEnvironment7runCodeEPKc \
__ZN13AppsContainer13dispatchEventEN3Ion6Events5EventE \

View File

@@ -22,11 +22,11 @@ allprojects {
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
compileSdkVersion 29
defaultConfig {
applicationId "com.numworks.calculator"
minSdkVersion 16
targetSdkVersion 26
targetSdkVersion 28
def (major, minor, patch) = System.getenv('EPSILON_VERSION').toLowerCase().tokenize('.').collect{it.toInteger()}
versionCode major*1000000 + minor*10000 + patch * 100
versionName System.getenv('EPSILON_VERSION')

View File

@@ -4,6 +4,8 @@
#include "events.h"
#include <ion/events.h>
#include <layout_events.h>
#include <string.h>
#include <stdio.h>

View File

@@ -14,7 +14,11 @@
#endif
constexpr int kHeapSize = 131072;
#if DEBUG
constexpr int kStackSize = 32768*2; // In DEBUG mode, we increase the stack to be able to pass the tests
#else
constexpr int kStackSize = 32768;
#endif
char heap[kHeapSize];
extern "C" {

View File

@@ -34,7 +34,7 @@ public:
/* Simplification */
Expression shallowReduce(ReductionContext reductionContext) override;
Expression shallowReplaceReplaceableSymbols(Context * context) override;
LayoutShape leftLayoutShape() const override { return strlen(m_name) > 1 ? LayoutShape::MoreLetters : LayoutShape::OneLetter; };
LayoutShape leftLayoutShape() const override;
/* Approximation */
Evaluation<float> approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate<float>(context, complexFormat, angleUnit); }

View File

@@ -16,15 +16,41 @@ namespace Poincare {
static inline int maxInt(int x, int y) { return x > y ? x : y; }
void removeZeroAtTheEnd(Integer * i, int minimalNumbersOfDigits = 1) {
void removeZeroAtTheEnd(Integer * i, int minimalNumbersOfDigits = -1) {
/* Remove the zeroes at the end of an integer, respecting the minimum number
* of digits asked for.
*
* For instance :
*
* i = 1000
* removeZeroAtTheEnd(&i, 2)
* assert(i==10)
*
* i = 1000
* removeZeroAtTheEnd(&i, -1)
* assert(i==1)
*/
if (i->isZero()) {
return;
}
/* If we check the number of digits, we want *i to stay outside of the
* interval ]-10^numberDigits; 10^numberDigits[. */
const bool shouldCheckMinimalNumberOfDigits = minimalNumbersOfDigits > 0;
Integer minimum = shouldCheckMinimalNumberOfDigits ?
Integer((int64_t)std::pow(10.0, minimalNumbersOfDigits-1)) :
Integer::Overflow(false);
Integer minusMinimum = shouldCheckMinimalNumberOfDigits ?
Integer(-(int64_t)std::pow(10.0, minimalNumbersOfDigits-1)) :
Integer::Overflow(false);
Integer base = Integer(10);
Integer minimum = Integer((int64_t)std::pow(10.0, minimalNumbersOfDigits-1));
Integer minusMinimum = Integer(-(int64_t)std::pow(10.0, minimalNumbersOfDigits-1));
IntegerDivision d = Integer::Division(*i, base);
while (d.remainder.isZero() && (Integer::NaturalOrder(*i, minimum) > 0 || Integer::NaturalOrder(*i, minusMinimum) < 0)) {
while (d.remainder.isZero()) {
if (shouldCheckMinimalNumberOfDigits && (Integer::NaturalOrder(d.quotient, minimum) < 0 && Integer::NaturalOrder(d.quotient, minusMinimum) > 0)) {
break;
}
*i = d.quotient;
d = Integer::Division(*i, base);
}
@@ -136,7 +162,7 @@ int DecimalNode::convertToText(char * buffer, int bufferSize, Preferences::Print
}
}
int exponentForEngineeringNotation = 0;
int minimalNumberOfMantissaDigits = 1;
int minimalNumberOfMantissaDigits = -1;
bool removeZeroes = true;
if (mode == Preferences::PrintFloatMode::Engineering) {
exponentForEngineeringNotation = PrintFloat::EngineeringExponentFromBase10Exponent(exponent);

View File

@@ -625,18 +625,22 @@ Expression Power::shallowReduce(ExpressionNode::ReductionContext reductionContex
* --> tan(2)+tan(2)*[tan(2)^1/2]^(-1)/tan(2)
* --> tan(2)^(3/2)+tan(2)^(3/2)*[tan(2)^1/2]^(-1)/tan(2)^3/2
* --> ...
* Indeed, we have to apply the rule (a^b)^c -> a^(b*c) as soon as c is an
* integer.
* Indeed, we have to apply the rule (a^b)^c -> a^(b*c) as soon as c is -1.
*/
if (baseType == ExpressionNode::Type::Power) {
Power powerBase = static_cast<Power &>(base);
bool cInteger = indexType == ExpressionNode::Type::Rational && static_cast<Rational &>(index).isInteger();
bool applyRule = powerBase.childAtIndex(0).sign(reductionContext.context()) == ExpressionNode::Sign::Positive // a > 0
|| (indexType == ExpressionNode::Type::Rational && static_cast<Rational &>(index).isInteger()); // c integer
|| cInteger; // c integer
bool cMinusOne = cInteger && static_cast<Rational &>(index).isMinusOne();
/* If the complexFormat is real, we check that the inner power is defined
* before applying the rule (a^b)^c -> a^(b*c). Otherwise, we return
* 'unreal' or we do nothing. */
if (reductionContext.complexFormat() == Preferences::ComplexFormat::Real) {
* 'unreal' or we do nothing.
* We escape this additional check if c = -1 for two reasons:
* - (a^b)^(-1) has to be reduced to avoid infinite loop discussed above;
* - if a^b is unreal, a^(-b) also. */
if (!cMinusOne && reductionContext.complexFormat() == Preferences::ComplexFormat::Real) {
Expression approximation = powerBase.approximate<float>(reductionContext.context(), reductionContext.complexFormat(), reductionContext.angleUnit());
if (approximation.type() == ExpressionNode::Type::Unreal) {
// The inner power is unreal, return "unreal"

View File

@@ -107,6 +107,15 @@ Expression SymbolNode::shallowReplaceReplaceableSymbols(Context * context) {
return Symbol(this).shallowReplaceReplaceableSymbols(context);
}
ExpressionNode::LayoutShape SymbolNode::leftLayoutShape() const {
UTF8Decoder decoder(m_name);
decoder.nextCodePoint();
if (decoder.nextCodePoint() == UCodePointNull) { // nextCodePoint asserts that the first character is non-null
return LayoutShape::OneLetter;
}
return LayoutShape::MoreLetters;
}
template<typename T>
Evaluation<T> SymbolNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
Symbol s(this);

View File

@@ -81,6 +81,7 @@ QUIZ_CASE(poincare_serialization_decimal) {
assert_expression_serialize_to(d10, "1.235ᴇ-1", ScientificMode, 4);
assert_expression_serialize_to(d10, "123.5ᴇ-3", EngineeringMode, 4);
assert_expression_serialize_to(Decimal::Builder(0.25), "250ᴇ-3", EngineeringMode);
assert_expression_serialize_to(Decimal::Builder(-1.23456789E30), "-1.23456789ᴇ30", ScientificMode, 14);
assert_expression_serialize_to(Decimal::Builder(1.23456789E30), "1.23456789ᴇ30", ScientificMode, 14);
assert_expression_serialize_to(Decimal::Builder(-1.23456789E-30), "-1.23456789ᴇ-30", ScientificMode, 14);

View File

@@ -107,6 +107,7 @@ QUIZ_CASE(poincare_simplification_infinity) {
}
QUIZ_CASE(poincare_simplification_addition) {
assert_parsed_expression_simplify_to("1/x^2+3", "\u00123×x^2+1\u0013/x^2", User, Radian, Real);
assert_parsed_expression_simplify_to("1+x", "x+1");
assert_parsed_expression_simplify_to("1/2+1/3+1/4+1/5+1/6+1/7", "223/140");
assert_parsed_expression_simplify_to("1+x+4-i-2x", "-i-x+5");