- Added clog2 function

- negative numbers can now be displayed in 2's compliment binary
This commit is contained in:
Joe Crop
2022-12-06 11:10:01 -08:00
parent 42d8fea8c6
commit fc95028b57
20 changed files with 97 additions and 9 deletions

View File

@@ -1,6 +1,8 @@
#include "integer_list_controller.h"
#include <poincare/based_integer.h>
#include <poincare/opposite.h>
#include <poincare/integer.h>
#include <poincare/logarithm.h>
#include <poincare/empty_layout.h>
#include <poincare/factor.h>
#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<BasedInteger &>(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<BasedInteger &>(m_expression).integer();
for (int index = 0; index < k_indexOfFactorExpression; ++index) {
m_layouts[index] = integer.createLayout(baseAtIndex(index));
}
}
else
{
Opposite b = static_cast<Opposite &>(m_expression);
Expression e = b.childAtIndex(0);
Integer childInt = static_cast<BasedInteger &>(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());

View File

@@ -109,7 +109,8 @@ const ToolboxMessageTree logicChildren[] = {
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::TwosComplementToBitsCommandWithArg, I18n::Message::TwosComplementToBits),
ToolboxMessageTree::Leaf(I18n::Message::CeilingLog2CommandWithArg, I18n::Message::CeilingLog2)
};
#if LIST_ARE_DEFINED

View File

@@ -511,3 +511,4 @@ LogicalRotateRightExplicitCommandWithArg = "ror(a,r,n)"
LogicalXor = "a XOR b"
LogicalXorCommandWithArg = "xor(a,r)"
TwosComplementToBitsCommandWithArg = "tc(a,n)"
CeilingLog2CommandWithArg = "clog2(a)"

View File

@@ -522,4 +522,5 @@ 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"

View File

@@ -522,4 +522,5 @@ 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"

View File

@@ -522,4 +522,5 @@ 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"

View File

@@ -526,4 +526,5 @@ 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 = "Nombre de bits nécessaires pour stocker a"
ExplicitNumberOfBits = "Nombre indiqué de bits"

View File

@@ -522,4 +522,5 @@ 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"

View File

@@ -522,4 +522,5 @@ 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"

View File

@@ -522,4 +522,5 @@ 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"

View File

@@ -522,4 +522,5 @@ 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"

View File

@@ -220,6 +220,14 @@ namespace Poincare
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<CeilingLog2, BinaryOperationNode<32> >({child1}); }
static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("clog2", 1, &UntypedBuilderOneChild<CeilingLog2>);
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
};
} // namespace Poincare
#endif

View File

@@ -36,6 +36,7 @@ class Expression : public TreeHandle {
friend class BitsClearExplicit;
friend class BitSet;
friend class Ceiling;
friend class CeilingLog2;
friend class CommonLogarithm;
template<typename T>
friend class ComplexNode;

View File

@@ -65,6 +65,7 @@ public:
BinomialCoefficient,
BinomPDF,
Ceiling,
CeilingLog2,
ComplexArgument,
Conjugate,
Derivative,

View File

@@ -169,6 +169,7 @@ public:
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);

View File

@@ -30,6 +30,7 @@ namespace Poincare {
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(); }
@@ -53,6 +54,7 @@ namespace Poincare {
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 {
@@ -164,10 +166,15 @@ namespace Poincare {
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 T>
int BinaryOperationNode<T>::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() :
@@ -303,6 +310,11 @@ namespace Poincare {
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) {
@@ -327,11 +339,11 @@ namespace Poincare {
Integer cq;
Integer x;
if(aq.isNegative() && t != ExpressionNode::Type::TwosComplement) {
if(aq.isNegative() && t != ExpressionNode::Type::TwosComplement && t != ExpressionNode::Type::CeilingLog2) {
return Undefined::Builder();
}
if(t != ExpressionNode::Type::Not) {
if(t != ExpressionNode::Type::Not && t != ExpressionNode::Type::CeilingLog2) {
bq = getValidInteger(e.childAtIndex(1));
if(bq.isNegative()) {
return Undefined::Builder();
@@ -434,6 +446,9 @@ namespace Poincare {
case ExpressionNode::Type::TwosComplement:
x = Integer::TwosComplementToBits(aq, bq);
break;
case ExpressionNode::Type::CeilingLog2:
x = Integer::CeilingLog2(aq);
break;
default:
break;
}
@@ -530,6 +545,10 @@ namespace Poincare {
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;
@@ -561,5 +580,6 @@ template int BinaryOperationNode<28>::serialize(char * buffer, int bufferSize, P
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

View File

@@ -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<BasedInteger>().integer(), Integer(stringInteger)) < 0);
return type() == ExpressionNode::Type::BasedInteger || (type() == ExpressionNode::Type::Opposite && childAtIndex(0).type() == ExpressionNode::Type::BasedInteger); // && (Integer::NaturalOrder(convert<BasedInteger>().integer(), Integer(stringInteger)) < 0);
}
bool Expression::isDivisionOfIntegers() const {

View File

@@ -521,7 +521,7 @@ Integer Integer::LogicalShift(const Integer &a, const Integer &shift, const Inte
return uint_final;
}
// Sift Left
// Shift Left
while (points > 0)
{
uint8_t power = (points >= 31) ? 31 : points;
@@ -832,6 +832,29 @@ Integer Integer::TwosComplementToBits(const Integer &a, const Integer &num_bits)
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) {

View File

@@ -114,6 +114,7 @@ private:
&BitGet::s_functionHelper,
&BitSet::s_functionHelper,
&Ceiling::s_functionHelper,
&CeilingLog2::s_functionHelper,
&ConfidenceInterval::s_functionHelper,
&Conjugate::s_functionHelper,
&Cosine::s_functionHelper,

View File

@@ -295,6 +295,7 @@ template BinomialCoefficient TreeHandle::FixedArityBuilder<BinomialCoefficient,
template BinomialCoefficientLayout TreeHandle::FixedArityBuilder<BinomialCoefficientLayout, BinomialCoefficientLayoutNode>(const Tuple &);
template BinomPDF TreeHandle::FixedArityBuilder<BinomPDF, BinomPDFNode>(const Tuple &);
template Ceiling TreeHandle::FixedArityBuilder<Ceiling, CeilingNode>(const Tuple &);
template CeilingLog2 TreeHandle::FixedArityBuilder<CeilingLog2, BinaryOperationNode<32> >(const Tuple &);
template CeilingLayout TreeHandle::FixedArityBuilder<CeilingLayout, CeilingLayoutNode>(const Tuple &);
template CommonLogarithm TreeHandle::FixedArityBuilder<CommonLogarithm, LogarithmNode<1> >(const Tuple &);
template ComplexArgument TreeHandle::FixedArityBuilder<ComplexArgument, ComplexArgumentNode>(const Tuple &);