mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] Cap binomial and permute coefficient reducing
Change-Id: Ib0c08a9788d77025e709d295bf05f30de50e9253
This commit is contained in:
@@ -12,6 +12,7 @@ public:
|
||||
Type type() const override;
|
||||
Expression * clone() const override;
|
||||
private:
|
||||
constexpr static int k_maxNValue = 300;
|
||||
/* Layout */
|
||||
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
|
||||
int writeTextInBuffer(char * buffer, int bufferSize) const override {
|
||||
|
||||
@@ -13,6 +13,7 @@ public:
|
||||
Type type() const override;
|
||||
Expression * clone() const override;
|
||||
private:
|
||||
constexpr static int k_maxNValue = 100;
|
||||
/* Layout */
|
||||
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
|
||||
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
|
||||
|
||||
@@ -57,17 +57,15 @@ Expression * BinomialCoefficient::shallowReduce(Context& context, AngleUnit angl
|
||||
if (n.isLowerThan(k)) {
|
||||
return replaceWith(new Undefined(), true);
|
||||
}
|
||||
/* if n is too big, we do not reduce to avoid too long computation.
|
||||
* The binomial coefficient will be evaluate approximatively later */
|
||||
if (Integer(k_maxNValue).isLowerThan(n)) {
|
||||
return this;
|
||||
}
|
||||
Rational result(1);
|
||||
Integer kBis = Integer::Subtraction(n, k);
|
||||
k = kBis.isLowerThan(k) ? kBis : k;
|
||||
// Out of bounds
|
||||
if (Integer(k_maxNumberOfSteps).isLowerThan(k)) {
|
||||
return replaceWith(new Undefined(), true);
|
||||
}
|
||||
int clippedK = k.extractedInt(); // Authorized because k < k_maxNumberOfSteps
|
||||
/* TODO: cap n and k -> if k or n too big, do not reduce to avoid too long
|
||||
* computation. The binomial coefficient will be evaluate approximatively
|
||||
* later */
|
||||
int clippedK = k.extractedInt(); // Authorized because k < n < k_maxNValue
|
||||
for (int i = 0; i < clippedK; i++) {
|
||||
Rational factor = Rational(Integer::Subtraction(n, Integer(i)), Integer::Subtraction(k, Integer(i)));
|
||||
result = Rational::Multiplication(result, factor);
|
||||
@@ -96,12 +94,15 @@ Expression * BinomialCoefficient::templatedEvaluate(Context& context, AngleUnit
|
||||
delete nInput;
|
||||
delete kInput;
|
||||
k = k > (n-k) ? n-k : k;
|
||||
if (isnan(n) || isnan(k) || n != std::round(n) || k != std::round(k) || k > n || k < 0 || n < 0 || k > k_maxNumberOfSteps) {
|
||||
if (isnan(n) || isnan(k) || n != std::round(n) || k != std::round(k) || k > n || k < 0 || n < 0) {
|
||||
return new Complex<T>(Complex<T>::Float(NAN));
|
||||
}
|
||||
T result = 1;
|
||||
for (int i = 0; i < k; i++) {
|
||||
result *= (n-(T)i)/(k-(T)i);
|
||||
if (isinf(result)) {
|
||||
return new Complex<T>(Complex<T>::Float(result));
|
||||
}
|
||||
}
|
||||
return new Complex<T>(Complex<T>::Float(std::round(result)));
|
||||
}
|
||||
|
||||
@@ -53,14 +53,13 @@ Expression * PermuteCoefficient::shallowReduce(Context& context, AngleUnit angle
|
||||
if (n.isLowerThan(k)) {
|
||||
return replaceWith(new Rational(0), true);
|
||||
}
|
||||
if (Integer(k_maxNumberOfSteps).isLowerThan(k)) {
|
||||
return replaceWith(new Undefined(), true);
|
||||
/* if n is too big, we do not reduce to avoid too long computation.
|
||||
* The permute coefficient will be evaluate approximatively later */
|
||||
if (Integer(k_maxNValue).isLowerThan(n)) {
|
||||
return this;
|
||||
}
|
||||
Integer result(1);
|
||||
int clippedK = k.extractedInt(); // Authorized because k < k_maxNumberOfSteps
|
||||
/* TODO: cap n and k -> if k or n too big, do not reduce to avoid too long
|
||||
* computation. The permute coefficient will be evaluate approximatively
|
||||
* later */
|
||||
int clippedK = k.extractedInt(); // Authorized because k < n < k_maxNValue
|
||||
for (int i = 0; i < clippedK; i++) {
|
||||
Integer factor = Integer::Subtraction(n, Integer(i));
|
||||
result = Integer::Multiplication(result, factor);
|
||||
@@ -79,7 +78,7 @@ Complex<T> * PermuteCoefficient::templatedEvaluate(Context& context, AngleUnit a
|
||||
T k = static_cast<Complex<T> *>(kInput)->toScalar();
|
||||
delete nInput;
|
||||
delete kInput;
|
||||
if (isnan(n) || isnan(k) || n != std::round(n) || k != std::round(k) || n < 0.0f || k < 0.0f || k > k_maxNumberOfSteps) {
|
||||
if (isnan(n) || isnan(k) || n != std::round(n) || k != std::round(k) || n < 0.0f || k < 0.0f) {
|
||||
return new Complex<T>(Complex<T>::Float(NAN));
|
||||
}
|
||||
if (k > n) {
|
||||
@@ -88,6 +87,9 @@ Complex<T> * PermuteCoefficient::templatedEvaluate(Context& context, AngleUnit a
|
||||
T result = 1;
|
||||
for (int i = (int)n-(int)k+1; i <= (int)n; i++) {
|
||||
result *= i;
|
||||
if (isinf(result)) {
|
||||
return new Complex<T>(Complex<T>::Float(result));
|
||||
}
|
||||
}
|
||||
return new Complex<T>(Complex<T>::Float(std::round(result)));
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ QUIZ_CASE(poincare_simplify_easy) {
|
||||
assert_parsed_expression_simplify_to("lcm(123,278)", "34194");
|
||||
assert_parsed_expression_simplify_to("lcm(11,121)", "121");
|
||||
assert_parsed_expression_simplify_to("root(4,3)", "4^(1/3)");
|
||||
assert_parsed_expression_simplify_to("permute(102,4)", "101989800");
|
||||
assert_parsed_expression_simplify_to("permute(99,4)", "90345024");
|
||||
assert_parsed_expression_simplify_to("permute(20,-10)", "undef");
|
||||
assert_parsed_expression_simplify_to("re(1/2)", "1/2");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user