Merge branch 'feature/Gradians' of https://github.com/boricj/epsilon

This commit is contained in:
Léa Saviot
2019-08-22 11:25:25 +02:00
25 changed files with 161 additions and 38 deletions

View File

@@ -16,6 +16,17 @@ using namespace Shared;
namespace Regression {
static double toRadians(Poincare::Preferences::AngleUnit angleUnit) {
switch (Poincare::Preferences::sharedPreferences()->angleUnit()) {
case Poincare::Preferences::AngleUnit::Degree:
return M_PI/180.0;
case Poincare::Preferences::AngleUnit::Gradian:
return M_PI/200.0;
default:
return 1;
}
}
Layout TrigonometricModel::layout() {
if (m_layout.isUninitialized()) {
const char * s = "a·sin(b·X+c)+d";
@@ -29,7 +40,7 @@ double TrigonometricModel::evaluate(double * modelCoefficients, double x) const
double b = modelCoefficients[1];
double c = modelCoefficients[2];
double d = modelCoefficients[3];
double radianX = Poincare::Preferences::sharedPreferences()->angleUnit() == Poincare::Preferences::AngleUnit::Radian ? x : x * M_PI/180.0;
double radianX = x * toRadians(Poincare::Preferences::sharedPreferences()->angleUnit());
return a*sin(b*radianX+c)+d;
}
@@ -37,7 +48,7 @@ double TrigonometricModel::partialDerivate(double * modelCoefficients, int deriv
double a = modelCoefficients[0];
double b = modelCoefficients[1];
double c = modelCoefficients[2];
double radianX = Poincare::Preferences::sharedPreferences()->angleUnit() == Poincare::Preferences::AngleUnit::Radian ? x : x * M_PI/180.0;
double radianX = x * toRadians(Poincare::Preferences::sharedPreferences()->angleUnit());
if (derivateCoefficientIndex == 0) {
// Derivate: sin(b*x+c)
return sin(b*radianX+c);

View File

@@ -11,6 +11,7 @@ ActivateExamMode = "Start Testmodus"
ExamModeActive = "Testmodus: aktiv"
About = "Über"
Degres = "Grad "
Gradians = "Gradians "
Radian = "Bogenmaß "
Decimal = "Dezimal "
Engineering = "Technisch "

View File

@@ -11,6 +11,7 @@ ActivateExamMode = "Activate exam mode"
ExamModeActive = "Exam mode: active"
About = "About"
Degres = "Degrees "
Gradians = "Gradians "
Radian = "Radians "
Decimal = "Decimal "
Scientific = "Scientific "

View File

@@ -11,6 +11,7 @@ ActivateExamMode = "Activar el modo examen"
ExamModeActive = "Modo examen: activo"
About = "Acerca"
Degres = "Grados "
Gradians = "Gradians "
Radian = "Radianes "
Engineering = "Ingeniería "
Decimal = "Decimal "

View File

@@ -11,6 +11,7 @@ ActivateExamMode = "Activer le mode examen"
ExamModeActive = "Mode examen: actif"
About = "À propos"
Degres = "Degrés "
Gradians = "Grades "
Radian = "Radians "
Decimal = "Décimal "
Scientific = "Scientifique "

View File

@@ -11,6 +11,7 @@ ActivateExamMode = "Inicio modo de exame"
ExamModeActive = "Modo de exame : ativo"
About = "Acerca"
Degres = "Graus "
Gradians = "Gradians "
Radian = "Radianos "
Decimal = "Decimal "
Scientific = "Científico "

View File

@@ -3,7 +3,7 @@
namespace Settings {
constexpr SettingsMessageTree s_modelAngleChildren[2] = {SettingsMessageTree(I18n::Message::Degres), SettingsMessageTree(I18n::Message::Radian)};
constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18n::Message::Degres), SettingsMessageTree(I18n::Message::Gradians), SettingsMessageTree(I18n::Message::Radian)};
constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)};
constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::Engineering), SettingsMessageTree(I18n::Message::SignificantFigures)};
constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessageTree(I18n::Message::Real), SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)};
@@ -11,7 +11,7 @@ constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n
constexpr SettingsMessageTree s_modelAboutChildren[3] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)};
constexpr SettingsMessageTree s_modelMenu[] =
{SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 2),
{SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3),
SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4),
SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2),
SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3),

View File

@@ -4,7 +4,7 @@
namespace Settings {
// TODO: factorize most parts of the final models with main_controller_prompt_beta and main_controller_prompt_update
constexpr SettingsMessageTree s_modelAngleChildren[2] = {SettingsMessageTree(I18n::Message::Degres), SettingsMessageTree(I18n::Message::Radian)};
constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18n::Message::Degres), SettingsMessageTree(I18n::Message::Gradians), SettingsMessageTree(I18n::Message::Radian)};
constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)};
constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::Engineering), SettingsMessageTree(I18n::Message::SignificantFigures)};
constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessageTree(I18n::Message::Real), SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)};
@@ -12,7 +12,7 @@ constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n
constexpr SettingsMessageTree s_modelAboutChildren[3] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)};
constexpr SettingsMessageTree s_modelMenu[] =
{SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 2),
{SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3),
SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4),
SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2),
SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3),

View File

@@ -7,7 +7,7 @@ namespace Settings {
namespace Settings {
constexpr SettingsMessageTree s_modelAngleChildren[2] = {SettingsMessageTree(I18n::Message::Degres), SettingsMessageTree(I18n::Message::Radian)};
constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18n::Message::Degres), SettingsMessageTree(I18n::Message::Gradians), SettingsMessageTree(I18n::Message::Radian)};
constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)};
constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::Engineering), SettingsMessageTree(I18n::Message::SignificantFigures)};
constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessageTree(I18n::Message::Real), SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)};
@@ -15,7 +15,7 @@ constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n
constexpr SettingsMessageTree s_modelAboutChildren[3] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)};
constexpr SettingsMessageTree s_modelMenu[] =
{SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 2),
{SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3),
SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4),
SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2),
SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3),

View File

@@ -58,6 +58,11 @@ Layout PreferencesController::layoutForPreferences(I18n::Message message) {
const char * degEx = "90°";
return LayoutHelper::String(degEx, strlen(degEx), k_layoutFont);
}
case I18n::Message::Gradians:
{
const char * degEx = "100 gon";
return LayoutHelper::String(degEx, strlen(degEx), k_layoutFont);
}
case I18n::Message::Radian:
return FractionLayout::Builder(
CodePointLayout::Builder(UCodePointGreekSmallLetterPi, k_layoutFont),

View File

@@ -21,6 +21,7 @@ FillWithFormula = "Mit einer Formel füllen"
ForbiddenValue = "Verbotener Wert"
FunctionColumn = "0(0) Spalte"
FunctionOptions = "Funktionsoptionen"
Gon = "gon"
Goto = "Gehe zu"
GraphTab = "Graph"
HardwareTestLaunch1 = "Sie sind dabei den Hardwaretest zu"

View File

@@ -21,6 +21,7 @@ FillWithFormula = "Fill with a formula"
ForbiddenValue = "Forbidden value"
FunctionColumn = "0(0) column"
FunctionOptions = "Function options"
Gon = "gon"
Goto = "Go to"
GraphTab = "Graph"
HardwareTestLaunch1 = "You are starting the hardware"

View File

@@ -21,6 +21,7 @@ FillWithFormula = "Rellenar con una fórmula"
ForbiddenValue = "Valor prohibido"
FunctionColumn = "Columna 0(0)"
FunctionOptions = "Opciones de la función"
Gon = "gon"
Goto = "Ir a"
GraphTab = "Gráfico"
HardwareTestLaunch1 = "Esta iniciando la prueba de"

View File

@@ -21,6 +21,7 @@ FillWithFormula = "Remplir avec une formule"
ForbiddenValue = "Valeur interdite"
FunctionColumn = "Colonne 0(0)"
FunctionOptions = "Options de la fonction"
Gon = "gon"
Goto = "Aller à"
GraphTab = "Graphique"
HardwareTestLaunch1 = "Vous allez lancer le test usine."

View File

@@ -21,6 +21,7 @@ FillWithFormula = "Preencher com uma fórmula"
ForbiddenValue = "Valor proibida"
FunctionColumn = "Coluna 0(0)"
FunctionOptions = "Opções de função"
Gon = "gon"
Goto = "Ir a"
GraphTab = "Gráfico"
HardwareTestLaunch1 = "Você vai executar o teste da planta."

View File

@@ -91,6 +91,8 @@ void TitleBarView::refreshPreferences() {
assert(numberOfChar <= bufferSize);
if (preferences->angleUnit() == Preferences::AngleUnit::Radian) {
numberOfChar += strlcpy(buffer+numberOfChar, I18n::translate(I18n::Message::Rad), bufferSize - numberOfChar);
} else if (preferences->angleUnit() == Preferences::AngleUnit::Gradian) {
numberOfChar += strlcpy(buffer+numberOfChar, I18n::translate(I18n::Message::Gon), bufferSize - numberOfChar);
} else {
numberOfChar += strlcpy(buffer+numberOfChar, I18n::translate(I18n::Message::Deg), bufferSize - numberOfChar);
}

View File

@@ -223,8 +223,9 @@ public:
Expression mapOnMatrixFirstChild(ExpressionNode::ReductionContext reductionContext);
static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context * context);
Expression radianToDegree();
Expression degreeToRadian();
Expression radianToAngleUnit(Preferences::AngleUnit angleUnit);
Expression angleUnitToRadian(Preferences::AngleUnit angleUnit);
/* Approximation Helper */
// These methods reset the sApproximationEncounteredComplex flag. They should not be use to implement node approximation

View File

@@ -28,7 +28,8 @@ public:
};
enum class AngleUnit {
Degree = 0,
Radian = 1
Gradian = 1,
Radian = 2
};
Preferences();
static Preferences * sharedPreferences();

View File

@@ -23,10 +23,11 @@ public:
constexpr static int k_numberOfEntries = 37;
enum class Type {
AngleInDegrees = 0,
AngleInRadians = 1,
Cosine = 2,
Sine = 3,
Tangent = 4
AngleInGradians = 1,
AngleInRadians = 2,
Cosine = 3,
Sine = 4,
Tangent = 5
};
static const TrigonometryCheatTable * Table();
Expression simplify(const Expression e, ExpressionNode::Type type, ExpressionNode::ReductionContext reductionContext) const;
@@ -50,8 +51,8 @@ private:
};
// END OF PAIR CLASS
constexpr Row(Pair angleInRadians, Pair angleInDegrees, Pair sine, Pair cosine, Pair tangent) :
m_pairs{angleInRadians, angleInDegrees, sine, cosine, tangent} {}
constexpr Row(Pair angleInRadians, Pair angleInGradians, Pair angleInDegrees, Pair sine, Pair cosine, Pair tangent) :
m_pairs{angleInRadians, angleInGradians, angleInDegrees, sine, cosine, tangent} {}
float floatForType(Type t) const {
assert(((int) t) >= 0 && ((int) t) < k_numberOfPairs);
return m_pairs[(int)t].value();
@@ -61,7 +62,7 @@ private:
return m_pairs[(int)t].reducedExpression(assertNotUninitialized, reductionContext);
}
private:
constexpr static int k_numberOfPairs = 5;
constexpr static int k_numberOfPairs = 6;
const Pair m_pairs[k_numberOfPairs];
};
// END OF ROW CLASS

View File

@@ -150,8 +150,8 @@ Expression ComplexCartesian::argument(ExpressionNode::ReductionContext reduction
Expression divab = Division::Builder(a, b.clone());
Expression arcTangent = ArcTangent::Builder(divab);
divab.shallowReduce(reductionContext);
if (reductionContext.angleUnit() == Preferences::AngleUnit::Degree) {
Expression temp = arcTangent.degreeToRadian();
if (reductionContext.angleUnit() != Preferences::AngleUnit::Radian) {
Expression temp = arcTangent.angleUnitToRadian(reductionContext.angleUnit());
arcTangent.shallowReduce(reductionContext);
arcTangent = temp;
}
@@ -352,8 +352,8 @@ ComplexCartesian ComplexCartesian::power(ComplexCartesian & other, ExpressionNod
thc.shallowReduce(reductionContext);
dlnr.shallowReduce(reductionContext);
if (reductionContext.angleUnit() == Preferences::AngleUnit::Degree) {
Expression temp = argument.radianToDegree();
if (reductionContext.angleUnit() != Preferences::AngleUnit::Radian) {
Expression temp = argument.radianToAngleUnit(reductionContext.angleUnit());
argument.shallowReduce(reductionContext);
argument = temp;
}

View File

@@ -691,14 +691,28 @@ Expression Expression::mapOnMatrixFirstChild(ExpressionNode::ReductionContext re
return matrix.shallowReduce(reductionContext);
}
Expression Expression::radianToDegree() {
// e*180/Pi
return Multiplication::Builder(*this, Rational::Builder(180), Power::Builder(Constant::Builder(UCodePointGreekSmallLetterPi), Rational::Builder(-1)));
Expression Expression::radianToAngleUnit(Preferences::AngleUnit angleUnit) {
if (angleUnit == Preferences::AngleUnit::Degree) {
// e*180/Pi
return Multiplication::Builder(*this, Rational::Builder(180), Power::Builder(Constant::Builder(UCodePointGreekSmallLetterPi), Rational::Builder(-1)));
}
else if (angleUnit == Preferences::AngleUnit::Gradian) {
// e*200/Pi
return Multiplication::Builder(*this, Rational::Builder(200), Power::Builder(Constant::Builder(UCodePointGreekSmallLetterPi), Rational::Builder(-1)));
}
return *this;
}
Expression Expression::degreeToRadian() {
// e*Pi/180
return Multiplication::Builder(*this, Rational::Builder(1, 180), Constant::Builder(UCodePointGreekSmallLetterPi));
Expression Expression::angleUnitToRadian(Preferences::AngleUnit angleUnit) {
if (angleUnit == Preferences::AngleUnit::Degree) {
// e*Pi/180
return Multiplication::Builder(*this, Rational::Builder(1, 180), Constant::Builder(UCodePointGreekSmallLetterPi));
}
else if (angleUnit == Preferences::AngleUnit::Gradian) {
// e*Pi/200
return Multiplication::Builder(*this, Rational::Builder(1, 200), Constant::Builder(UCodePointGreekSmallLetterPi));
}
return *this;
}
Expression Expression::reduce(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) {

View File

@@ -21,6 +21,27 @@
namespace Poincare {
static constexpr double s_pi[] = {
180.0,
200.0,
M_PI
};
static constexpr int s_piDivisor[] {
180,
200,
1
};
static Expression piExpression(Preferences::AngleUnit angleUnit) {
switch (angleUnit) {
case Preferences::AngleUnit::Radian:
return static_cast<Expression>(Constant::Builder(UCodePointGreekSmallLetterPi));
default:
return static_cast<Expression>(Rational::Builder(180));
}
}
float Trigonometry::characteristicXRange(const Expression & e, Context * context, Preferences::AngleUnit angleUnit) {
assert(e.numberOfChildren() == 1);
@@ -43,7 +64,7 @@ float Trigonometry::characteristicXRange(const Expression & e, Context * context
* derivative of child(0) for any x value. */
Poincare::Derivative derivative = Poincare::Derivative::Builder(e.childAtIndex(0).clone(), Symbol::Builder(x, 1), Float<float>::Builder(1.0f));
float a = derivative.node()->approximate(float(), context, Preferences::ComplexFormat::Real, angleUnit).toScalar();
float pi = angleUnit == Preferences::AngleUnit::Radian ? M_PI : 180.0f;
float pi = s_pi[(int)angleUnit];
return 2.0f*pi/std::fabs(a);
}
@@ -202,15 +223,15 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, ExpressionN
&& e.childAtIndex(0).childAtIndex(1).type() == ExpressionNode::Type::Constant
&& e.childAtIndex(0).childAtIndex(1).convert<Constant>().isPi()
&& e.childAtIndex(0).childAtIndex(0).type() == ExpressionNode::Type::Rational)
|| (reductionContext.angleUnit() == Preferences::AngleUnit::Degree
|| ((reductionContext.angleUnit() == Preferences::AngleUnit::Degree || reductionContext.angleUnit() == Preferences::AngleUnit::Gradian)
&& e.childAtIndex(0).type() == ExpressionNode::Type::Rational))
{
Rational r = reductionContext.angleUnit() == Preferences::AngleUnit::Radian ? e.childAtIndex(0).childAtIndex(0).convert<Rational>() : e.childAtIndex(0).convert<Rational>();
/* Step 4.1. In radians:
* We first check if p/q * π is already in the right quadrant:
* p/q * π < π/2 => p/q < 2 => 2p < q */
Integer dividand = reductionContext.angleUnit() == Preferences::AngleUnit::Radian ? Integer::Addition(r.unsignedIntegerNumerator(), r.unsignedIntegerNumerator()) : r.unsignedIntegerNumerator();
Integer divisor = reductionContext.angleUnit() == Preferences::AngleUnit::Radian ? r.integerDenominator() : Integer::Multiplication(r.integerDenominator(), Integer(90));
Integer dividand = Integer::Addition(r.unsignedIntegerNumerator(), r.unsignedIntegerNumerator());
Integer divisor = Integer::Multiplication(r.integerDenominator(), Integer(s_piDivisor[(int)reductionContext.angleUnit()]));
if (divisor.isLowerThan(dividand)) {
/* Step 4.2. p/q * π is not in the wanted trigonometrical quadrant.
* We could subtract n*π to p/q with n an integer.
@@ -218,9 +239,9 @@ Expression Trigonometry::shallowReduceDirectFunction(Expression & e, ExpressionN
* (p/q * π - q'*π) < π/2 => r'/q < 1/2 => 2*r'<q
* (q' is the theoretical n).*/
int unaryCoefficient = 1; // store 1 or -1 for the final result.
Integer piDivisor = reductionContext.angleUnit() == Preferences::AngleUnit::Radian ? r.integerDenominator() : Integer::Multiplication(r.integerDenominator(), Integer(180));
Integer piDivisor = Integer::Multiplication(r.integerDenominator(), Integer(s_piDivisor[(int)reductionContext.angleUnit()]));
IntegerDivision div = Integer::Division(r.unsignedIntegerNumerator(), piDivisor);
dividand = reductionContext.angleUnit() == Preferences::AngleUnit::Radian ? Integer::Addition(div.remainder, div.remainder) : div.remainder;
dividand = Integer::Addition(div.remainder, div.remainder);
if (divisor.isLowerThan(dividand)) {
/* Step 4.3. r'/q * π is not in the wanted trigonometrical quadrant,
* and because r'<q (as r' is the remainder of an euclidian division
@@ -270,7 +291,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Expressio
}
}
float pi = reductionContext.angleUnit() == Preferences::AngleUnit::Radian ? M_PI : 180;
float pi = s_pi[(int)reductionContext.angleUnit()];
// Step 1. Look for an expression of type "acos(cos(x))", return x
if (AreInverseFunctions(e.childAtIndex(0), e)) {
@@ -339,7 +360,7 @@ Expression Trigonometry::shallowReduceInverseFunction(Expression & e, Expressio
// The argument was made positive
// acos(-x) = π-acos(x)
if (e.type() == ExpressionNode::Type::ArcCosine) {
Expression pi = reductionContext.angleUnit() == Preferences::AngleUnit::Radian ? static_cast<Expression>(Constant::Builder(UCodePointGreekSmallLetterPi)) : static_cast<Expression>(Rational::Builder(180));
Expression pi = piExpression(reductionContext.angleUnit());
Subtraction s = Subtraction::Builder();
e.replaceWithInPlace(s);
s.replaceChildAtIndexInPlace(0, pi);
@@ -365,6 +386,9 @@ std::complex<T> Trigonometry::ConvertToRadian(const std::complex<T> c, Preferenc
if (angleUnit == Preferences::AngleUnit::Degree) {
return c * std::complex<T>(M_PI/180.0);
}
else if (angleUnit == Preferences::AngleUnit::Gradian) {
return c * std::complex<T>(M_PI/200.0);
}
return c;
}
@@ -373,6 +397,9 @@ std::complex<T> Trigonometry::ConvertRadianToAngleUnit(const std::complex<T> c,
if (angleUnit == Preferences::AngleUnit::Degree) {
return c * std::complex<T>(180/M_PI);
}
else if (angleUnit == Preferences::AngleUnit::Gradian) {
return c * std::complex<T>(200/M_PI);
}
return c;
}

View File

@@ -2,6 +2,12 @@
namespace Poincare {
static constexpr TrigonometryCheatTable::Type s_targetType[] = {
TrigonometryCheatTable::Type::AngleInDegrees,
TrigonometryCheatTable::Type::AngleInGradians,
TrigonometryCheatTable::Type::AngleInRadians
};
Expression TrigonometryCheatTable::Row::Pair::reducedExpression(bool assertNotUninitialized, ExpressionNode::ReductionContext reductionContext) const {
Expression e = Expression::Parse(m_expression);
if (assertNotUninitialized) {
@@ -23,7 +29,7 @@ Expression TrigonometryCheatTable::simplify(const Expression e, ExpressionNode::
|| type == ExpressionNode::Type::ArcTangent);
// Compute the input and output types
Type angleUnitType = reductionContext.angleUnit() == Preferences::AngleUnit::Radian ? Type::AngleInRadians : Type::AngleInDegrees;
Type angleUnitType = s_targetType[(int)reductionContext.angleUnit()];
Type trigonometricFunctionType;
if (type == ExpressionNode::Type::Cosine || type == ExpressionNode::Type::ArcCosine) {
trigonometricFunctionType = Type::Cosine;
@@ -37,7 +43,7 @@ Expression TrigonometryCheatTable::simplify(const Expression e, ExpressionNode::
Type outputType = isIndirectType ? angleUnitType : trigonometricFunctionType;
// Avoid looping if we can exclude quickly that e is in the table
if ((inputType == Type::AngleInDegrees
if (((inputType == Type::AngleInDegrees || inputType == Type::AngleInGradians)
&& e.type() != ExpressionNode::Type::Rational)
|| (inputType == Type::AngleInRadians
&& e.type() != ExpressionNode::Type::Rational
@@ -78,186 +84,223 @@ Expression TrigonometryCheatTable::simplify(const Expression e, ExpressionNode::
const TrigonometryCheatTable * TrigonometryCheatTable::Table() {
static Row sTableRows[] = {
Row(Row::Pair("-90", -90.0f),
Row::Pair("-100", -100.0f),
Row::Pair("π*(-2)^(-1)", -1.5707963267948966f),
Row::Pair(""),
Row::Pair("-1",-1.0f),
Row::Pair("undef")),
Row(Row::Pair("-75",-75.0),
Row::Pair("-250/3",-250.0/3),
Row::Pair("π*(-5)*12^(-1)",-1.3089969389957472f),
Row::Pair(""),
Row::Pair("(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)",-0.9659258262890683f),
Row::Pair("-(3^(1/2)+2)",-3.7320508075688776f)),
Row(Row::Pair("-72",-72.0),
Row::Pair("-80",-80),
Row::Pair("π*2*(-5)^(-1)",-1.2566370614359172f),
Row::Pair(""),
Row::Pair("-(5/8+5^(1/2)/8)^(1/2)",-0.9510565162951535f),
Row::Pair("-(5+2*5^(1/2))^(1/2)",-3.077683537175253f)),
Row(Row::Pair("-135/2",67.5f),
Row::Pair("-75",-75.0),
Row::Pair("π*(-3)*8^(-1)",-1.1780972450961724f),
Row::Pair(""),
Row::Pair("-(2+2^(1/2))^(1/2)*2^(-1)",-0.9238795325112867f),
Row::Pair("-1-2^(1/2)",-2.4142135623730945f)),
Row(Row::Pair("-60",-60.0f),
Row::Pair("-200/3",-200.0/3),
Row::Pair("π*(-3)^(-1)",-1.0471975511965976f),
Row::Pair(""),
Row::Pair("-3^(1/2)*2^(-1)",-0.8660254037844386f),
Row::Pair("-3^(1/2)",-1.7320508075688767f)),
Row(Row::Pair("-54",-54.0f),
Row::Pair("-60",-60.0),
Row::Pair("π*(-3)*10^(-1)",-0.9424777960769379),
Row::Pair(""),
Row::Pair("4^(-1)*(-1-5^(1/2))",-0.8090169943749473f),
Row::Pair("-(1+2*5^(-1/2))^(1/2)",-1.3763819204711731f)),
Row(Row::Pair("-45",-45.0f),
Row::Pair("-50",-50),
Row::Pair("π*(-4)^(-1)",-0.7853981633974483f),
Row::Pair(""),
Row::Pair("(-1)*(2^(-1/2))",-0.7071067811865475f),
Row::Pair("-1",-1.0f)),
Row(Row::Pair("-36",-36.0f),
Row::Pair("-40",-40.0),
Row::Pair("π*(-5)^(-1)",-0.6283185307179586f),
Row::Pair(""),
Row::Pair("-(5/8-5^(1/2)/8)^(1/2)",-0.5877852522924731f),
Row::Pair("-(5-2*5^(1/2))^(1/2)",-0.7265425280053609f)),
Row(Row::Pair("-30",-30.0f),
Row::Pair("-100/3",-100/3),
Row::Pair("π*(-6)^(-1)",-0.5235987755982988f),
Row::Pair(""),
Row::Pair("-0.5",-0.5f),
Row::Pair("-3^(-1/2)",-0.5773502691896256f)),
Row(Row::Pair("-45/2",-22.5f),
Row::Pair("-25",-25.0),
Row::Pair("π*(-8)^(-1)",-0.39269908169872414f),
Row::Pair(""),
Row::Pair("(2-2^(1/2))^(1/2)*(-2)^(-1)",-0.3826834323650898f),
Row::Pair("1-2^(1/2)",-0.4142135623730951f)),
Row(Row::Pair("-18",-18.0f),
Row::Pair("-20",-20.0),
Row::Pair("π*(-10)^(-1)",-0.3141592653589793f),
Row::Pair(""),
Row::Pair("4^(-1)*(1-5^(1/2))",-0.3090169943749474f),
Row::Pair("-(1-2*5^(-1/2))^(1/2)",-0.3249196962329063f)),
Row(Row::Pair("-15",-15.0f),
Row::Pair("-50/3",-50.0/3),
Row::Pair("π*(-12)^(-1)",-0.2617993877991494f),
Row::Pair(""),
Row::Pair("-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",-0.25881904510252074f),
Row::Pair("3^(1/2)-2",-0.2679491924311227f)),
Row(Row::Pair("0",0.0f),
Row::Pair("0",0.0f),
Row::Pair("0",0.0f),
Row::Pair("1",1.0f),
Row::Pair("0",0.0f),
Row::Pair("0",0.0f)),
Row(Row::Pair("15",15.0f),
Row::Pair("50/3",50.0/3),
Row::Pair("π*12^(-1)",0.2617993877991494f),
Row::Pair("6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",0.9659258262890683f),
Row::Pair("6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)",0.25881904510252074f),
Row::Pair("-(3^(1/2)-2)",0.2679491924311227f)),
Row(Row::Pair("18",18.0f),
Row::Pair("20",20.0),
Row::Pair("π*10^(-1)",0.3141592653589793f),
Row::Pair("(5/8+5^(1/2)/8)^(1/2)",0.9510565162951535f),
Row::Pair("4^(-1)*(5^(1/2)-1)",0.3090169943749474f),
Row::Pair("(1-2*5^(-1/2))^(1/2)",0.3249196962329063f)),
Row(Row::Pair("45/2",22.5f),
Row::Pair("25",25.0),
Row::Pair("π*8^(-1)",0.39269908169872414f),
Row::Pair("(2+2^(1/2))^(1/2)*2^(-1)",0.9238795325112867f),
Row::Pair("(2-2^(1/2))^(1/2)*2^(-1)",0.3826834323650898f),
Row::Pair("2^(1/2)-1",0.4142135623730951f)),
Row(Row::Pair("30",30.0f),
Row::Pair("100/3",100/3),
Row::Pair("π*6^(-1)",0.5235987755982988f),
Row::Pair("3^(1/2)*2^(-1)",0.8660254037844387f),
Row::Pair("0.5",0.5f),
Row::Pair("3^(-1/2)",0.5773502691896256f)),
Row(Row::Pair("36",36.0f),
Row::Pair("40",40.0),
Row::Pair("π*5^(-1)",0.6283185307179586f),
Row::Pair("(5^(1/2)+1)*4^(-1)",0.8090169943749475f),
Row::Pair("(5/8-5^(1/2)/8)^(1/2)",0.5877852522924731f),
Row::Pair("(5-2*5^(1/2))^(1/2)",0.7265425280053609f)),
Row(Row::Pair("45",45.0f),
Row::Pair("50",50),
Row::Pair("π*4^(-1)",0.7853981633974483f),
Row::Pair("2^(-1/2)",0.7071067811865476f),
Row::Pair("2^(-1/2)",0.7071067811865475f),
Row::Pair("1",1.0f)),
Row(Row::Pair("54",54.0f),
Row::Pair("60",60.0),
Row::Pair("π*3*10^(-1)",0.9424777960769379f),
Row::Pair("(5/8-5^(1/2)/8)^(1/2)",0.5877852522924732f),
Row::Pair("4^(-1)*(5^(1/2)+1)",0.8090169943749473f),
Row::Pair("(1+2*5^(-1/2))^(1/2)",1.3763819204711731f)),
Row(Row::Pair("60",60.0f),
Row::Pair("200/3",200.0/3),
Row::Pair("π*3^(-1)",1.0471975511965976f),
Row::Pair("0.5",0.5f),
Row::Pair("3^(1/2)*2^(-1)",0.8660254037844386f),
Row::Pair("3^(1/2)",1.7320508075688767f)),
Row(Row::Pair("135/2",67.5f),
Row::Pair("75",75.0),
Row::Pair("π*3*8^(-1)",1.1780972450961724f),
Row::Pair("(2-2^(1/2))^(1/2)*2^(-1)",0.38268343236508984f),
Row::Pair("(2+2^(1/2))^(1/2)*2^(-1)",0.9238795325112867f),
Row::Pair("1+2^(1/2)",2.4142135623730945f)),
Row(Row::Pair("72",72.0f),
Row::Pair("80",80),
Row::Pair("π*2*5^(-1)",1.2566370614359172f),
Row::Pair("(5^(1/2)-1)*4^(-1)",0.30901699437494745f),
Row::Pair("(5/8+5^(1/2)/8)^(1/2)",0.9510565162951535f),
Row::Pair("(5+2*5^(1/2))^(1/2)",3.077683537175253f)),
Row(Row::Pair("75",75.0f),
Row::Pair("250/3",250.0/3),
Row::Pair("π*5*12^(-1)",1.3089969389957472f),
Row::Pair("6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)",0.25881904510252074f),
Row::Pair("6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",0.9659258262890683f),
Row::Pair("3^(1/2)+2",3.7320508075688776f)),
Row(Row::Pair("90",90.0f),
Row::Pair("100",100.0f),
Row::Pair("π*2^(-1)",1.5707963267948966f),
Row::Pair("0",0.0f),
Row::Pair("1",1.0f),
Row::Pair("undef")),
Row(Row::Pair("105",105.0f),
Row::Pair("350/3",350.0/3),
Row::Pair("π*7*12^(-1)",1.832595714594046f),
Row::Pair("-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)",-0.25881904510252063f),
Row::Pair(""),
Row::Pair("")),
Row(Row::Pair("108",108.0f),
Row::Pair("120",120.0),
Row::Pair("π*3*5^(-1)",1.8849555921538759f),
Row::Pair("(1-5^(1/2))*4^(-1)",-0.30901699437494734f),
Row::Pair(""),
Row::Pair("")),
Row(Row::Pair("225/2",112.5f),
Row::Pair("125",125),
Row::Pair("π*5*8^(-1)",1.9634954084936207f),
Row::Pair("(2-2^(1/2))^(1/2)*(-2)^(-1)",-0.3826834323650897f),
Row::Pair(""),
Row::Pair("")),
Row(Row::Pair("120",120.0f),
Row::Pair("400/3",400/3),
Row::Pair("π*2*3^(-1)",2.0943951023931953f),
Row::Pair("-0.5",-0.5f),
Row::Pair(""),
Row::Pair("")),
Row(Row::Pair("126",126.0f),
Row::Pair("140",140),
Row::Pair("π*7*10^(-1)",2.199114857512855f),
Row::Pair("-(5*8^(-1)-5^(1/2)*8^(-1))^(1/2)",-0.587785252292473f),
Row::Pair(""),
Row::Pair("")),
Row(Row::Pair("135",135.0f),
Row::Pair("150",150.0),
Row::Pair("π*3*4^(-1)",2.356194490192345f),
Row::Pair("(-1)*(2^(-1/2))",-0.7071067811865475f),
Row::Pair(""),
Row::Pair("")),
Row(Row::Pair("144",144.0f),
Row::Pair("160",160.0),
Row::Pair("π*4*5^(-1)",2.5132741228718345f),
Row::Pair("(-5^(1/2)-1)*4^(-1)",-0.8090169943749473f),
Row::Pair(""),
Row::Pair("")),
Row(Row::Pair("150",150.0f),
Row::Pair("500/3",500.0/3),
Row::Pair("π*5*6^(-1)",2.6179938779914944f),
Row::Pair("-3^(1/2)*2^(-1)",-0.8660254037844387f),
Row::Pair(""),
Row::Pair("")),
Row(Row::Pair("315/2",157.5f),
Row::Pair("350",350.0),
Row::Pair("π*7*8^(-1)",2.748893571891069f),
Row::Pair("-(2+2^(1/2))^(1/2)*2^(-1)",-0.9238795325112867f),
Row::Pair(""),
Row::Pair("")),
Row(Row::Pair("162",162.0f),
Row::Pair("180",180.0),
Row::Pair("π*9*10^(-1)",2.827433388230814f),
Row::Pair("-(5*8^(-1)+5^(1/2)*8^(-1))^(1/2)",-0.9510565162951535f),
Row::Pair(""),
Row::Pair("")),
Row(Row::Pair("165",165.0f),
Row::Pair("550/3",550.0/3),
Row::Pair("π*11*12^(-1)",2.8797932657906435f),
Row::Pair("(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)",-0.9659258262890682f),
Row::Pair(""),
Row::Pair("")),
Row(Row::Pair("180",180.0f),
Row::Pair("200",200.0),
Row::Pair("π",3.141592653589793f),
Row::Pair("-1",-1.0f),
Row::Pair("0",0.0f),

View File

@@ -394,6 +394,7 @@ QUIZ_CASE(poincare_approximation_trigonometry_functions) {
// On R
assert_expression_approximates_to<double>("cos(2)", "-4.1614683654714ᴇ-1", Radian);
assert_expression_approximates_to<double>("cos(2)", "0.9993908270191", Degree);
assert_expression_approximates_to<double>("cos(2)", "9.9950656036573ᴇ-1", Gradian);
// Oscillator
assert_expression_approximates_to<float>("cos(π/2)", "0", Radian);
assert_expression_approximates_to<double>("cos(3×π/2)", "0", Radian);
@@ -415,6 +416,7 @@ QUIZ_CASE(poincare_approximation_trigonometry_functions) {
// On R
assert_expression_approximates_to<double>("sin(2)", "9.0929742682568ᴇ-1", Radian);
assert_expression_approximates_to<double>("sin(2)", "3.4899496702501ᴇ-2", Degree);
assert_expression_approximates_to<double>("sin(2)", "3.1410759078128ᴇ-2", Gradian);
// Oscillator
assert_expression_approximates_to<float>("sin(π/2)", "1", Radian);
assert_expression_approximates_to<double>("sin(3×π/2)", "-1", Radian);
@@ -437,6 +439,7 @@ QUIZ_CASE(poincare_approximation_trigonometry_functions) {
// On R
assert_expression_approximates_to<double>("tan(2)", "-2.1850398632615", Radian);
assert_expression_approximates_to<double>("tan(2)", "3.4920769491748ᴇ-2", Degree);
assert_expression_approximates_to<double>("tan(2)", "3.1426266043351ᴇ-2", Gradian);
// Tangent-style
assert_expression_approximates_to<float>("tan(π/2)", Undefined::Name(), Radian);
assert_expression_approximates_to<double>("tan(3×π/2)", Undefined::Name(), Radian);
@@ -461,6 +464,7 @@ QUIZ_CASE(poincare_approximation_trigonometry_functions) {
assert_expression_approximates_to<double>("acos(0.5)", "1.0471975511966", Radian);
assert_expression_approximates_to<double>("acos(0.03)", "1.5407918249714", Radian);
assert_expression_approximates_to<double>("acos(0.5)", "60", Degree);
assert_expression_approximates_to<double>("acos(0.5)", "66.666666666667", Gradian);
// On [1, inf[
assert_expression_approximates_to<double>("acos(2)", "1.3169578969248×𝐢", Radian);
assert_expression_approximates_to<double>("acos(2)", "75.456129290217×𝐢", Degree);
@@ -483,6 +487,9 @@ QUIZ_CASE(poincare_approximation_trigonometry_functions) {
assert_expression_approximates_to<double>("acos(0)", "90", Degree);
assert_expression_approximates_to<float>("acos(-1)", "180", Degree);
assert_expression_approximates_to<double>("acos(1)", "0", Degree);
assert_expression_approximates_to<double>("acos(0)", "100", Gradian);
assert_expression_approximates_to<float>("acos(-1)", "200", Gradian)
assert_expression_approximates_to<double>("acos(1)", "0", Gradian);
/* asin: [-1,1] -> R
* ]-inf,-1[ -> -π/2+R×i (odd)

View File

@@ -8,6 +8,7 @@ const char * BigOverflowedIntegerString(); // OverflowedIntegerString with a 2 o
constexpr Poincare::ExpressionNode::ReductionTarget System = Poincare::ExpressionNode::ReductionTarget::System;
constexpr Poincare::ExpressionNode::ReductionTarget User = Poincare::ExpressionNode::ReductionTarget::User;
constexpr Poincare::Preferences::AngleUnit Degree = Poincare::Preferences::AngleUnit::Degree;
constexpr Poincare::Preferences::AngleUnit Gradian = Poincare::Preferences::AngleUnit::Gradian;
constexpr Poincare::Preferences::AngleUnit Radian = Poincare::Preferences::AngleUnit::Radian;
constexpr Poincare::Preferences::ComplexFormat Cartesian = Poincare::Preferences::ComplexFormat::Cartesian;
constexpr Poincare::Preferences::ComplexFormat Polar = Poincare::Preferences::ComplexFormat::Polar;