- 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

@@ -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 &);