mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[1.15.5] Updated Epsilon
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++
|
||||
|
||||
@@ -10,7 +10,6 @@ _IonEventsEmscriptenKeyUp \
|
||||
_IonEventsEmscriptenPushEvent \
|
||||
_IonSimulatorCallbackDidScanKeyboard \
|
||||
__Z8ion_mainiPKPKc \
|
||||
__Z8ion_mainiPPc \
|
||||
__ZN10Invocation7performEPv \
|
||||
__ZN11MicroPython20ExecutionEnvironment7runCodeEPKc \
|
||||
__ZN13AppsContainer13dispatchEventEN3Ion6Events5EventE \
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "events.h"
|
||||
|
||||
#include <ion/events.h>
|
||||
#include <layout_events.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
@@ -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" {
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user