diff --git a/apps/calculation/additional_outputs/integer_list_controller.cpp b/apps/calculation/additional_outputs/integer_list_controller.cpp index 634c24f3a96..d7ebd019429 100644 --- a/apps/calculation/additional_outputs/integer_list_controller.cpp +++ b/apps/calculation/additional_outputs/integer_list_controller.cpp @@ -1,6 +1,8 @@ #include "integer_list_controller.h" #include +#include #include +#include #include #include #include "../app.h" @@ -26,10 +28,30 @@ Integer::Base baseAtIndex(int index) { void IntegerListController::setExpression(Poincare::Expression e) { ExpressionsListController::setExpression(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) { - m_layouts[index] = integer.createLayout(baseAtIndex(index)); + assert(!m_expression.isUninitialized() && m_expression.type() == ExpressionNode::Type::BasedInteger || (m_expression.type() == ExpressionNode::Type::Opposite && m_expression.childAtIndex(0).type() == ExpressionNode::Type::BasedInteger)); + assert(!m_expression.isUninitialized()); + + if (m_expression.type() == ExpressionNode::Type::BasedInteger) { + Integer integer = static_cast(m_expression).integer(); + for (int index = 0; index < k_indexOfFactorExpression; ++index) { + m_layouts[index] = integer.createLayout(baseAtIndex(index)); + } + } + else + { + Opposite b = static_cast(m_expression); + Expression e = b.childAtIndex(0); + Integer childInt = static_cast(e).integer(); + childInt.setNegative(true); + Integer num_bits = Integer::CeilingLog2(childInt); + Integer integer = Integer::TwosComplementToBits(childInt, num_bits); + for (int index = 0; index < k_indexOfFactorExpression; ++index) { + if(baseAtIndex(index) == Integer::Base::Decimal) { + m_layouts[index] = childInt.createLayout(baseAtIndex(index)); + } else { + m_layouts[index] = integer.createLayout(baseAtIndex(index)); + } + } } // Computing factorExpression Expression factor = Factor::Builder(m_expression.clone()); diff --git a/apps/calculation/calculation.h b/apps/calculation/calculation.h index 4c026cbc42b..4c40bcbb1aa 100644 --- a/apps/calculation/calculation.h +++ b/apps/calculation/calculation.h @@ -97,7 +97,7 @@ friend CalculationStore; AdditionalInformationType additionalInformationType(Poincare::Context * context); private: static constexpr KDCoordinate k_heightComputationFailureHeight = 50; - static constexpr const char * k_maximalIntegerWithAdditionalInformation = "10000000000000000"; + static constexpr const char * k_maximalIntegerWithAdditionalInformation = "18446744073709551617"; // 2^64 + 1 void setHeights(KDCoordinate height, KDCoordinate expandedHeight); diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index 0cb24ab13c6..85e1a688f16 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -81,7 +81,34 @@ const ToolboxMessageTree matricesChildren[] = { const ToolboxMessageTree vectorsChildren[] = { ToolboxMessageTree::Leaf(I18n::Message::DotCommandWithArg, I18n::Message::Dot), ToolboxMessageTree::Leaf(I18n::Message::CrossCommandWithArg, I18n::Message::Cross), - ToolboxMessageTree::Leaf(I18n::Message::NormVectorCommandWithArg, I18n::Message::NormVector), + ToolboxMessageTree::Leaf(I18n::Message::NormVectorCommandWithArg, I18n::Message::NormVector) +}; + +const ToolboxMessageTree logicExplicitChildren[] = { + ToolboxMessageTree::Leaf(I18n::Message::LogicalNotExplicitCommandWithArg, I18n::Message::LogicalNot), + ToolboxMessageTree::Leaf(I18n::Message::LogicalShiftRightArithmeticExplicitCommandWithArg, I18n::Message::LogicalShiftRightArithmetic), + ToolboxMessageTree::Leaf(I18n::Message::LogicalRotateLeftExplicitCommandWithArg, I18n::Message::LogicalRotateLeft), + ToolboxMessageTree::Leaf(I18n::Message::LogicalRotateRightExplicitCommandWithArg, I18n::Message::LogicalRotateRight), + ToolboxMessageTree::Leaf(I18n::Message::LogicalBitsClearExplicitCommandWithArg, I18n::Message::LogicalBitsClear)}; + +const ToolboxMessageTree logicChildren[] = { + ToolboxMessageTree::Node(I18n::Message::ExplicitNumberOfBits, logicExplicitChildren), + ToolboxMessageTree::Leaf(I18n::Message::LogicalAndCommandWithArg, I18n::Message::LogicalAnd), + ToolboxMessageTree::Leaf(I18n::Message::LogicalOrCommandWithArg, I18n::Message::LogicalOr), + ToolboxMessageTree::Leaf(I18n::Message::LogicalXorCommandWithArg, I18n::Message::LogicalXor), + ToolboxMessageTree::Leaf(I18n::Message::LogicalNotCommandWithArg, I18n::Message::LogicalNot), + ToolboxMessageTree::Leaf(I18n::Message::LogicalShiftLeftCommandWithArg, I18n::Message::LogicalShiftLeft), + ToolboxMessageTree::Leaf(I18n::Message::LogicalShiftRightCommandWithArg, I18n::Message::LogicalShiftRight), + ToolboxMessageTree::Leaf(I18n::Message::LogicalShiftRightArithmeticCommandWithArg, I18n::Message::LogicalShiftRightArithmetic), + ToolboxMessageTree::Leaf(I18n::Message::LogicalRotateLeftCommandWithArg, I18n::Message::LogicalRotateLeft), + ToolboxMessageTree::Leaf(I18n::Message::LogicalRotateRightCommandWithArg, I18n::Message::LogicalRotateRight), + ToolboxMessageTree::Leaf(I18n::Message::LogicalBitGetCommandWithArg, I18n::Message::LogicalBitGet), + ToolboxMessageTree::Leaf(I18n::Message::LogicalBitSetCommandWithArg, I18n::Message::LogicalBitSet), + ToolboxMessageTree::Leaf(I18n::Message::LogicalBitClearCommandWithArg, I18n::Message::LogicalBitClear), + ToolboxMessageTree::Leaf(I18n::Message::LogicalBitFlipCommandWithArg, I18n::Message::LogicalBitFlip), + ToolboxMessageTree::Leaf(I18n::Message::LogicalBitsClearCommandWithArg, I18n::Message::LogicalBitsClear), + ToolboxMessageTree::Leaf(I18n::Message::TwosComplementToBitsCommandWithArg, I18n::Message::TwosComplementToBits), + ToolboxMessageTree::Leaf(I18n::Message::CeilingLog2CommandWithArg, I18n::Message::CeilingLog2) }; #if LIST_ARE_DEFINED @@ -867,7 +894,8 @@ const ToolboxMessageTree menu[] = { ToolboxMessageTree::Node(I18n::Message::HyperbolicTrigonometry, trigonometryChildren), ToolboxMessageTree::Node(I18n::Message::Fluctuation, predictionChildren), ToolboxMessageTree::Node(I18n::Message::Chemistry, chemistry), - ToolboxMessageTree::Node(I18n::Message::Physics, Physics) + ToolboxMessageTree::Node(I18n::Message::Physics, Physics), + ToolboxMessageTree::Node(I18n::Message::Logic, logicChildren), }; const ToolboxMessageTree toolboxModel = ToolboxMessageTree::Node(I18n::Message::Toolbox, menu); diff --git a/apps/shared.universal.i18n b/apps/shared.universal.i18n index cad61ea9b97..08a516ff50c 100644 --- a/apps/shared.universal.i18n +++ b/apps/shared.universal.i18n @@ -485,3 +485,28 @@ Rstvt_Water = "1.01·10^3_Ω_m" Rstvt_Air = "1.00·10^9_Ω_m" Rstvt_Glass = "5.00·10^14_Ω_m" Rstvt_Wood = "1.00·10^3_Ω_m" +LogicalAnd = "a AND b" +LogicalAndCommandWithArg = "and(a,b)" +LogicalBitClearCommandWithArg = "bclr(a,b)" +LogicalBitFlipCommandWithArg = "bflp(a,b)" +LogicalBitGetCommandWithArg = "bit(a,b)" +LogicalBitSetCommandWithArg = "bset(a,b)" +LogicalBitsClearCommandWithArg = "bic(a,b)" +LogicalBitsClearExplicitCommandWithArg = "bic(a,b,n)" +LogicalNot = "NOT a" +LogicalNotCommandWithArg = "not(a)" +LogicalNotExplicitCommandWithArg = "not(a,n)" +LogicalOr = "a OR b" +LogicalOrCommandWithArg = "or(a,b)" +LogicalShiftLeftCommandWithArg = "sll(a,s)" +LogicalShiftRightArithmeticCommandWithArg = "sra(a,s)" +LogicalShiftRightArithmeticExplicitCommandWithArg = "sra(a,s,n)" +LogicalShiftRightCommandWithArg = "srl(a,s)" +LogicalRotateLeftCommandWithArg = "rol(a,r)" +LogicalRotateLeftExplicitCommandWithArg = "rol(a,r,n)" +LogicalRotateRightCommandWithArg = "ror(a,r)" +LogicalRotateRightExplicitCommandWithArg = "ror(a,r,n)" +LogicalXor = "a XOR b" +LogicalXorCommandWithArg = "xor(a,r)" +TwosComplementToBitsCommandWithArg = "tc(a,n)" +CeilingLog2CommandWithArg = "clog2(a)" diff --git a/apps/toolbox.de.i18n b/apps/toolbox.de.i18n index 40c021a7065..c8d8dc5ae6d 100644 --- a/apps/toolbox.de.i18n +++ b/apps/toolbox.de.i18n @@ -510,3 +510,17 @@ HartreeConstantTag = "Hartbaum-Konstante" MagneticFluxQuantumTag = "Magnetisches Fluss-Quantum" ConductanceQuantumTag = "Leitwertquantum" CirculationQuantumTag = "Auflage-Quantum" +Logic = "Logik" +LogicalBitClear = "Bit b in a löschen" +LogicalBitFlip = "Bit b in a umkehren" +LogicalBitGet = "Bit b aus a lesen" +LogicalBitSet = "Bit b in a setzen" +LogicalBitsClear = "a AND NOT b" +LogicalShiftLeft = "Bitverschiebung links von a um s" +LogicalShiftRightArithmetic = "Arithm. Versch. rechts von a um s" +LogicalShiftRight = "Bitverschiebung rechts von a um s" +LogicalRotateLeft = "Rotieren von a um r Bit n. links" +LogicalRotateRight= "Rotieren von a um r Bit n. rechts" +TwosComplementToBits = "Äquivalent im Zweierkomplement" +CeilingLog2 = "Anzahl der Bits, die zum Speichern von a benötigt werden" +ExplicitNumberOfBits = "Explizite Bitbreite" diff --git a/apps/toolbox.en.i18n b/apps/toolbox.en.i18n index b3ff61e2961..4e093158a43 100644 --- a/apps/toolbox.en.i18n +++ b/apps/toolbox.en.i18n @@ -510,3 +510,17 @@ HartreeConstantTag = "Hartree Constant" MagneticFluxQuantumTag = "Magnetic Flux Quantum" ConductanceQuantumTag = "Conductance Quantum" CirculationQuantumTag = "Circulation Quantum" +Logic = "Logic" +LogicalBitClear = "Clear bit b in a" +LogicalBitFlip = "Flip bit b in a" +LogicalBitGet = "Get bit b in a" +LogicalBitSet = "Set bit b in a" +LogicalBitsClear = "Clear a with b [a AND NOT b]" +LogicalShiftLeft = "Logical shift left [a << s]" +LogicalShiftRightArithmetic = "Arithmetic shift right [a >>> s]" +LogicalShiftRight = "Logical shift right [a >> s]" +LogicalRotateLeft = "Rotate r bits of a to the left" +LogicalRotateRight= "Rotate r bits of a to the right" +TwosComplementToBits = "Two's complement equivalent" +CeilingLog2 = "Number of bits needed to store a" +ExplicitNumberOfBits = "Explicit number of bits" diff --git a/apps/toolbox.es.i18n b/apps/toolbox.es.i18n index f4f9a212c56..483bee01932 100644 --- a/apps/toolbox.es.i18n +++ b/apps/toolbox.es.i18n @@ -510,3 +510,17 @@ HartreeConstantTag = "Constante de Hartree" MagneticFluxQuantumTag = "Flujo Magnético Cuántico" ConductanceQuantumTag = "Conductancia Quantum" CirculationQuantumTag = "Circulación Quantum" +Logic = "Lógico" +LogicalBitClear = "Borrar bit número b en a" +LogicalBitFlip = "Voltear el bit número b en a" +LogicalBitGet = "Obtener el bit número b en a" +LogicalBitSet = "Establecer el número de bit b en a" +LogicalBitsClear = "Borrar a con bits en b" +LogicalShiftLeft = "Desplazamiento lógico izquierda" +LogicalShiftRightArithmetic = "Desplazamiento aritmético derecha" +LogicalShiftRight = "Desplazamiento lógico derecha" +LogicalRotateLeft = "Gire r bits de a hacia izquierda" +LogicalRotateRight= "Gire r bits de a hacia derecha" +TwosComplementToBits = "Equivalente en complemento a dos" +CeilingLog2 = "Número de bits necesarios para almacenar a" +ExplicitNumberOfBits = "Número explícito de bits" diff --git a/apps/toolbox.fr.i18n b/apps/toolbox.fr.i18n index 41164cd0863..7ad42eaa81c 100644 --- a/apps/toolbox.fr.i18n +++ b/apps/toolbox.fr.i18n @@ -514,3 +514,17 @@ HartreeConstantTag = "Constante de Hartree" MagneticFluxQuantumTag = "Quantum de Flux Magnétique" ConductanceQuantumTag = "Quantum de Conductance" CirculationQuantumTag = "Quantum de Circulation" +Logic = "Logique" +LogicalBitClear = "Effacer le bit numéro b dans a" +LogicalBitFlip = "Inverser le bit numéro b dans a" +LogicalBitGet = "Obtenir le bit numéro b dans a" +LogicalBitSet = "Mettre le bit numéro b dans a" +LogicalBitsClear = "Effacer bits b ds a [a AND NOT b]" +LogicalShiftLeft = "Décalage logique gauche [a << s]" +LogicalShiftRightArithmetic = "Décalage arith. droite [a >>> s]" +LogicalShiftRight = "Décalage logique droite [a >> s]" +LogicalRotateLeft = "Rotation gauche de a par r bits" +LogicalRotateRight= "Rotation droite de a par r bits" +TwosComplementToBits = "Equivalent en complément à deux" +CeilingLog2 = "Nb de bits nécessaires pour stocker a" +ExplicitNumberOfBits = "Nombre indiqué de bits" diff --git a/apps/toolbox.hu.i18n b/apps/toolbox.hu.i18n index 79d22308ab3..45a437bfdf5 100644 --- a/apps/toolbox.hu.i18n +++ b/apps/toolbox.hu.i18n @@ -510,3 +510,17 @@ HartreeConstantTag = "Hartree Állandó" MagneticFluxQuantumTag = "Mágneses Fluxuskvantum" ConductanceQuantumTag = "Vezetőképesség Kvantum" CirculationQuantumTag = "Keringési Kvantum" +Logic = "Logika" +LogicalBitClear = "Tiszta bit b ban ben a" +LogicalBitFlip = "Flip bit b ban ben a" +LogicalBitGet = "Kap bit b ban ben a" +LogicalBitSet = "Készlet bit b ban ben a" +LogicalBitsClear = "Tiszta a val vel b [a AND NOT b]" +LogicalShiftLeft = "Logikai eltolás balra [a << s]" +LogicalShiftRightArithmetic = "Aritmetikai eltolás jobbra [a >>> s]" +LogicalShiftRight = "Logikai eltolás jobbra [a >> s]" +LogicalRotateLeft = "Forog r bitek nak a balra" +LogicalRotateRight= "Forog r bitek nak a jobbra" +TwosComplementToBits = "Kettő komplementere egyenértékű" +CeilingLog2 = "Az a tárolásához szükséges bitek száma" +ExplicitNumberOfBits = "Explicit bitszám" diff --git a/apps/toolbox.it.i18n b/apps/toolbox.it.i18n index 440a87f5662..8428d633c1b 100644 --- a/apps/toolbox.it.i18n +++ b/apps/toolbox.it.i18n @@ -510,3 +510,17 @@ HartreeConstantTag = "Costante di Hartree" MagneticFluxQuantumTag = "Flusso magnetico quantico" ConductanceQuantumTag = "Conduttanza quantistica" CirculationQuantumTag = "Circolazione quantistica" +Logic = "Logica" +LogicalBitClear = "Cancella il numero di bit b in a" +LogicalBitFlip = "Capovolgere il bit numero b in a" +LogicalBitGet = "Ottieni il bit numero b in a" +LogicalBitSet = "Impostare il numero di bit b in a" +LogicalBitsClear = "Cancella a con b [a AND NOT b]" +LogicalShiftLeft = "Spostamento logico a sinistra" +LogicalShiftRightArithmetic = "Spostamento aritmetico a destra" +LogicalShiftRight = "Spostamento logico a destra" +LogicalRotateLeft = "Ruota r bit di a verso sinistra" +LogicalRotateRight= "Ruota r bit di a verso destra" +TwosComplementToBits = "Equivalente in complemento di due" +CeilingLog2 = "Numero di bit necessari per memorizzare a" +ExplicitNumberOfBits = "Numero esplicito di bit" diff --git a/apps/toolbox.nl.i18n b/apps/toolbox.nl.i18n index e7a40ed2529..64156d40550 100644 --- a/apps/toolbox.nl.i18n +++ b/apps/toolbox.nl.i18n @@ -510,3 +510,17 @@ HartreeConstantTag = "Hartreeconstante" MagneticFluxQuantumTag = "Magnetische flux kwantum" ConductanceQuantumTag = "Kwantumgeleiding" CirculationQuantumTag = "Kwantumcirculatie" +Logic = "Logica" +LogicalBitClear = "Wis bitnummer b in a" +LogicalBitFlip = "Draai bitnummer b om in a" +LogicalBitGet = "Haal bit nummer b op in a" +LogicalBitSet = "Stel bitnummer b in a" +LogicalBitsClear = "Wis a met bits in b [a AND NOT b]" +LogicalShiftLeft = "Logische verschuiving naar links" +LogicalShiftRightArithmetic = "Rekenkundige verschuiving naar rechts" +LogicalShiftRight = "Logische verschuiving naar rechts" +LogicalRotateLeft = "Draai r stukjes a naar links" +LogicalRotateRight= "Draai r stukjes a naar rechts" +TwosComplementToBits = "Tweeën vullen equivalent aan" +CeilingLog2 = "Aantal bits dat nodig is om a op te slaan" +ExplicitNumberOfBits = "Expliciet aantal bits" diff --git a/apps/toolbox.pt.i18n b/apps/toolbox.pt.i18n index 4891b4e1b15..e36156edcbc 100644 --- a/apps/toolbox.pt.i18n +++ b/apps/toolbox.pt.i18n @@ -510,3 +510,17 @@ HartreeConstantTag = "Constante de Hartree" MagneticFluxQuantumTag = "Fluxo Magnético Quântico" ConductanceQuantumTag = "Quantum de Conduta" CirculationQuantumTag = "Quantum de Circulação" +Logic = "Lógica" +LogicalBitClear = "Limpar o bit b em a" +LogicalBitFlip = "Virar o bit em a" +LogicalBitGet = "Obter o bit b em a" +LogicalBitSet = "Definir o bit b em a" +LogicalBitsClear = "Limpar a com b [a AND NOT b]" +LogicalShiftLeft = "Mudar lógica à esquerda" +LogicalShiftRightArithmetic = "Mudar aritmético para a direita" +LogicalShiftRight = "Mudar lógica para a direita" +LogicalRotateLeft = "Girar r bits de a para a esquerda" +LogicalRotateRight= "Girar r bits de a para a direita" +TwosComplementToBits = "Complementar de dois equivalente" +CeilingLog2 = "Número de bits necessários para armazenar a" +ExplicitNumberOfBits = "Número explícito de bits" diff --git a/poincare/Makefile b/poincare/Makefile index 380f200ab23..d8378b8fcb5 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -50,6 +50,7 @@ poincare_src += $(addprefix poincare/src/,\ arc_tangent.cpp \ arithmetic.cpp \ based_integer.cpp \ + binary_operation.cpp \ binom_cdf.cpp \ binomial_coefficient.cpp \ binomial_distribution_function.cpp \ @@ -188,6 +189,7 @@ tests_src += $(addprefix poincare/test/,\ layout_cursor.cpp\ layout_serialization.cpp\ layout_to_expression.cpp\ + logic.cpp\ parsing.cpp\ print_float.cpp\ print_int.cpp\ diff --git a/poincare/include/poincare/binary_operation.h b/poincare/include/poincare/binary_operation.h new file mode 100644 index 00000000000..b99da0cf4b6 --- /dev/null +++ b/poincare/include/poincare/binary_operation.h @@ -0,0 +1,218 @@ +#ifndef POINCARE_BINARY_OPERATION_H +#define POINCARE_BINARY_OPERATION_H + +#include +#include + +namespace Poincare +{ + + template + class BinaryOperationNode final : public ExpressionNode { + public: + // TreeNode + size_t size() const override { return sizeof(BinaryOperationNode); } + int numberOfChildren() const override; +#if POINCARE_TREE_LOG + void logNodeName(std::ostream &stream) const override + { + stream << "BinaryOperation"; + } +#endif + + // Properties + Type type() const override { return Type::And; } + + // Layout + Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; + int serialize(char *buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; + // Simplification + Expression shallowReduce(ReductionContext reductionContext) override; + LayoutShape leftLayoutShape() const override { return LayoutShape::MoreLetters; }; + LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; } + + // Evaluation + Evaluation approximate(SinglePrecision p, ApproximationContext approximationContext) const override { return templatedApproximate(approximationContext); } + Evaluation approximate(DoublePrecision p, ApproximationContext approximationContext) const override { return templatedApproximate(approximationContext); } + + template + Evaluation templatedApproximate(ApproximationContext approximationContext) const { + return Complex::RealUndefined(); + } + }; + + class BinaryOperation final { + public: + static Expression shallowReduceDirect(Expression & e, const ExpressionNode::Type t, ExpressionNode::ReductionContext reductionContext); + }; + class And final : public Expression { + public: + And(const BinaryOperationNode<1> *n) : Expression(n) {} + static And Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("and", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class Or final : public Expression { + public: + Or(const BinaryOperationNode<5> *n) : Expression(n) {} + static Or Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("or", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class Xor final : public Expression { + public: + Xor(const BinaryOperationNode<9> *n) : Expression(n) {} + static Xor Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("xor", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class Not final : public Expression { + public: + Not(const BinaryOperationNode<13> *n) : Expression(n) {} + static Not Builder(Expression child1) { return TreeHandle::FixedArityBuilder >({child1}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("not", 1, &UntypedBuilderOneChild); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class NotExplicit final : public Expression { + public: + NotExplicit(const BinaryOperationNode<14> *n) : Expression(n) {} + static NotExplicit Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("not", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class BitClear final : public Expression { + public: + BitClear(const BinaryOperationNode<15> *n) : Expression(n) {} + static BitClear Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("bclr", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class BitFlip final : public Expression { + public: + BitFlip(const BinaryOperationNode<16> *n) : Expression(n) {} + static BitFlip Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("bflp", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class BitGet final : public Expression { + public: + BitGet(const BinaryOperationNode<17> *n) : Expression(n) {} + static BitGet Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("bit", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + class BitSet final : public Expression { + public: + BitSet(const BinaryOperationNode<18> *n) : Expression(n) {} + static BitSet Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("bset", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class BitsClear final : public Expression { + public: + BitsClear(const BinaryOperationNode<19> *n) : Expression(n) {} + static BitsClear Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("bic", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class BitsClearExplicit final : public Expression { + public: + BitsClearExplicit(const BinaryOperationNode<20> *n) : Expression(n) {} + static BitsClearExplicit Builder(Expression child1, Expression child2, Expression child3) { return TreeHandle::FixedArityBuilder >({child1, child2, child3}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("bic", 3, &UntypedBuilderThreeChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class ShiftLogicLeft final : public Expression { + public: + ShiftLogicLeft(const BinaryOperationNode<21> *n) : Expression(n) {} + static ShiftLogicLeft Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sll", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + + class ShiftLogicRight final : public Expression { + public: + ShiftLogicRight(const BinaryOperationNode<23> *n) : Expression(n) {} + static ShiftLogicRight Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("srl", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class ShiftArithmeticRight final : public Expression { + public: + ShiftArithmeticRight(const BinaryOperationNode<25> *n) : Expression(n) {} + static ShiftArithmeticRight Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sra", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class ShiftArithmeticRightExplicit final : public Expression { + public: + ShiftArithmeticRightExplicit(const BinaryOperationNode<26> *n) : Expression(n) {} + static ShiftArithmeticRightExplicit Builder(Expression child1, Expression child2, Expression child3) { return TreeHandle::FixedArityBuilder >({child1, child2, child3}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sra", 3, &UntypedBuilderThreeChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class RotateLeft final : public Expression { + public: + RotateLeft(const BinaryOperationNode<27> *n) : Expression(n) {} + static RotateLeft Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("rol", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class RotateLeftExplicit final : public Expression { + public: + RotateLeftExplicit(const BinaryOperationNode<28> *n) : Expression(n) {} + static RotateLeftExplicit Builder(Expression child1, Expression child2, Expression child3) { return TreeHandle::FixedArityBuilder >({child1, child2, child3}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("rol", 3, &UntypedBuilderThreeChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class RotateRight final : public Expression { + public: + RotateRight(const BinaryOperationNode<29> *n) : Expression(n) {} + static RotateRight Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ror", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class RotateRightExplicit final : public Expression { + public: + RotateRightExplicit(const BinaryOperationNode<30> *n) : Expression(n) {} + static RotateRightExplicit Builder(Expression child1, Expression child2, Expression child3) { return TreeHandle::FixedArityBuilder >({child1, child2, child3}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ror", 3, &UntypedBuilderThreeChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class TwosComplement final : public Expression { + public: + TwosComplement(const BinaryOperationNode<31> *n) : Expression(n) {} + static TwosComplement Builder(Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder >({child1, child2}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("tc", 2, &UntypedBuilderTwoChildren); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + + class CeilingLog2 final : public Expression { + public: + CeilingLog2(const BinaryOperationNode<32> *n) : Expression(n) {} + static CeilingLog2 Builder(Expression child1) { return TreeHandle::FixedArityBuilder >({child1}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("clog2", 1, &UntypedBuilderOneChild); + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + }; + +} // namespace Poincare + +#endif diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 4ac1ba70774..2f0361c9003 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -20,14 +20,23 @@ class Symbol; class Expression : public TreeHandle { friend class AbsoluteValue; friend class Addition; + friend class And; friend class ArcCosine; friend class ArcSine; friend class ArcTangent; friend class Arithmetic; friend class BasedInteger; + friend class BinaryOperation; friend class BinomialCoefficient; friend class BinomialDistributionFunction; + friend class BitClear; + friend class BitFlip; + friend class BitGet; + friend class BitsClear; + friend class BitsClearExplicit; + friend class BitSet; friend class Ceiling; + friend class CeilingLog2; friend class CommonLogarithm; template friend class ComplexNode; @@ -74,9 +83,12 @@ class Expression : public TreeHandle { friend class NormCDF; friend class NormCDF2; friend class NormPDF; + friend class Not; + friend class NotExplicit; friend class NthRoot; friend class Number; friend class Opposite; + friend class Or; friend class ParameteredExpression; friend class Parenthesis; friend class PermuteCoefficient; @@ -86,9 +98,17 @@ class Expression : public TreeHandle { friend class Product; friend class Randint; friend class RealPart; + friend class RotateLeft; + friend class RotateLeftExplicit; + friend class RotateRight; + friend class RotateRightExplicit; friend class Round; friend class Sequence; friend class SequenceNode; + friend class ShiftArithmeticRight; + friend class ShiftArithmeticRightExplicit; + friend class ShiftLogicLeft; + friend class ShiftLogicRight; friend class SignFunction; friend class Sine; friend class SquareRoot; @@ -104,11 +124,13 @@ class Expression : public TreeHandle { friend class Tangent; friend class Trigonometry; friend class TrigonometryCheatTable; + friend class TwosComplement; friend class Unit; friend class UnitConvert; friend class VectorCross; friend class VectorDot; friend class VectorNorm; + friend class Xor; friend class AdditionNode; friend class DerivativeNode; @@ -119,6 +141,8 @@ class Expression : public TreeHandle { friend class FunctionNode; friend class IntegralNode; template + friend class BinaryOperationNode; + template friend class LogarithmNode; friend class MatrixNode; friend class NaperianLogarithmNode; diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 862e10e7384..1f94a2fc3e8 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -51,13 +51,21 @@ class ExpressionNode : public TreeNode { Cosine, Tangent, AbsoluteValue, + And, ArcCosine, ArcSine, ArcTangent, + BitClear, + BitFlip, + BitGet, + BitsClear, + BitsClearExplicit, + BitSet, BinomCDF, BinomialCoefficient, BinomPDF, Ceiling, + CeilingLog2, ComplexArgument, Conjugate, Derivative, @@ -87,22 +95,35 @@ class ExpressionNode : public TreeNode { NormCDF, NormCDF2, NormPDF, + Not, + NotExplicit, NthRoot, Opposite, + Or, Parenthesis, PermuteCoefficient, Product, Random, Randint, RealPart, + RotateLeft, + RotateLeftExplicit, + RotateRight, + RotateRightExplicit, Round, Sequence, + ShiftArithmeticRight, + ShiftArithmeticRightExplicit, + ShiftLogicLeft, + ShiftLogicRight, SignFunction, SquareRoot, Subtraction, Sum, + TwosComplement, VectorDot, VectorNorm, + Xor, /* When sorting the children of an expression, we assert that the following * nodes are at the end of the list : */ // - Units diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 1d27e50c508..2e6b7500d03 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -66,6 +66,7 @@ class Integer final : public TreeHandle { Decimal = 10, Hexadecimal = 16, }; + enum class LogicOperation { And, Or, Xor }; /* Constructors & Destructors */ static Integer BuildInteger(native_uint_t * digits, uint16_t numberOfDigits, bool negative, bool enableOverflow = false); Integer(native_int_t i = 0); @@ -154,6 +155,21 @@ class Integer final : public TreeHandle { static IntegerDivision Division(const Integer & numerator, const Integer & denominator); static Integer Power(const Integer & i, const Integer & j); static Integer Factorial(const Integer & i); + // logical operations + static Integer LogicalAndOrXor(const Integer &a, const Integer &b, LogicOperation operation, const Integer &num_bits = Integer(32)); + static Integer LogicalNot(const Integer &a, const Integer &num_bits = Integer(32)); + static Integer LogicalShift(const Integer &a, const Integer &shift, const Integer &num_bits = Integer(32)); + static Integer LogicalShiftRightArithmetic(const Integer &a, const Integer &shift, const Integer &num_bits = Integer(32)); + static Integer LogicalRotateRight(const Integer &a, const Integer &rotate, const Integer &num_bits = Integer(32)); + static Integer LogicalRotateLeft(const Integer &a, const Integer &rotate, const Integer &num_bits = Integer(32)); + static Integer LogicalBitsClear(const Integer &a, const Integer &b, const Integer &num_bits = Integer(32)); + static Integer LogicalBitGet(const Integer &a, const Integer &bit); + static Integer LogicalBitClear(const Integer &a, const Integer &bit); + static Integer LogicalBitSet(const Integer &a, const Integer &bit); + static Integer LogicalBitFlip(const Integer &a, const Integer &bit); + static Integer Truncate(const Integer &a, const Integer &num_bits); + static Integer TwosComplementToBits(const Integer &a, const Integer &num_bits); + static Integer CeilingLog2(const Integer &a); // Derived expression builder static Expression CreateMixedFraction(const Integer & num, const Integer & denom); diff --git a/poincare/include/poincare_nodes.h b/poincare/include/poincare_nodes.h index a3f8499953b..e6b2d55e0bd 100644 --- a/poincare/include/poincare_nodes.h +++ b/poincare/include/poincare_nodes.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/src/binary_operation.cpp b/poincare/src/binary_operation.cpp new file mode 100644 index 00000000000..02bd1f6b1a2 --- /dev/null +++ b/poincare/src/binary_operation.cpp @@ -0,0 +1,543 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace Poincare { + + constexpr Expression::FunctionHelper And::s_functionHelper; + constexpr Expression::FunctionHelper Or::s_functionHelper; + constexpr Expression::FunctionHelper Xor::s_functionHelper; + constexpr Expression::FunctionHelper Not::s_functionHelper; + constexpr Expression::FunctionHelper NotExplicit::s_functionHelper; + constexpr Expression::FunctionHelper BitClear::s_functionHelper; + constexpr Expression::FunctionHelper BitFlip::s_functionHelper; + constexpr Expression::FunctionHelper BitGet::s_functionHelper; + constexpr Expression::FunctionHelper BitSet::s_functionHelper; + constexpr Expression::FunctionHelper BitsClear::s_functionHelper; + constexpr Expression::FunctionHelper BitsClearExplicit::s_functionHelper; + constexpr Expression::FunctionHelper ShiftLogicLeft::s_functionHelper; + constexpr Expression::FunctionHelper ShiftLogicRight::s_functionHelper; + constexpr Expression::FunctionHelper ShiftArithmeticRight::s_functionHelper; + constexpr Expression::FunctionHelper ShiftArithmeticRightExplicit::s_functionHelper; + constexpr Expression::FunctionHelper RotateLeft::s_functionHelper; + constexpr Expression::FunctionHelper RotateLeftExplicit::s_functionHelper; + constexpr Expression::FunctionHelper RotateRight::s_functionHelper; + constexpr Expression::FunctionHelper RotateRightExplicit::s_functionHelper; + constexpr Expression::FunctionHelper TwosComplement::s_functionHelper; + constexpr Expression::FunctionHelper CeilingLog2::s_functionHelper; + + template<> int BinaryOperationNode<1>::numberOfChildren() const { return And::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<5>::numberOfChildren() const { return Or::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<9>::numberOfChildren() const { return Xor::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<13>::numberOfChildren() const { return Not::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<14>::numberOfChildren() const { return NotExplicit::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<15>::numberOfChildren() const { return BitClear::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<16>::numberOfChildren() const { return BitFlip::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<17>::numberOfChildren() const { return BitGet::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<18>::numberOfChildren() const { return BitSet::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<19>::numberOfChildren() const { return BitsClear::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<20>::numberOfChildren() const { return BitsClearExplicit::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<21>::numberOfChildren() const { return ShiftLogicLeft::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<23>::numberOfChildren() const { return ShiftLogicRight::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<25>::numberOfChildren() const { return ShiftArithmeticRight::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<26>::numberOfChildren() const { return ShiftArithmeticRightExplicit::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<27>::numberOfChildren() const { return RotateLeft::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<28>::numberOfChildren() const { return RotateLeftExplicit::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<29>::numberOfChildren() const { return RotateRight::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<30>::numberOfChildren() const { return RotateRightExplicit::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<31>::numberOfChildren() const { return TwosComplement::s_functionHelper.numberOfChildren(); } + template<> int BinaryOperationNode<32>::numberOfChildren() const { return CeilingLog2::s_functionHelper.numberOfChildren(); } + + template<> + Layout BinaryOperationNode<1>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, And::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<5>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, Or::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<9>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, Xor::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<13>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, Not::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<14>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, NotExplicit::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<15>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, BitClear::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<16>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, BitFlip::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<17>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, BitGet::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<18>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, BitSet::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<19>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, BitsClear::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<20>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, BitsClearExplicit::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<21>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, ShiftLogicLeft::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<23>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, ShiftLogicRight::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<25>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, ShiftArithmeticRight::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<26>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, ShiftArithmeticRightExplicit::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<27>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, RotateLeft::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<28>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, RotateLeftExplicit::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<29>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, RotateRight::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<30>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, RotateRightExplicit::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<31>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, TwosComplement::s_functionHelper.name()); + } + + template<> + Layout BinaryOperationNode<32>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, CeilingLog2::s_functionHelper.name()); + } + + template + int BinaryOperationNode::serialize(char *buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, + T == 32 ? CeilingLog2::s_functionHelper.name() : + T == 31 ? TwosComplement::s_functionHelper.name() : + T == 30 ? RotateRightExplicit::s_functionHelper.name() : + T == 29 ? RotateRight::s_functionHelper.name() : + T == 28 ? RotateLeftExplicit::s_functionHelper.name() : + T == 27 ? RotateLeft::s_functionHelper.name() : + T == 26 ? ShiftArithmeticRightExplicit::s_functionHelper.name() : + T == 25 ? ShiftArithmeticRight::s_functionHelper.name() : + T == 23 ? ShiftLogicRight::s_functionHelper.name() : + T == 21 ? ShiftLogicLeft::s_functionHelper.name() : + T == 20 ? BitsClearExplicit::s_functionHelper.name() : + T == 19 ? BitsClear::s_functionHelper.name() : + T == 18 ? BitSet::s_functionHelper.name() : + T == 17 ? BitGet::s_functionHelper.name() : + T == 16 ? BitFlip::s_functionHelper.name() : + T == 15 ? BitClear::s_functionHelper.name() : + T == 14 ? NotExplicit::s_functionHelper.name() : + T == 13 ? Not::s_functionHelper.name() : + T == 9 ? Xor::s_functionHelper.name() : + T == 5 ? Or::s_functionHelper.name() : + And::s_functionHelper.name() + ); + } + + template<> + Expression BinaryOperationNode<1>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return And(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<5>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return Or(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<9>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return Xor(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<13>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return Not(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<14>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return NotExplicit(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<15>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BitClear(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<16>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BitFlip(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<17>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BitGet(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<18>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BitSet(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<19>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BitsClear(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<20>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BitsClearExplicit(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<21>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return ShiftLogicLeft(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<23>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return ShiftLogicRight(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<25>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return ShiftArithmeticRight(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<26>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return ShiftArithmeticRightExplicit(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<27>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return RotateLeft(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<28>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return RotateLeftExplicit(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<29>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return RotateRight(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<30>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return RotateRightExplicit(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<31>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return TwosComplement(this).shallowReduce(reductionContext); + } + + template<> + Expression BinaryOperationNode<32>::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return CeilingLog2(this).shallowReduce(reductionContext); + } + + // Check to make sure the the expression is a positive integer + Integer getValidInteger(Expression a) { + if (a.type() != ExpressionNode::Type::Rational) { + return Integer(-1); + } + Rational ar = static_cast(a); + if (!ar.integerDenominator().isOne()) { + return Integer(-1); + } + return ar.signedIntegerNumerator(); + } + + Expression BinaryOperation::shallowReduceDirect(Expression & e, const ExpressionNode::Type t, ExpressionNode::ReductionContext reductionContext) { + { + e = e.defaultHandleUnitsInChildren(); + if (e.isUndefined()) { + return e; + } + } + Integer aq = getValidInteger(e.childAtIndex(0)); + Integer bq; + Integer cq; + Integer x; + + if(aq.isNegative() && t != ExpressionNode::Type::TwosComplement && t != ExpressionNode::Type::CeilingLog2) { + return Undefined::Builder(); + } + + if(t != ExpressionNode::Type::Not && t != ExpressionNode::Type::CeilingLog2) { + bq = getValidInteger(e.childAtIndex(1)); + if(bq.isNegative()) { + return Undefined::Builder(); + } + } + //used for logic shift (right) + Integer bq_neg = Integer::Multiplication(bq, Integer(-1)); + + switch(t) { + case ExpressionNode::Type::NotExplicit: + case ExpressionNode::Type::TwosComplement: + if(!bq.isLowerThan(Integer(__INT8_MAX__))) { + return Undefined::Builder(); + } + break; + default: + break; + } + + switch(t) { + case ExpressionNode::Type::BitsClearExplicit: + case ExpressionNode::Type::ShiftArithmeticRightExplicit: + case ExpressionNode::Type::RotateLeftExplicit: + case ExpressionNode::Type::RotateRightExplicit: + cq = getValidInteger(e.childAtIndex(2)); + if(cq.isMinusOne() || !cq.isLowerThan(Integer(__INT8_MAX__))) { + return Undefined::Builder(); + } + break; + default: + break; + } + + switch (t) { + case ExpressionNode::Type::And: + x = Integer::LogicalAndOrXor(aq, bq, Integer::LogicOperation::And); + break; + case ExpressionNode::Type::Or: + x = Integer::LogicalAndOrXor(aq, bq, Integer::LogicOperation::Or); + break; + case ExpressionNode::Type::Xor: + x = Integer::LogicalAndOrXor(aq, bq, Integer::LogicOperation::Xor); + break; + case ExpressionNode::Type::Not: + x = Integer::LogicalNot(aq); + break; + case ExpressionNode::Type::NotExplicit: + x = Integer::LogicalNot(aq, bq); + break; + case ExpressionNode::Type::BitClear: + x = Integer::LogicalBitClear(aq, bq); + break; + case ExpressionNode::Type::BitFlip: + x = Integer::LogicalBitFlip(aq, bq); + break; + case ExpressionNode::Type::BitGet: + x = Integer::LogicalBitGet(aq, bq); + break; + case ExpressionNode::Type::BitSet: + x = Integer::LogicalBitSet(aq, bq); + break; + case ExpressionNode::Type::BitsClear: + x = Integer::LogicalBitsClear(aq, bq); + break; + case ExpressionNode::Type::BitsClearExplicit: + x = Integer::LogicalBitsClear(aq, bq, cq); + break; + case ExpressionNode::Type::ShiftLogicLeft: + x = Integer::LogicalShift(aq, bq); + break; + case ExpressionNode::Type::ShiftLogicRight: + x = Integer::LogicalShift(aq, bq_neg); + break; + case ExpressionNode::Type::ShiftArithmeticRight: + x = Integer::LogicalShiftRightArithmetic(aq, bq); + break; + case ExpressionNode::Type::ShiftArithmeticRightExplicit: + x = Integer::LogicalShiftRightArithmetic(aq, bq, cq); + break; + case ExpressionNode::Type::RotateLeft: + x = Integer::LogicalRotateLeft(aq, bq); + break; + case ExpressionNode::Type::RotateLeftExplicit: + x = Integer::LogicalRotateLeft(aq, bq, cq); + break; + case ExpressionNode::Type::RotateRight: + x = Integer::LogicalRotateRight(aq, bq); + break; + case ExpressionNode::Type::RotateRightExplicit: + x = Integer::LogicalRotateRight(aq, bq, cq); + break; + case ExpressionNode::Type::TwosComplement: + x = Integer::TwosComplementToBits(aq, bq); + break; + case ExpressionNode::Type::CeilingLog2: + x = Integer::CeilingLog2(aq); + break; + default: + break; + } + Expression result = Rational::Builder(x); + e.replaceWithInPlace(result); + return result.shallowReduce(reductionContext); + } + + Expression And::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::And, reductionContext); + } + + Expression Or::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + Expression e = Expression::defaultShallowReduce(); + return BinaryOperation::shallowReduceDirect(e, ExpressionNode::Type::Or, reductionContext); + } + + Expression Xor::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::Xor, reductionContext); + } + + Expression Not::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::Not, reductionContext); + } + + Expression NotExplicit::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::NotExplicit, reductionContext); + } + + Expression BitClear::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::BitClear, reductionContext); + } + + Expression BitFlip::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::BitFlip, reductionContext); + } + + Expression BitGet::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::BitGet, reductionContext); + } + + Expression BitSet::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::BitSet, reductionContext); + } + Expression BitsClear::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::BitsClear, reductionContext); + } + + Expression BitsClearExplicit::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::BitsClearExplicit, reductionContext); + } + + Expression ShiftLogicLeft::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::ShiftLogicLeft, reductionContext); + } + + Expression ShiftLogicRight::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::ShiftLogicRight, reductionContext); + } + + Expression ShiftArithmeticRight::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::ShiftArithmeticRight, reductionContext); + } + + Expression ShiftArithmeticRightExplicit::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::ShiftArithmeticRightExplicit, reductionContext); + } + + Expression RotateLeft::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::RotateLeft, reductionContext); + } + + Expression RotateLeftExplicit::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::RotateLeftExplicit, reductionContext); + } + + Expression RotateRight::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::RotateRight, reductionContext); + } + + Expression RotateRightExplicit::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::RotateRightExplicit, reductionContext); + } + + Expression TwosComplement::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::TwosComplement, reductionContext); + } + + Expression CeilingLog2::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return BinaryOperation::shallowReduceDirect(*this, ExpressionNode::Type::CeilingLog2, reductionContext); + } + +template int BinaryOperationNode<1>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<2>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<3>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<4>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<5>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<6>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<7>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<8>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<9>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<10>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<11>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<12>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<13>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<14>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<15>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<16>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<17>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<18>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<19>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<20>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<21>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<22>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<23>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<24>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<25>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<26>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<27>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<28>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<29>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<30>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<31>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; +template int BinaryOperationNode<32>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const; + +} // namespace Poincare \ No newline at end of file diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 4c066e6c1eb..10c117bbc54 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -272,7 +272,7 @@ bool Expression::isDefinedCosineOrSine(Context * context, Preferences::ComplexFo } bool Expression::isBasedIntegerCappedBy(const char * stringInteger) const { - return type() == ExpressionNode::Type::BasedInteger && (Integer::NaturalOrder(convert().integer(), Integer(stringInteger)) < 0); + return type() == ExpressionNode::Type::BasedInteger || (type() == ExpressionNode::Type::Opposite && childAtIndex(0).type() == ExpressionNode::Type::BasedInteger); // && (Integer::NaturalOrder(convert().integer(), Integer(stringInteger)) < 0); } bool Expression::isDivisionOfIntegers() const { diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index fc67dda6609..c4fadbc4fe5 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -22,6 +22,8 @@ extern "C" { } #include +#define __INT8_MAX_MINUS_1__ 0x7E + namespace Poincare { /* To compute operations between Integers, we need an array where to store the @@ -452,6 +454,407 @@ Integer Integer::Factorial(const Integer & i) { return result; } +Integer Integer::LogicalAndOrXor(const Integer &a, const Integer &b, LogicOperation operation, const Integer &num_bits) +{ + assert(!a.isNegative()); + assert(!b.isNegative()); + assert(num_bits.isLowerThan(Integer(__INT8_MAX__))); + if (a.isOverflow() || b.isOverflow()) + { + return Overflow(false); + } + + uint8_t digits = std::max(a.numberOfDigits(), b.numberOfDigits()); + for (size_t i = 0; i < digits; i++) + { + + native_uint_t abits = a.numberOfDigits() > i ? a.digit(i) : 0; + native_uint_t bbits = b.numberOfDigits() > i ? b.digit(i) : 0; + switch(operation) { + case LogicOperation::And: s_workingBuffer[i] = abits & bbits; break; + case LogicOperation::Or: s_workingBuffer[i] = abits | bbits; break; + case LogicOperation::Xor: s_workingBuffer[i] = abits ^ bbits; break; + } + } + + Integer uint_final = Truncate(BuildInteger(s_workingBuffer, digits, false), num_bits); + return uint_final; +} + +Integer Integer::LogicalNot(const Integer &a, const Integer &num_bits) +{ + assert(!a.isNegative()); + assert(num_bits.isLowerThan(Integer(__INT8_MAX__))); + if (a.isOverflow()) + { + return Overflow(false); + } + + uint8_t digits = std::max(a.numberOfDigits(), (uint8_t)std::ceil(num_bits.extractedInt() / 32.0)); + for (size_t i = 0; i < digits; i++) + { + native_uint_t abits = a.numberOfDigits() > i ? a.digit(i) : 0; + s_workingBuffer[i] = ~abits; + } + + Integer uint_final = Truncate(BuildInteger(s_workingBuffer, digits, false), num_bits); + return uint_final; +} + +Integer Integer::LogicalShift(const Integer &a, const Integer &shift, const Integer &num_bits) +{ + assert(!a.isNegative()); + assert(num_bits.isLowerThan(Integer(__INT8_MAX__))); + if (a.isOverflow() || shift.isOverflow()) + { + return Overflow(false); + } + if (a.isZero()) + { + return a; + } + + int8_t points = shift.extractedInt(); + Integer uint_final = Truncate(a, num_bits); + if (uint_final.isZero()) + { + return uint_final; + } + + // Shift Left + while (points > 0) + { + uint8_t power = (points >= 31) ? 31 : points; + //multiplyByPowerOf2 prohibits powers greater than 31... + uint_final = uint_final.multiplyByPowerOf2(power); + points -= power; + } + //Shift Right + while (points < 0) + { + uint8_t power = (-points >= 31) ? 31 : -points; + //multiplyByPowerOf2 prohibits powers greater than 31... + uint_final = uint_final.divideByPowerOf2(power); + points += power; + } + + return Truncate(uint_final, num_bits); +} + +Integer Integer::LogicalShiftRightArithmetic(const Integer &a, const Integer &shift, const Integer &num_bits) +{ + assert(!a.isNegative()); + assert(!shift.isNegative()); + assert(num_bits.isLowerThan(Integer(__INT8_MAX__))); + if (a.isOverflow() || shift.isOverflow()) + { + return Overflow(false); + } + + Integer uint_final = Truncate(a, num_bits); // Make sure input is at the correct precision + if (uint_final.isZero() || shift.isZero()) + { + return uint_final; + } + + Integer num_bits_minus_1 = Subtraction(num_bits, Integer(1)); + Integer sign = LogicalBitGet(uint_final, num_bits_minus_1); + uint8_t points = shift.extractedInt(); + uint8_t power; + while (points > 0) + { + //multiplyByPowerOf2 prohibits powers greater than 31... + power = (points >= 31) ? 31 : points; + uint_final = uint_final.divideByPowerOf2(power); + points -= power; + } + + //only bother sign extending if the sign is negative + if (!sign.isZero()) + { + points = shift.extractedInt(); + Integer extend = Integer(1); + while (points > 0) + { + power = (points >= 31) ? 31 : points; + extend = extend.multiplyByPowerOf2(power); + points -= power; + } + extend = Subtraction(extend, Integer(1)); + + points = num_bits.extractedInt() - shift.extractedInt(); + while (points > 0) + { + power = (points >= 31) ? 31 : points; + extend = extend.multiplyByPowerOf2(power); + points -= power; + } + + uint_final = Addition(uint_final, extend); + } + + return Truncate(uint_final, num_bits); +} + +Integer Integer::LogicalRotateRight(const Integer &a, const Integer &rotate, const Integer &num_bits) +{ + assert(!a.isNegative()); + assert(!rotate.isNegative()); + assert(num_bits.isLowerThan(Integer(__INT8_MAX__))); + assert(rotate.isLowerThan(num_bits)); + if (a.isOverflow() || rotate.isOverflow()) + { + return Overflow(false); + } + + Integer uint_final = Truncate(a, num_bits); // Make sure input is at the correct precision + if (uint_final.isZero() || rotate.isZero()) + { + return uint_final; + } + + Integer num_bits_plus_1 = Addition(num_bits, Integer(1)); + Integer rotate_mask = LogicalShift(Integer(1), rotate, num_bits_plus_1); + rotate_mask = Subtraction(rotate_mask, Integer(1)); + Integer rotate_word = LogicalAndOrXor(uint_final, rotate_mask, Integer::LogicOperation::And, num_bits); + Integer rotate_neg = multiplication(rotate, Integer(-1)); + uint_final = LogicalShift(uint_final, rotate_neg, num_bits); + + //only bother adding if the rotate word is non-zero + if (!rotate_word.isZero()) + { + Integer num_bits_minus_rotate = Subtraction(num_bits, rotate); + rotate_word = LogicalShift(rotate_word, num_bits_minus_rotate, num_bits); + uint_final = Addition(uint_final, rotate_word); + } + + return Truncate(uint_final, num_bits); +} + +Integer Integer::LogicalRotateLeft(const Integer &a, const Integer &rotate, const Integer &num_bits) +{ + assert(!a.isNegative()); + assert(!rotate.isNegative()); + assert(num_bits.isLowerThan(Integer(__INT8_MAX__))); + assert(rotate.isLowerThan(num_bits)); + if (a.isOverflow() || rotate.isOverflow()) + { + return Overflow(false); + } + + Integer uint_final = Truncate(a, num_bits); // Make sure input is at the correct precision + if (uint_final.isZero() || rotate.isZero()) + { + return uint_final; + } + + Integer num_bits_plus_1 = Addition(num_bits, Integer(1)); + Integer rotate_mask = LogicalShift(Integer(1), rotate, num_bits_plus_1); + rotate_mask = Subtraction(rotate_mask, Integer(1)); + Integer num_bits_minus_rotate = Subtraction(num_bits, rotate); + rotate_mask = LogicalShift(rotate_mask, num_bits_minus_rotate, num_bits); + Integer rotate_word = LogicalAndOrXor(uint_final, rotate_mask, Integer::LogicOperation::And, num_bits); + Integer num_bits_minus_rotate_neg = multiplication(num_bits_minus_rotate, Integer(-1)); + rotate_word = LogicalShift(rotate_word, num_bits_minus_rotate_neg, num_bits); + + uint_final = LogicalShift(uint_final, rotate, num_bits); + + uint_final = Addition(uint_final, rotate_word); + + return Truncate(uint_final, num_bits); +} + +Integer Integer::LogicalBitsClear(const Integer &a, const Integer &b, const Integer &num_bits) +{ + //aka. BIC instruction (a & ~b) + assert(!a.isNegative()); + assert(!b.isNegative()); + assert(num_bits.isLowerThan(Integer(__INT8_MAX__))); + if (a.isOverflow() || b.isOverflow()) + { + return Overflow(false); + } + + Integer b_invert = LogicalNot(b, num_bits); + Integer bic = LogicalAndOrXor(a, b_invert, Integer::LogicOperation::And, num_bits); + + return Truncate(bic, num_bits); +} + +Integer Integer::LogicalBitGet(const Integer &a, const Integer &bit) +{ + // (a >> bit) & 1, return the bit-th bit of a + assert(!a.isNegative()); + assert(bit.isLowerThan(Integer(__INT8_MAX__))); + if (a.isOverflow()) + { + return Overflow(false); + } + Integer bit_neg = multiplication(bit, Integer(-1)); + Integer shifted = LogicalShift(a, bit_neg, Integer(__INT8_MAX_MINUS_1__)); + return LogicalAndOrXor(shifted, Integer(1), Integer::LogicOperation::And, Integer(__INT8_MAX_MINUS_1__)); +} + +Integer Integer::LogicalBitClear(const Integer &a, const Integer &bit) +{ + // x = a & ~(1 << bit), clear tha bit-th bit of a; + assert(!a.isNegative()); + assert(bit.isLowerThan(Integer(__INT8_MAX__))); + if (a.isOverflow()) + { + return Overflow(false); + } + + Integer shifted = LogicalShift(Integer(1), bit, Integer(__INT8_MAX_MINUS_1__)); + shifted = LogicalNot(shifted, Integer(__INT8_MAX_MINUS_1__)); + return LogicalAndOrXor(a, shifted, Integer::LogicOperation::And, Integer(__INT8_MAX_MINUS_1__)); +} + +Integer Integer::LogicalBitSet(const Integer &a, const Integer &bit) +{ + // x = a | (1 << bit), clear tha bit-th bit of a; + assert(!a.isNegative()); + assert(bit.isLowerThan(Integer(__INT8_MAX__))); + if (a.isOverflow()) + { + return Overflow(false); + } + + Integer shifted = LogicalShift(Integer(1), bit, Integer(__INT8_MAX_MINUS_1__)); + return LogicalAndOrXor(a, shifted, Integer::LogicOperation::Or, Integer(__INT8_MAX_MINUS_1__)); +} + +Integer Integer::LogicalBitFlip(const Integer &a, const Integer &bit) +{ + // x = a ^ (1 << bit), flip the bit-th bit of a. + assert(!a.isNegative()); + assert(bit.isLowerThan(Integer(__INT8_MAX__))); + if (a.isOverflow()) + { + return Overflow(false); + } + + Integer shifted = LogicalShift(Integer(1), bit, Integer(__INT8_MAX_MINUS_1__)); + return LogicalAndOrXor(a, shifted, Integer::LogicOperation::Xor, Integer(__INT8_MAX_MINUS_1__)); +} + +Integer Integer::Truncate(const Integer &a, const Integer &num_bits) +{ + if (a.isZero() || num_bits.isZero()) + { + return Integer(0); + } + assert(!num_bits.isNegative()); + + native_uint_t n = num_bits.extractedInt(); + + uint8_t num_digits = std::min((uint8_t)a.numberOfDigits(), (uint8_t)(std::ceil(n / 32.0))); + + for (size_t i = 0; i < (uint8_t)(std::ceil(n / 32.0)); i++) + { + s_workingBuffer[i] = a.numberOfDigits() > i ? a.digit(i) : 0; + } + + for (uint16_t i = num_digits * 32 - 1; i >= n; i--) + { + bool bit_i = (s_workingBuffer[i / 32] & (1 << i)) >> i; + if (bit_i) + { + s_workingBuffer[i / 32] = s_workingBuffer[i / 32] ^ (1 << i); //flip bit + } + } + + // clear all zero-valued digits + if (num_digits > 1) + { + bool msb_cleared = true; + for (uint16_t i = num_digits - 1; i > 0; i--) + { + if (s_workingBuffer[i] == 0 && msb_cleared) + { + num_digits--; + msb_cleared = true; + } else { + msb_cleared = false; + } + } + } + + Integer uint_final = BuildInteger(s_workingBuffer, num_digits, false); + + return uint_final; +} + +Integer Integer::TwosComplementToBits(const Integer &a, const Integer &num_bits) +{ + if (a.isZero() || num_bits.isZero()) + { + return Integer(0); + } + assert(!num_bits.isNegative()); + + native_uint_t points = num_bits.extractedInt(); + + //convert to signed bits if needed: + if (a.isNegative()) + { + Integer buffer = usum(Integer(0), a, true); + Integer num_bits_in_a = Integer(32*buffer.numberOfDigits()); + Integer msb_pointer = Subtraction(num_bits_in_a, Integer(1)); + Integer sign = LogicalBitGet(buffer, msb_pointer); + if(sign.isOne() && num_bits_in_a.isLowerThan(num_bits)) { + //sign extend + for (size_t i = 0; i < (uint8_t)(std::ceil(points / 32.0)); i++) + { + s_workingBuffer[i] = buffer.numberOfDigits() > i ? buffer.digit(i) : 4294967295; //4294967295 = all 1's + } + Integer uint_final = BuildInteger(s_workingBuffer, (uint8_t)(std::ceil(points / 32.0)), false); + return Truncate(uint_final, num_bits); + } + return Truncate(buffer, num_bits); + } + + //a is positive + Integer msb_pointer = Subtraction(num_bits, Integer(1)); + Integer a_truncated = Truncate(a, num_bits); + Integer sign = LogicalBitGet(a_truncated, msb_pointer); + Integer num_bits_plus_1 = Addition(num_bits, Integer(1)); + if (sign.isOne()) + { + // flip bits back to unsigned from two's comp + Integer bias = LogicalShift(Integer(1), num_bits, num_bits_plus_1); + bias.setNegative(true); + Integer a_negative = Addition(a_truncated, bias); + return a_negative; + } + + // a is positive and the msb is 0 + return a; +} + +Integer Integer::CeilingLog2(const Integer &a) +{ + if (a.isZero()) + { + return Integer(0); + } + uint8_t bits = 0; + Integer buffer; + if(a.isNegative()) { + Integer x2 = Integer::Multiplication(a,2); + x2.setNegative(false); + buffer = Integer::Subtraction(x2, Integer(1)); + } else { + buffer = a; + } + while(!buffer.isZero()) { + bits++; + buffer = Integer::LogicalShift(buffer,Integer(-1)); + } + Integer num_bits_in_a = Integer(bits); + return num_bits_in_a; +} + Integer Integer::addition(const Integer & a, const Integer & b, bool inverseBNegative, bool oneDigitOverflow) { bool bNegative = (inverseBNegative ? !b.m_negative : b.m_negative); if (a.m_negative == bNegative) { diff --git a/poincare/src/parsing/parser.h b/poincare/src/parsing/parser.h index f68a6a9a5f8..8a457c98a00 100644 --- a/poincare/src/parsing/parser.h +++ b/poincare/src/parsing/parser.h @@ -98,15 +98,23 @@ class Parser { &AbsoluteValue::s_functionHelper, &ArcCosine::s_functionHelper, &HyperbolicArcCosine::s_functionHelper, + &And::s_functionHelper, &ComplexArgument::s_functionHelper, &ArcSine::s_functionHelper, &HyperbolicArcSine::s_functionHelper, &ArcTangent::s_functionHelper, &HyperbolicArcTangent::s_functionHelper, + &BitClear::s_functionHelper, + &BitFlip::s_functionHelper, + &BitsClear::s_functionHelper, + &BitsClearExplicit::s_functionHelper, &BinomCDF::s_functionHelper, &BinomialCoefficient::s_functionHelper, &BinomPDF::s_functionHelper, + &BitGet::s_functionHelper, + &BitSet::s_functionHelper, &Ceiling::s_functionHelper, + &CeilingLog2::s_functionHelper, &ConfidenceInterval::s_functionHelper, &Conjugate::s_functionHelper, &Cosine::s_functionHelper, @@ -135,6 +143,9 @@ class Parser { &NormCDF::s_functionHelper, &NormCDF2::s_functionHelper, &NormPDF::s_functionHelper, + &Not::s_functionHelper, + &NotExplicit::s_functionHelper, + &Or::s_functionHelper, &PermuteCoefficient::s_functionHelper, &SimplePredictionInterval::s_functionHelper, &PredictionInterval::s_functionHelper, @@ -145,17 +156,27 @@ class Parser { &RealPart::s_functionHelper, &MatrixRowEchelonForm::s_functionHelper, &DivisionRemainder::s_functionHelper, + &RotateLeft::s_functionHelper, + &RotateLeftExplicit::s_functionHelper, &NthRoot::s_functionHelper, + &RotateRight::s_functionHelper, + &RotateRightExplicit::s_functionHelper, &Round::s_functionHelper, &MatrixReducedRowEchelonForm::s_functionHelper, &SignFunction::s_functionHelper, &Sine::s_functionHelper, &HyperbolicSine::s_functionHelper, + &ShiftLogicLeft::s_functionHelper, + &ShiftArithmeticRight::s_functionHelper, + &ShiftArithmeticRightExplicit::s_functionHelper, + &ShiftLogicRight::s_functionHelper, &Sum::s_functionHelper, &Tangent::s_functionHelper, &HyperbolicTangent::s_functionHelper, + &TwosComplement::s_functionHelper, &MatrixTrace::s_functionHelper, &MatrixTranspose::s_functionHelper, + &Xor::s_functionHelper, &SquareRoot::s_functionHelper }; static constexpr const Expression::FunctionHelper * const * s_reservedFunctionsUpperBound = s_reservedFunctions + (sizeof(s_reservedFunctions)/sizeof(Expression::FunctionHelper *)); diff --git a/poincare/src/tree_handle.cpp b/poincare/src/tree_handle.cpp index 057a237dbec..01e63a2d6c2 100644 --- a/poincare/src/tree_handle.cpp +++ b/poincare/src/tree_handle.cpp @@ -280,14 +280,22 @@ void TreeHandle::release(uint16_t identifier) { template AbsoluteValue TreeHandle::FixedArityBuilder(const Tuple &); template AbsoluteValueLayout TreeHandle::FixedArityBuilder(const Tuple &); template Addition TreeHandle::NAryBuilder(const Tuple &); +template And TreeHandle::FixedArityBuilder >(const Tuple &); template ArcCosine TreeHandle::FixedArityBuilder(const Tuple &); template ArcSine TreeHandle::FixedArityBuilder(const Tuple &); template ArcTangent TreeHandle::FixedArityBuilder(const Tuple &); +template BitClear TreeHandle::FixedArityBuilder >(const Tuple &); +template BitFlip TreeHandle::FixedArityBuilder >(const Tuple &); +template BitGet TreeHandle::FixedArityBuilder >(const Tuple &); +template BitsClear TreeHandle::FixedArityBuilder >(const Tuple &); +template BitsClearExplicit TreeHandle::FixedArityBuilder >(const Tuple &); +template BitSet TreeHandle::FixedArityBuilder >(const Tuple &); template BinomCDF TreeHandle::FixedArityBuilder(const Tuple &); template BinomialCoefficient TreeHandle::FixedArityBuilder(const Tuple &); template BinomialCoefficientLayout TreeHandle::FixedArityBuilder(const Tuple &); template BinomPDF TreeHandle::FixedArityBuilder(const Tuple &); template Ceiling TreeHandle::FixedArityBuilder(const Tuple &); +template CeilingLog2 TreeHandle::FixedArityBuilder >(const Tuple &); template CeilingLayout TreeHandle::FixedArityBuilder(const Tuple &); template CommonLogarithm TreeHandle::FixedArityBuilder >(const Tuple &); template ComplexArgument TreeHandle::FixedArityBuilder(const Tuple &); @@ -345,8 +353,11 @@ template NaperianLogarithm TreeHandle::FixedArityBuilder(const Tuple &); template NormCDF2 TreeHandle::FixedArityBuilder(const Tuple &); template NormPDF TreeHandle::FixedArityBuilder(const Tuple &); +template Not TreeHandle::FixedArityBuilder >(const Tuple &); +template NotExplicit TreeHandle::FixedArityBuilder >(const Tuple &); template NthRoot TreeHandle::FixedArityBuilder(const Tuple &); template Opposite TreeHandle::FixedArityBuilder(const Tuple &); +template Or TreeHandle::FixedArityBuilder >(const Tuple &); template Parenthesis TreeHandle::FixedArityBuilder(const Tuple &); template PermuteCoefficient TreeHandle::FixedArityBuilder(const Tuple &); template Power TreeHandle::FixedArityBuilder(const Tuple &); @@ -358,7 +369,15 @@ template Random TreeHandle::FixedArityBuilder(const Tuple &) template RealPart TreeHandle::FixedArityBuilder(const Tuple &); template RightParenthesisLayout TreeHandle::FixedArityBuilder(const Tuple &); template RightSquareBracketLayout TreeHandle::FixedArityBuilder(const Tuple &); +template RotateLeft TreeHandle::FixedArityBuilder >(const Tuple &); +template RotateLeftExplicit TreeHandle::FixedArityBuilder >(const Tuple &); +template RotateRight TreeHandle::FixedArityBuilder >(const Tuple &); +template RotateRightExplicit TreeHandle::FixedArityBuilder >(const Tuple &); template Round TreeHandle::FixedArityBuilder(const Tuple &); +template ShiftArithmeticRight TreeHandle::FixedArityBuilder >(const Tuple &); +template ShiftArithmeticRightExplicit TreeHandle::FixedArityBuilder >(const Tuple &); +template ShiftLogicLeft TreeHandle::FixedArityBuilder >(const Tuple &); +template ShiftLogicRight TreeHandle::FixedArityBuilder >(const Tuple &); template SignFunction TreeHandle::FixedArityBuilder(const Tuple &); template SimplePredictionInterval TreeHandle::FixedArityBuilder(const Tuple &); template Sine TreeHandle::FixedArityBuilder(const Tuple &); @@ -377,5 +396,6 @@ template VectorNorm TreeHandle::FixedArityBuilder(co template VectorNormLayout TreeHandle::FixedArityBuilder(const Tuple &); template VectorLayout TreeHandle::FixedArityBuilder(const Tuple &); template MatrixLayout TreeHandle::NAryBuilder(const Tuple &); - +template TwosComplement TreeHandle::FixedArityBuilder >(const Tuple &); +template Xor TreeHandle::FixedArityBuilder >(const Tuple &); } diff --git a/poincare/test/logic.cpp b/poincare/test/logic.cpp new file mode 100644 index 00000000000..2a8109fc627 --- /dev/null +++ b/poincare/test/logic.cpp @@ -0,0 +1,402 @@ +#include "helper.h" + +using namespace Poincare; + +static inline void assert_equal(const Integer i, const Integer j) +{ + quiz_assert(Integer::NaturalOrder(i, j) == 0); +} + +QUIZ_CASE(poincare_logic_xor_compare) +{ + Integer hFFFF_FFFF = Integer("4294967295"); + Integer h1_FFFF_FFFF = Integer("8589934591"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_0000_0000_FFFF = Integer("18446462598732906495"); + assert_equal(Integer::LogicalAndOrXor(Integer(15), Integer(1), Integer::LogicOperation::Xor), Integer(14)); + assert_equal(Integer::LogicalAndOrXor(Integer(15), Integer(0), Integer::LogicOperation::Xor), Integer(15)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), Integer(15), Integer::LogicOperation::Xor), Integer(15)); + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF, Integer(0), Integer::LogicOperation::Xor), hFFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(Integer(0), hFFFF_FFFF, Integer::LogicOperation::Xor), hFFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Xor), hFFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(Integer(0), Integer(0), Integer::LogicOperation::Xor), Integer(0)); + //explicit num_bits + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF, h1_FFFF_FFFF, Integer::LogicOperation::Xor, Integer(33)), h1_0000_0000); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Xor, Integer(33)), h1_FFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Xor, Integer(15)), Integer(32767)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Xor, Integer(8)), Integer(255)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Xor, Integer(4)), Integer(15)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Xor, Integer(1)), Integer(1)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Xor, Integer(0)), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF_FFFF_FFFF, h0000_FFFF_FFFF_0000, Integer::LogicOperation::Xor, Integer(64)), hFFFF_0000_0000_FFFF); + assert_equal(Integer::LogicalAndOrXor(h0000_FFFF_FFFF_0000, hFFFF_FFFF_FFFF_FFFF, Integer::LogicOperation::Xor, Integer(65)), hFFFF_0000_0000_FFFF); +} + +QUIZ_CASE(poincare_logic_or_compare) +{ + Integer hFFFF_FFFF = Integer("4294967295"); + Integer h1_FFFF_FFFF = Integer("8589934591"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_0000_0000_FFFF = Integer("18446462598732906495"); + assert_equal(Integer::LogicalAndOrXor(Integer(15), Integer(1), Integer::LogicOperation::Or), Integer(15)); + assert_equal(Integer::LogicalAndOrXor(Integer(15), Integer(0), Integer::LogicOperation::Or), Integer(15)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), Integer(15), Integer::LogicOperation::Or), Integer(15)); + assert_equal(Integer::LogicalAndOrXor(Integer(15), Integer(15), Integer::LogicOperation::Or), Integer(15)); + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF, Integer(0), Integer::LogicOperation::Or), hFFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(Integer(0), hFFFF_FFFF, Integer::LogicOperation::Or), hFFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF, hFFFF_FFFF, Integer::LogicOperation::Or), hFFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Or), hFFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(Integer(0), Integer(0), Integer::LogicOperation::Or), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_0000_0000, Integer::LogicOperation::Or), Integer(0)); + //explicit num_bits + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF, h1_FFFF_FFFF, Integer::LogicOperation::Or, Integer(33)), h1_FFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_0000_0000, Integer::LogicOperation::Or, Integer(33)), h1_0000_0000); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Or, Integer(15)), Integer(32767)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Or, Integer(8)), Integer(255)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Or, Integer(4)), Integer(15)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Or, Integer(1)), Integer(1)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::Or, Integer(0)), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF_FFFF_FFFF, h0000_FFFF_FFFF_0000, Integer::LogicOperation::Or, Integer(64)), hFFFF_FFFF_FFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(h0000_FFFF_FFFF_0000, hFFFF_0000_0000_FFFF, Integer::LogicOperation::Or, Integer(65)), hFFFF_FFFF_FFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(h0000_FFFF_FFFF_0000, Integer(0), Integer::LogicOperation::Or, Integer(65)), h0000_FFFF_FFFF_0000); +} + +QUIZ_CASE(poincare_logic_and_compare) +{ + Integer hFFFF_FFFF = Integer("4294967295"); + Integer h1_FFFF_FFFF = Integer("8589934591"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_0000_0000_FFFF = Integer("18446462598732906495"); + assert_equal(Integer::LogicalAndOrXor(Integer(15), Integer(1), Integer::LogicOperation::And), Integer(1)); + assert_equal(Integer::LogicalAndOrXor(Integer(15), Integer(0), Integer::LogicOperation::And), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), Integer(15), Integer::LogicOperation::And), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(Integer(15), Integer(15), Integer::LogicOperation::And), Integer(15)); + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF, Integer(0), Integer::LogicOperation::And), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), hFFFF_FFFF, Integer::LogicOperation::And), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF, hFFFF_FFFF, Integer::LogicOperation::And), hFFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_FFFF_FFFF, Integer::LogicOperation::And), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(h1_FFFF_FFFF, h1_FFFF_FFFF, Integer::LogicOperation::And), hFFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(Integer(0), Integer(0), Integer::LogicOperation::And), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_0000_0000, Integer::LogicOperation::And), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(h1_0000_0000, h1_0000_0000, Integer::LogicOperation::And), Integer(0)); + //explicit num_bits + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF, h1_FFFF_FFFF, Integer::LogicOperation::And, Integer(33)), hFFFF_FFFF); + assert_equal(Integer::LogicalAndOrXor(Integer(0), h1_0000_0000, Integer::LogicOperation::And, Integer(33)), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(h1_0000_0000, h1_0000_0000, Integer::LogicOperation::And, Integer(33)), h1_0000_0000); + assert_equal(Integer::LogicalAndOrXor(h1_0000_0000, h1_0000_0000, Integer::LogicOperation::And, Integer(34)), h1_0000_0000); + assert_equal(Integer::LogicalAndOrXor(h1_FFFF_FFFF, h1_FFFF_FFFF, Integer::LogicOperation::And, Integer(15)), Integer(32767)); + assert_equal(Integer::LogicalAndOrXor(h1_FFFF_FFFF, h1_FFFF_FFFF, Integer::LogicOperation::And, Integer(8)), Integer(255)); + assert_equal(Integer::LogicalAndOrXor(h1_FFFF_FFFF, h1_FFFF_FFFF, Integer::LogicOperation::And, Integer(4)), Integer(15)); + assert_equal(Integer::LogicalAndOrXor(h1_FFFF_FFFF, h1_FFFF_FFFF, Integer::LogicOperation::And, Integer(1)), Integer(1)); + assert_equal(Integer::LogicalAndOrXor(h1_FFFF_FFFF, h1_FFFF_FFFF, Integer::LogicOperation::And, Integer(0)), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF_FFFF_FFFF, h0000_FFFF_FFFF_0000, Integer::LogicOperation::And, Integer(64)), h0000_FFFF_FFFF_0000); + assert_equal(Integer::LogicalAndOrXor(hFFFF_FFFF_FFFF_FFFF, h0000_FFFF_FFFF_0000, Integer::LogicOperation::And, Integer(90)), h0000_FFFF_FFFF_0000); + assert_equal(Integer::LogicalAndOrXor(h0000_FFFF_FFFF_0000, hFFFF_0000_0000_FFFF, Integer::LogicOperation::And, Integer(65)), Integer(0)); + assert_equal(Integer::LogicalAndOrXor(h0000_FFFF_FFFF_0000, hFFFF_FFFF_FFFF_FFFF, Integer::LogicOperation::And, Integer(65)), h0000_FFFF_FFFF_0000); +} + +QUIZ_CASE(poincare_logic_not_compare) +{ + Integer hFFFF_FFFF = Integer("4294967295"); + Integer h1_FFFF_FFFF = Integer("8589934591"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_0000_0000_FFFF = Integer("18446462598732906495"); + assert_equal(Integer::LogicalNot(hFFFF_FFFF), Integer(0)); + assert_equal(Integer::LogicalNot(Integer(0)), hFFFF_FFFF); + assert_equal(Integer::LogicalNot(h1_FFFF_FFFF), Integer(0)); + assert_equal(Integer::LogicalNot(h1_0000_0000), hFFFF_FFFF); + //explicit num_bits + assert_equal(Integer::LogicalNot(hFFFF_FFFF, Integer(33)), h1_0000_0000); + assert_equal(Integer::LogicalNot(Integer(0), Integer(33)), h1_FFFF_FFFF); + assert_equal(Integer::LogicalNot(h1_0000_0000, Integer(33)), hFFFF_FFFF); + assert_equal(Integer::LogicalNot(h1_0000_0000, Integer(15)), Integer(32767)); + assert_equal(Integer::LogicalNot(h1_0000_0000, Integer(8)), Integer(255)); + assert_equal(Integer::LogicalNot(h1_0000_0000, Integer(4)), Integer(15)); + assert_equal(Integer::LogicalNot(h1_0000_0000, Integer(1)), Integer(1)); + assert_equal(Integer::LogicalNot(h1_0000_0000, Integer(0)), Integer(0)); + assert_equal(Integer::LogicalNot(h0000_FFFF_FFFF_0000, Integer(64)), hFFFF_0000_0000_FFFF); + assert_equal(Integer::LogicalNot(hFFFF_0000_0000_FFFF, Integer(64)), h0000_FFFF_FFFF_0000); + assert_equal(Integer::LogicalNot(hFFFF_FFFF_FFFF_FFFF, Integer(64)), Integer(0)); + assert_equal(Integer::LogicalNot(hFFFF_FFFF_FFFF_FFFF, Integer(51)), Integer(0)); + assert_equal(Integer::LogicalNot(Integer(0), Integer(64)), hFFFF_FFFF_FFFF_FFFF); +} + +QUIZ_CASE(poincare_logic_sll_compare) +{ + Integer hFFFF_FFFF = Integer("4294967295"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_FFFF_0000_0000 = Integer("18446744069414584320"); + Integer h1_0000_0000_0000_0000 = Integer("18446744073709551616"); + assert_equal(Integer::LogicalShift(hFFFF_FFFF, Integer(0)), hFFFF_FFFF); + assert_equal(Integer::LogicalShift(Integer(0), Integer(6)), Integer(0)); + assert_equal(Integer::LogicalShift(Integer(0), Integer(36)), Integer(0)); + assert_equal(Integer::LogicalShift(h1_0000_0000, Integer(32)), Integer(0)); + //explicit num_bits + assert_equal(Integer::LogicalShift(Integer(1), Integer(32), Integer(33)), h1_0000_0000); + assert_equal(Integer::LogicalShift(h0000_FFFF_FFFF_0000, Integer(16), Integer(64)), hFFFF_FFFF_0000_0000); + assert_equal(Integer::LogicalShift(h0000_FFFF_FFFF_0000, Integer(16), Integer(65)), hFFFF_FFFF_0000_0000); + assert_equal(Integer::LogicalShift(Integer(1), Integer(64), Integer(65)), h1_0000_0000_0000_0000); +} + +QUIZ_CASE(poincare_logic_srl_compare) +{ + Integer hFFFF = Integer("65535"); + Integer hFFFF_FFFF = Integer("4294967295"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_FFFF_0000_0000 = Integer("18446744069414584320"); + assert_equal(Integer::LogicalShift(hFFFF_FFFF, Integer(-0)), hFFFF_FFFF); + assert_equal(Integer::LogicalShift(Integer(0), Integer(-6)), Integer(0)); + assert_equal(Integer::LogicalShift(Integer(0), Integer(-36)), Integer(0)); + assert_equal(Integer::LogicalShift(h1_0000_0000, Integer(-32)), Integer(0)); + assert_equal(Integer::LogicalShift(hFFFF_FFFF, Integer(-32)), Integer(0)); + assert_equal(Integer::LogicalShift(hFFFF_FFFF, Integer(-31)), Integer(1)); + assert_equal(Integer::LogicalShift(hFFFF_FFFF, Integer(-30)), Integer(3)); + //explicit num_bits + assert_equal(Integer::LogicalShift(h0000_FFFF_FFFF_0000, Integer(-32), Integer(33)), Integer(1)); + assert_equal(Integer::LogicalShift(h0000_FFFF_FFFF_0000, Integer(-32), Integer(64)), hFFFF); + assert_equal(Integer::LogicalShift(h0000_FFFF_FFFF_0000, Integer(-32), Integer(66)), hFFFF); +} + +QUIZ_CASE(poincare_logic_sra_compare) +{ + Integer hFFFF = Integer("65535"); + Integer hFFFF_FFFF = Integer("4294967295"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_FFFF_0000_0000 = Integer("18446744069414584320"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + assert_equal(Integer::LogicalShiftRightArithmetic(hFFFF_FFFF, Integer(0)), hFFFF_FFFF); + assert_equal(Integer::LogicalShiftRightArithmetic(Integer(0), Integer(6)), Integer(0)); + assert_equal(Integer::LogicalShiftRightArithmetic(Integer(0), Integer(36)), Integer(0)); + assert_equal(Integer::LogicalShiftRightArithmetic(h1_0000_0000, Integer(32)), Integer(0)); + assert_equal(Integer::LogicalShiftRightArithmetic(hFFFF_FFFF, Integer(32)), hFFFF_FFFF); + assert_equal(Integer::LogicalShiftRightArithmetic(hFFFF_FFFF, Integer(3)), hFFFF_FFFF); + assert_equal(Integer::LogicalShiftRightArithmetic(hFFFF_FFFF, Integer(30)), hFFFF_FFFF); + assert_equal(Integer::LogicalShiftRightArithmetic(hFFFF, Integer(14)), Integer(3)); + assert_equal(Integer::LogicalShiftRightArithmetic(hFFFF, Integer(15)), Integer(1)); + assert_equal(Integer::LogicalShiftRightArithmetic(hFFFF, Integer(16)), Integer(0)); + //explicit num_bits + assert_equal(Integer::LogicalShiftRightArithmetic(h0000_FFFF_FFFF_0000, Integer(16), Integer(64)), hFFFF_FFFF); + assert_equal(Integer::LogicalShiftRightArithmetic(h0000_FFFF_FFFF_0000, Integer(16), Integer(50)), hFFFF_FFFF); + assert_equal(Integer::LogicalShiftRightArithmetic(h0000_FFFF_FFFF_0000, Integer(32), Integer(64)), hFFFF); + assert_equal(Integer::LogicalShiftRightArithmetic(h0000_FFFF_FFFF_0000, Integer(32), Integer(4)), Integer(0)); + assert_equal(Integer::LogicalShiftRightArithmetic(hFFFF_FFFF_0000_0000, Integer(32), Integer(64)), hFFFF_FFFF_FFFF_FFFF); +} + +QUIZ_CASE(poincare_logic_bit_compare) +{ + Integer hFFFF = Integer("65535"); + Integer hFFFF_FFFF = Integer("4294967295"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_FFFF_0000_0000 = Integer("18446744069414584320"); + for (uint8_t i = 0; i < 32; i++) + { + assert_equal(Integer::LogicalBitGet(hFFFF_FFFF, Integer(i)), Integer(1)); + assert_equal(Integer::LogicalBitGet(h1_0000_0000, Integer(i)), Integer(0)); + } + assert_equal(Integer::LogicalBitGet(h1_0000_0000, Integer(32)), Integer(1)); + + assert_equal(Integer::LogicalBitGet(Integer(0), Integer(6)), Integer(0)); + assert_equal(Integer::LogicalBitGet(h0000_FFFF_FFFF_0000, Integer(32)), Integer(1)); + assert_equal(Integer::LogicalBitGet(h0000_FFFF_FFFF_0000, Integer(33)), Integer(1)); + assert_equal(Integer::LogicalBitGet(h0000_FFFF_FFFF_0000, Integer(47)), Integer(1)); + assert_equal(Integer::LogicalBitGet(h0000_FFFF_FFFF_0000, Integer(48)), Integer(0)); +} + +QUIZ_CASE(poincare_logic_ror_compare) +{ + Integer hFFFF = Integer("65535"); + Integer hFFFF_FFFF = Integer("4294967295"); + Integer hFFFF_0000 = Integer("4294901760"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_FFFF_0000_0000 = Integer("18446744069414584320"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + Integer hFFFF_0000_0000_FFFF = Integer("18446462598732906495"); + assert_equal(Integer::LogicalRotateRight(hFFFF_FFFF, Integer(0)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateRight(hFFFF_FFFF, Integer(1)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateRight(hFFFF_FFFF, Integer(2)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateRight(hFFFF_FFFF, Integer(3)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateRight(hFFFF_FFFF, Integer(16)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateRight(hFFFF_FFFF, Integer(30)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateRight(hFFFF_FFFF, Integer(31)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateRight(Integer(0), Integer(0)), Integer(0)); + assert_equal(Integer::LogicalRotateRight(Integer(0), Integer(6)), Integer(0)); + assert_equal(Integer::LogicalRotateRight(h1_0000_0000, Integer(31)), Integer(0)); + assert_equal(Integer::LogicalRotateRight(h1_0000_0000, Integer(3)), Integer(0)); + assert_equal(Integer::LogicalRotateRight(hFFFF, Integer(16)), hFFFF_0000); + assert_equal(Integer::LogicalRotateRight(Integer(2), Integer(1)), Integer(1)); + assert_equal(Integer::LogicalRotateRight(Integer(6), Integer(1)), Integer(3)); + //explicit num_bits + assert_equal(Integer::LogicalRotateRight(h0000_FFFF_FFFF_0000, Integer(16), Integer(64)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateRight(h0000_FFFF_FFFF_0000, Integer(16), Integer(50)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateRight(h0000_FFFF_FFFF_0000, Integer(32), Integer(64)), hFFFF_0000_0000_FFFF); + assert_equal(Integer::LogicalRotateRight(hFFFF_FFFF_0000_0000, Integer(16), Integer(64)), h0000_FFFF_FFFF_0000); + assert_equal(Integer::LogicalRotateRight(h0000_FFFF_FFFF_0000, Integer(48), Integer(64)), hFFFF_FFFF_0000_0000); +} + +QUIZ_CASE(poincare_logic_rol_compare) +{ + Integer hFFFF = Integer("65535"); + Integer hFFFF_FFFF = Integer("4294967295"); + Integer hFFFF_0000 = Integer("4294901760"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_FFFF_0000_0000 = Integer("18446744069414584320"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + Integer hFFFF_0000_0000_FFFF = Integer("18446462598732906495"); + assert_equal(Integer::LogicalRotateLeft(hFFFF_FFFF, Integer(0)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateLeft(hFFFF_FFFF, Integer(1)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateLeft(hFFFF_FFFF, Integer(2)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateLeft(hFFFF_FFFF, Integer(3)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateLeft(hFFFF_FFFF, Integer(16)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateLeft(hFFFF_FFFF, Integer(30)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateLeft(hFFFF_FFFF, Integer(31)), hFFFF_FFFF); + assert_equal(Integer::LogicalRotateLeft(Integer(0), Integer(0)), Integer(0)); + assert_equal(Integer::LogicalRotateLeft(Integer(0), Integer(6)), Integer(0)); + assert_equal(Integer::LogicalRotateLeft(h1_0000_0000, Integer(31)), Integer(0)); + assert_equal(Integer::LogicalRotateLeft(h1_0000_0000, Integer(3)), Integer(0)); + assert_equal(Integer::LogicalRotateLeft(hFFFF, Integer(16)), hFFFF_0000); + assert_equal(Integer::LogicalRotateLeft(Integer(2), Integer(1)), Integer(4)); + assert_equal(Integer::LogicalRotateLeft(Integer(6), Integer(1)), Integer(12)); + //explicit num_bits + assert_equal(Integer::LogicalRotateLeft(h0000_FFFF_FFFF_0000, Integer(16), Integer(64)), hFFFF_FFFF_0000_0000); + assert_equal(Integer::LogicalRotateLeft(hFFFF_FFFF, Integer(16), Integer(50)), h0000_FFFF_FFFF_0000); + assert_equal(Integer::LogicalRotateLeft(h0000_FFFF_FFFF_0000, Integer(32), Integer(64)), hFFFF_0000_0000_FFFF); + assert_equal(Integer::LogicalRotateLeft(hFFFF_FFFF_0000_0000, Integer(16), Integer(64)), hFFFF_0000_0000_FFFF); + assert_equal(Integer::LogicalRotateLeft(h0000_FFFF_FFFF_0000, Integer(48), Integer(64)), hFFFF_FFFF); +} + +QUIZ_CASE(poincare_logic_bic_compare) +{ + Integer hFFFF = Integer("65535"); + Integer hFFFF_FFFF = Integer("4294967295"); + Integer hFFFF_0000 = Integer("4294901760"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_FFFF_0000_0000 = Integer("18446744069414584320"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + Integer hFFFF_0000_0000_FFFF = Integer("18446462598732906495"); + assert_equal(Integer::LogicalBitsClear(hFFFF_FFFF, Integer(0)), hFFFF_FFFF); + assert_equal(Integer::LogicalBitsClear(hFFFF_FFFF, hFFFF), hFFFF_0000); + assert_equal(Integer::LogicalBitsClear(hFFFF_0000, hFFFF), hFFFF_0000); + assert_equal(Integer::LogicalBitsClear(Integer(7), Integer(2)), Integer(5)); + assert_equal(Integer::LogicalBitsClear(Integer(0), Integer(0)), Integer(0)); + assert_equal(Integer::LogicalBitsClear(Integer(0), Integer(6)), Integer(0)); + assert_equal(Integer::LogicalBitsClear(h1_0000_0000, Integer(31)), Integer(0)); + assert_equal(Integer::LogicalBitsClear(h1_0000_0000, Integer(3)), Integer(0)); + //explicit num_bits + assert_equal(Integer::LogicalBitsClear(hFFFF_FFFF_0000_0000, hFFFF_FFFF, Integer(64)), hFFFF_FFFF_0000_0000); + assert_equal(Integer::LogicalBitsClear(hFFFF_FFFF_FFFF_FFFF, hFFFF_FFFF_0000_0000, Integer(64)), hFFFF_FFFF); + assert_equal(Integer::LogicalBitsClear(hFFFF_FFFF_FFFF_FFFF, hFFFF_0000_0000_FFFF, Integer(64)), h0000_FFFF_FFFF_0000); + assert_equal(Integer::LogicalBitsClear(hFFFF_FFFF_FFFF_FFFF, h0000_FFFF_FFFF_0000, Integer(64)), hFFFF_0000_0000_FFFF); +} + +QUIZ_CASE(poincare_logic_bclr_compare) +{ + Integer hFFFF = Integer("65535"); + Integer hFFFF_FFFF = Integer("4294967295"); + Integer hFFFF_0000 = Integer("4294901760"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_FFFF_0000_0000 = Integer("18446744069414584320"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + Integer h7FFF_FFFF_FFFF_FFFF = Integer("9223372036854775807"); + Integer hFFFF_0000_0000_FFFF = Integer("18446462598732906495"); + assert_equal(Integer::LogicalBitClear(Integer(1), Integer(0)), Integer(0)); + assert_equal(Integer::LogicalBitClear(Integer(7), Integer(2)), Integer(3)); + assert_equal(Integer::LogicalBitClear(Integer(0), Integer(0)), Integer(0)); + assert_equal(Integer::LogicalBitClear(Integer(0), Integer(6)), Integer(0)); + assert_equal(Integer::LogicalBitClear(h1_0000_0000, Integer(32)), Integer(0)); + assert_equal(Integer::LogicalBitClear(h1_0000_0000, Integer(3)), h1_0000_0000); + assert_equal(Integer::LogicalBitClear(hFFFF_FFFF_0000_0000, Integer(64)), hFFFF_FFFF_0000_0000); + assert_equal(Integer::LogicalBitClear(hFFFF_FFFF_FFFF_FFFF, Integer(64)), hFFFF_FFFF_FFFF_FFFF); + assert_equal(Integer::LogicalBitClear(hFFFF_FFFF_FFFF_FFFF, Integer(63)), h7FFF_FFFF_FFFF_FFFF); +} + +QUIZ_CASE(poincare_logic_bset_compare) +{ + Integer hFFFF = Integer("65535"); + Integer hFFFF_FFFF = Integer("4294967295"); + Integer hFFFF_0000 = Integer("4294901760"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_FFFF_0000_0000 = Integer("18446744069414584320"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + Integer h7FFF_FFFF_FFFF_FFFF = Integer("9223372036854775807"); + Integer hFFFF_0000_0000_FFFF = Integer("18446462598732906495"); + assert_equal(Integer::LogicalBitSet(Integer(1), Integer(0)), Integer(1)); + assert_equal(Integer::LogicalBitSet(Integer(0), Integer(0)), Integer(1)); + assert_equal(Integer::LogicalBitSet(Integer(3), Integer(2)), Integer(7)); + assert_equal(Integer::LogicalBitSet(Integer(0), Integer(8)), Integer(256)); + assert_equal(Integer::LogicalBitSet(Integer(0), Integer(32)), h1_0000_0000); + assert_equal(Integer::LogicalBitSet(hFFFF_FFFF_0000_0000, Integer(63)), hFFFF_FFFF_0000_0000); + assert_equal(Integer::LogicalBitSet(hFFFF_FFFF_FFFF_FFFF, Integer(60)), hFFFF_FFFF_FFFF_FFFF); + assert_equal(Integer::LogicalBitSet(h7FFF_FFFF_FFFF_FFFF, Integer(63)), hFFFF_FFFF_FFFF_FFFF); +} + +QUIZ_CASE(poincare_logic_bflip_compare) +{ + Integer hFFFF = Integer("65535"); + Integer hFFFF_FFFF = Integer("4294967295"); + Integer hFFFF_0000 = Integer("4294901760"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_FFFF_0000_0000 = Integer("18446744069414584320"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + Integer h7FFF_FFFF_FFFF_FFFF = Integer("9223372036854775807"); + Integer hFFFF_0000_0000_FFFF = Integer("18446462598732906495"); + assert_equal(Integer::LogicalBitFlip(Integer(1), Integer(0)), Integer(0)); + assert_equal(Integer::LogicalBitFlip(Integer(0), Integer(0)), Integer(1)); + assert_equal(Integer::LogicalBitFlip(Integer(3), Integer(2)), Integer(7)); + assert_equal(Integer::LogicalBitFlip(Integer(7), Integer(2)), Integer(3)); + assert_equal(Integer::LogicalBitFlip(Integer(1), Integer(8)), Integer(257)); + assert_equal(Integer::LogicalBitFlip(Integer(257), Integer(8)), Integer(1)); + assert_equal(Integer::LogicalBitFlip(Integer(0), Integer(32)), h1_0000_0000); + assert_equal(Integer::LogicalBitFlip(h1_0000_0000, Integer(32)), Integer(0)); + assert_equal(Integer::LogicalBitFlip(h7FFF_FFFF_FFFF_FFFF, Integer(63)), hFFFF_FFFF_FFFF_FFFF); + assert_equal(Integer::LogicalBitFlip(hFFFF_FFFF_FFFF_FFFF, Integer(63)), h7FFF_FFFF_FFFF_FFFF); +} + +QUIZ_CASE(poincare_logic_tc_compare) +{ + Integer hFFFF = Integer("65535"); + Integer hFFFF_FFFF = Integer("4294967295"); + Integer hFFFF_0000 = Integer("4294901760"); + Integer h1_0000_0000 = Integer("4294967296"); + Integer h0000_FFFF_FFFF_0000 = Integer("281474976645120"); + Integer hFFFF_FFFF_0000_0000 = Integer("18446744069414584320"); + Integer hFFFF_FFFF_FFFF_FFFF = Integer("18446744073709551615"); + Integer h7FFF_FFFF_FFFF_FFFF = Integer("9223372036854775807"); + Integer hFFFF_0000_0000_FFFF = Integer("18446462598732906495"); + assert_equal(Integer::TwosComplementToBits(Integer("-1"), Integer(64)), hFFFF_FFFF_FFFF_FFFF); + assert_equal(Integer::TwosComplementToBits(Integer("-1"), Integer(63)), h7FFF_FFFF_FFFF_FFFF); + assert_equal(Integer::TwosComplementToBits(Integer("-1"), Integer(32)), hFFFF_FFFF); + assert_equal(Integer::TwosComplementToBits(Integer("-1"), Integer(16)), hFFFF); + assert_equal(Integer::TwosComplementToBits(Integer("-4294967296"), Integer(33)), h1_0000_0000); + + assert_equal(Integer::TwosComplementToBits(hFFFF_FFFF, Integer(32)), Integer("-1")); + assert_equal(Integer::TwosComplementToBits(hFFFF, Integer(17)), Integer("65535")); + assert_equal(Integer::TwosComplementToBits(hFFFF, Integer(16)), Integer("-1")); + assert_equal(Integer::TwosComplementToBits(h7FFF_FFFF_FFFF_FFFF, Integer(63)), Integer("-1")); + assert_equal(Integer::TwosComplementToBits(hFFFF_FFFF_FFFF_FFFF, Integer(63)), Integer("-1")); + assert_equal(Integer::TwosComplementToBits(hFFFF_FFFF_FFFF_FFFF, Integer(64)), Integer("-1")); + assert_equal(Integer::TwosComplementToBits(hFFFF_FFFF_0000_0000, Integer(64)), Integer("-4294967296")); + assert_equal(Integer::TwosComplementToBits(hFFFF_0000_0000_FFFF, Integer(64)), Integer("-281474976645121")); + assert_equal(Integer::TwosComplementToBits(hFFFF_0000_0000_FFFF, Integer(63)), Integer("-281474976645121")); + assert_equal(Integer::TwosComplementToBits(hFFFF_0000_0000_FFFF, Integer(59)), Integer("-281474976645121")); + assert_equal(Integer::TwosComplementToBits(h1_0000_0000, Integer(33)), Integer("-4294967296")); + assert_equal(Integer::TwosComplementToBits(hFFFF_0000, Integer(33)), Integer("4294901760")); + assert_equal(Integer::TwosComplementToBits(hFFFF_0000, Integer(17)), Integer("-65536")); +} diff --git a/poincare/test/parsing.cpp b/poincare/test/parsing.cpp index 49bd40c2f95..5cbefc5569a 100644 --- a/poincare/test/parsing.cpp +++ b/poincare/test/parsing.cpp @@ -423,6 +423,26 @@ QUIZ_CASE(poincare_parsing_identifiers) { assert_parsed_expression_is("√(1)", SquareRoot::Builder(BasedInteger::Builder(1))); assert_text_not_parsable("cos(1,2)"); assert_text_not_parsable("log(1,2,3)"); + assert_parsed_expression_is("and(1,1)", And::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("or(1,1)", Or::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("not(1)", Not::Builder(BasedInteger::Builder(1))); + assert_parsed_expression_is("not(1,1)", NotExplicit::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("xor(1,1)", Xor::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("bclr(1,1)", BitClear::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("bflp(1,1)", BitFlip::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("bit(1,1)", BitGet::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("bset(1,1)", BitSet::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("bic(1,1)", BitsClear::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("bic(1,1,1)", BitsClearExplicit::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("rol(1,1)", RotateLeft::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("rol(1,1,1)", RotateLeftExplicit::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("ror(1,1)", RotateRight::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("ror(1,1,1)", RotateRightExplicit::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("sra(1,1)", ShiftArithmeticRight::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("sra(1,1,1)", ShiftArithmeticRightExplicit::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("sll(1,1)", ShiftLogicLeft::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("srl(1,1)", ShiftLogicRight::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); + assert_parsed_expression_is("tc(1,1)", TwosComplement::Builder(BasedInteger::Builder(1), BasedInteger::Builder(1))); } QUIZ_CASE(poincare_parsing_parse_store) {