From 2b3a9d8c9820eae8827ad8bca9fe941378c0d458 Mon Sep 17 00:00:00 2001 From: David A Roberts Date: Sun, 20 Oct 2024 21:26:51 +1000 Subject: [PATCH 1/2] Add missing builtins: combinatorial functions (#1134) I pulled out just the combinatorial functions from #1133, knocks a couple of items off the list in #500 --- mathics/builtin/intfns/combinatorial.py | 125 ++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/mathics/builtin/intfns/combinatorial.py b/mathics/builtin/intfns/combinatorial.py index cc1a30989..33b7333f2 100644 --- a/mathics/builtin/intfns/combinatorial.py +++ b/mathics/builtin/intfns/combinatorial.py @@ -17,12 +17,14 @@ from mathics.core.atoms import Integer from mathics.core.attributes import ( A_LISTABLE, + A_N_HOLD_FIRST, A_NUMERIC_FUNCTION, A_ORDERLESS, A_PROTECTED, A_READ_PROTECTED, ) from mathics.core.builtin import Builtin, MPMathFunction, SympyFunction +from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression from mathics.core.list import ListExpression from mathics.core.symbols import ( @@ -39,6 +41,36 @@ SymbolSubsets = Symbol("Subsets") +class BellB(SympyFunction): + """ + + :Bell number: https://en.wikipedia.org/wiki/Bell_number ( + :SymPy: https://docs.sympy.org/latest/modules/functions/combinatorial.html#sympy.functions.combinatorial.numbers.bell, + :WMA: https://reference.wolfram.com/language/ref/BellB.html) +
+
'BellB[$n$]' +
Bell number $B$_$n$. + +
'BellB[$n$, $x$]' +
Bell polynomial $B$_$n$($x$). +
+ + >> BellB[10] + = 115975 + + >> BellB[5, x] + = x + 15 x ^ 2 + 25 x ^ 3 + 10 x ^ 4 + x ^ 5 + """ + + attributes = A_LISTABLE | A_N_HOLD_FIRST | A_PROTECTED | A_READ_PROTECTED + summary_text = "Bell numbers" + sympy_name = "bell" + + def eval(self, z, evaluation: Evaluation): + "%(name)s[z__]" + return super().eval(z, evaluation) + + class _BooleanDissimilarity(Builtin): @staticmethod def _to_bool_vector(u): @@ -184,6 +216,36 @@ def _compute(self, n, c_ff, c_ft, c_tf, c_tt): ) +class EulerE(SympyFunction): + """ + + :Euler numbers: https://en.wikipedia.org/wiki/Euler_numbers ( + :SymPy: https://docs.sympy.org/latest/modules/functions/combinatorial.html#sympy.functions.combinatorial.numbers.euler, + :WMA: https://reference.wolfram.com/language/ref/EulerE.html) +
+
'EulerE[$n$]' +
Euler number $E$_$n$. + +
'EulerE[$n$, $x$]' +
Euler polynomial $E$_$n$($x$). +
+ + >> Table[EulerE[k], {k, 0, 10}] + = {1, 0, -1, 0, 5, 0, -61, 0, 1385, 0, -50521} + + >> EulerE[5, z] + = -1 / 2 + 5 z ^ 2 / 2 - 5 z ^ 4 / 2 + z ^ 5 + """ + + attributes = A_LISTABLE | A_PROTECTED + summary_text = "Euler numbers" + sympy_name = "euler" + + def eval(self, z, evaluation: Evaluation): + "%(name)s[z__]" + return super().eval(z, evaluation) + + class JaccardDissimilarity(_BooleanDissimilarity): """ @@ -214,6 +276,44 @@ def _compute(self, n, c_ff, c_ft, c_tf, c_tt): ) +class LucasL(SympyFunction): + """ + + :Lucas Number: + https://en.wikipedia.org/wiki/Lucas_number ( + :SymPy: + https://docs.sympy.org/latest/modules/functions/combinatorial.html#sympy.functions.combinatorial.numbers.lucas, \ + + :WMA: + https://reference.wolfram.com/language/ref/LucasL.html) + +
+
'LucasL[$n$]' +
gives the $n$th Lucas number. +
+ + A list of the first five Lucas numbers: + >> Table[LucasL[n], {n, 1, 5}] + = {1, 3, 4, 7, 11} + >> Series[LucasL[1/2, x], {x, 0, 5}] + = 1 + 1 / 4 x + 1 / 32 x ^ 2 + (-1 / 128) x ^ 3 + (-5 / 2048) x ^ 4 + 7 / 8192 x ^ 5 + O[x] ^ 6 + """ + + attributes = A_LISTABLE | A_NUMERIC_FUNCTION | A_PROTECTED | A_READ_PROTECTED + + summary_text = "lucas number" + sympy_name = "lucas" + + rules = { + "LucasL[n_, 1]": "LucasL[n]", + "LucasL[n_, x_]": "(x/2 + Sqrt[1 + x^2 / 4])^n + Cos[n Pi] / (x/2 + Sqrt[1 + x^2 / 4])^n // Simplify", + } + + def eval_integer(self, n: Integer, evaluation): + "LucasL[n_Integer]" + return self.eval(n, evaluation) + + class MatchingDissimilarity(_BooleanDissimilarity): """ :WMA link:https://reference.wolfram.com/language/ref/MatchingDissimilarity.html @@ -276,6 +376,31 @@ def eval(self, values, evaluation): return Expression(SymbolTimes, *elements) +class PolygonalNumber(Builtin): + """ + + :Polygonal number: https://en.wikipedia.org/wiki/Polygonal_number ( + :WMA: https://reference.wolfram.com/language/ref/PolygonalNumber.html) +
+
'PolygonalNumber[$r$, $n$]' +
gives the $n$th $r$-gonal number. +
+ + >> Table[PolygonalNumber[n], {n, 10}] + = {1, 3, 6, 10, 15, 21, 28, 36, 45, 55} + >> Table[PolygonalNumber[r, 10], {r, 3, 10}] + = {55, 100, 145, 190, 235, 280, 325, 370} + """ + + attributes = A_LISTABLE | A_NUMERIC_FUNCTION | A_PROTECTED | A_READ_PROTECTED + summary_text = "polygonal number" + + rules = { + "PolygonalNumber[n_Integer]": "PolygonalNumber[3, n]", + "PolygonalNumber[r_Integer, n_Integer]": "(1/2) n (n (r - 2) - r + 4)", + } + + class RogersTanimotoDissimilarity(_BooleanDissimilarity): """ From 38012c3e158cbe98144a9007c846bde7edc15d7e Mon Sep 17 00:00:00 2001 From: David A Roberts Date: Sun, 20 Oct 2024 21:27:31 +1000 Subject: [PATCH 2/2] Add missing builtins: number theory (#1135) I pulled out just the number theory builtins (and ReverseSort) from #1133 --- mathics/builtin/numbers/numbertheory.py | 326 +++++++++++++++++++++-- mathics/builtin/statistics/orderstats.py | 34 +++ 2 files changed, 343 insertions(+), 17 deletions(-) diff --git a/mathics/builtin/numbers/numbertheory.py b/mathics/builtin/numbers/numbertheory.py index b227a77cf..ca4ccbbc3 100644 --- a/mathics/builtin/numbers/numbertheory.py +++ b/mathics/builtin/numbers/numbertheory.py @@ -6,10 +6,12 @@ import mpmath import sympy from packaging.version import Version +from sympy.utilities.iterables import ordered_partitions from mathics.core.atoms import Integer, Integer0, Integer10, Rational, Real from mathics.core.attributes import ( A_LISTABLE, + A_N_HOLD_ALL, A_NUMERIC_FUNCTION, A_ORDERLESS, A_PROTECTED, @@ -33,6 +35,7 @@ from mathics.eval.nevaluator import eval_N SymbolFractionalPart = Symbol("System`FractionalPart") +SymbolIntegerPart = Symbol("System`IntegerPart") SymbolMantissaExponent = Symbol("System`MantissaExponent") @@ -105,6 +108,59 @@ def eval(self, n: Integer, evaluation: Evaluation): return to_mathics_list(*sympy.divisors(n.value), elements_conversion_fn=Integer) +class DivisorSigma(SympyFunction): + """ + + :Divisor function: https://en.wikipedia.org/wiki/Divisor_function ( + :SymPy: https://docs.sympy.org/latest/modules/functions/combinatorial.html#sympy.functions.combinatorial.numbers.divisor_sigma, + :WMA: https://reference.wolfram.com/language/ref/DivisorSigma.html) + +
+
'DivisorSigma[$k$, $n$]' +
returns σ_$k$($n$) +
+ + >> DivisorSigma[1, 20] + = 42 + >> DivisorSigma[2, 20] + = 546 + """ + + attributes = A_LISTABLE | A_N_HOLD_ALL | A_PROTECTED + summary_text = "divisor function" + sympy_name = "divisor_sigma" + + def eval(self, k: Integer, n: Integer, evaluation: Evaluation): + "DivisorSigma[k_Integer, n_Integer]" + # arguments are in reverse order + return from_sympy(sympy.divisor_sigma(n.to_sympy(), k.to_sympy())) + + +class DivisorSum(Builtin): + """ + :WMA: https://reference.wolfram.com/language/ref/DivisorSum.html + +
+
'DivisorSum[$n$, $form$]' +
transform the divisors of $n$ using $form$ and take their sum +
+ + >> DivisorSum[30, # &] + = 72 + >> DivisorSum[1000, #^2 &] + = 1383460 + + """ + + attributes = A_N_HOLD_ALL | A_PROTECTED | A_READ_PROTECTED + summary_text = "divisor sum" + + rules = { + "DivisorSum[n_Integer, form_]": "Sum[form[d], {d, Divisors[n]}]", + "DivisorSum[n_Integer, form_, cond_]": "Sum[If[cond[d], form[d], 0], {d, Divisors[n]}]", + } + + # FIXME: Previously this used gmpy's gcdext. sympy's gcdex is not as powerful # class ExtendedGCD(Builtin): # """ @@ -234,23 +290,22 @@ def eval(self, n, evaluation: Evaluation): evaluation.message("FactorInteger", "exact", n) -def _fractional_part(self, n, expr, evaluation: Evaluation): +def _integer_part(n, expr, evaluation: Evaluation): n_sympy = n.to_sympy() if n_sympy.is_constant(): if n_sympy >= 0: - positive_integer_part = ( - Expression(SymbolFloor, n).evaluate(evaluation).to_python() - ) - result = n - Integer(positive_integer_part) + return Expression(SymbolFloor, n).evaluate(evaluation) else: - negative_integer_part = ( - Expression(SymbolCeiling, n).evaluate(evaluation).to_python() - ) - result = n - Integer(negative_integer_part) + return Expression(SymbolCeiling, n).evaluate(evaluation) else: return expr - return from_python(result) + +def _fractional_part(n, expr, evaluation: Evaluation): + if n.to_sympy().is_constant(): + return n - _integer_part(n, expr, evaluation) + else: + return expr class FractionalPart(Builtin): @@ -275,7 +330,7 @@ class FractionalPart(Builtin): def eval(self, n, evaluation: Evaluation): "FractionalPart[n_]" expr = Expression(SymbolFractionalPart, n) - return _fractional_part(self.__class__.__name__, n, expr, evaluation) + return _fractional_part(n, expr, evaluation) def eval_complex_n(self, n, evaluation: Evaluation): "FractionalPart[n_Complex]" @@ -283,12 +338,8 @@ def eval_complex_n(self, n, evaluation: Evaluation): n_real = Expression(SymbolRe, n).evaluate(evaluation) n_image = Expression(SymbolIm, n).evaluate(evaluation) - real_fractional_part = _fractional_part( - self.__class__.__name__, n_real, expr, evaluation - ) - image_fractional_part = _fractional_part( - self.__class__.__name__, n_image, expr, evaluation - ) + real_fractional_part = _fractional_part(n_real, expr, evaluation) + image_fractional_part = _fractional_part(n_image, expr, evaluation) return Expression(SymbolComplex, real_fractional_part, image_fractional_part) @@ -322,6 +373,139 @@ def eval(self, expr, evaluation: Evaluation): return from_sympy(sympy.continued_fraction_reduce(nums)) +class IntegerPart(Builtin): + """ + :WMA link:https://reference.wolfram.com/language/ref/IntegerPart.html + +
+
'IntegerPart[$n$]' +
finds the integer part of $n$. +
+ + >> IntegerPart[4.1] + = 4 + + >> IntegerPart[-5.25] + = -5 + """ + + attributes = A_LISTABLE | A_NUMERIC_FUNCTION | A_PROTECTED + summary_text = "integer part of a number" + + def eval(self, n, evaluation: Evaluation): + "IntegerPart[n_]" + expr = Expression(SymbolIntegerPart, n) + return _integer_part(n, expr, evaluation) + + def eval_complex_n(self, n, evaluation: Evaluation): + "IntegerPart[n_Complex]" + expr = Expression(SymbolIntegerPart, n) + n_real = Expression(SymbolRe, n).evaluate(evaluation) + n_image = Expression(SymbolIm, n).evaluate(evaluation) + + real_integer_part = _integer_part(n_real, expr, evaluation) + image_integer_part = _integer_part(n_image, expr, evaluation) + return Expression(SymbolComplex, real_integer_part, image_integer_part) + + +class IntegerPartitions(Builtin): + """ + :Integer partition: https://en.wikipedia.org/wiki/Integer_partition ( + :SymPy: https://docs.sympy.org/latest/modules/utilities/iterables.html#sympy.utilities.iterables.ordered_partitions, + :WMA: https://reference.wolfram.com/language/ref/IntegerPartitions.html) + +
+
'IntegerPartitions[$n$]' +
lists partitions of the integer $n$ +
+ + >> IntegerPartitions[5] + = {{5}, {4, 1}, {3, 2}, {3, 1, 1}, {2, 2, 1}, {2, 1, 1, 1}, {1, 1, 1, 1, 1}} + >> IntegerPartitions[8, 3] + = {{8}, {7, 1}, {6, 2}, {6, 1, 1}, {5, 3}, {5, 2, 1}, {4, 4}, {4, 3, 1}, {4, 2, 2}, {3, 3, 2}} + >> IntegerPartitions[8, {3}] + = {{6, 1, 1}, {5, 2, 1}, {4, 3, 1}, {4, 2, 2}, {3, 3, 2}} + >> IntegerPartitions[8, All, {1, 2, 5}] + = {{5, 2, 1}, {5, 1, 1, 1}, {2, 2, 2, 2}, {2, 2, 2, 1, 1}, {2, 2, 1, 1, 1, 1}, {2, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}} + >> IntegerPartitions[8, All, All, 3] + = {{8}, {7, 1}, {6, 2}} + >> IntegerPartitions[4, {2}, {-1, 0, 1, 4, 5}] + = {{5, -1}, {4, 0}} + """ + + attributes = A_PROTECTED + summary_text = "list integer partitions" + + rules = { + "IntegerPartitions[n_Integer]": "IntegerPartitions[n, All]", + "IntegerPartitions[n_Integer, All]": "IntegerPartitions[n, n]", + "IntegerPartitions[n_Integer, k_Integer]": "IntegerPartitions[n, {1, k}]", + "IntegerPartitions[n_Integer, {k_Integer}]": "IntegerPartitions[n, {k, k}]", + "IntegerPartitions[n_Integer, kspec_, s_List] /; SubsetQ[Range[n], s]": "Select[IntegerPartitions[n, kspec], SubsetQ[s, #] &]", + "IntegerPartitions[n_Integer, kspec_, All]": "IntegerPartitions[n, kspec]", + "IntegerPartitions[n_Integer, kspec_, sspec_, m_]": "Take[IntegerPartitions[n, kspec, sspec], m]", + "IntegerPartitions[n_Integer, {k_Integer}, s_List]": "ReverseSort@Select[Union[ReverseSort /@ Tuples[s, k]], Total[#] == n &]", + } + + def eval(self, n: Integer, kmin: Integer, kmax: Integer, evaluation: Evaluation): + "IntegerPartitions[n_Integer, {kmin_Integer, kmax_Integer}]" + partitions = [] + for k in range(kmin.value, kmax.value + 1): + for p in ordered_partitions(n.value, k, sort=False): + partitions.append([Integer(i) for i in reversed(p)]) + partitions.sort(reverse=True) + return ListExpression(*[ListExpression(*p) for p in partitions]) + + +class JacobiSymbol(Builtin): + """ + + :Jacobi symbol: https://en.wikipedia.org/wiki/Jacobi_symbol ( + :WMA: https://reference.wolfram.com/language/ref/JacobiSymbol.html) +
+
'JacobiSymbol[$a$, $n$]' +
returns the Jacobi symbol ($a$/$n$). +
+ + >> Table[JacobiSymbol[n, m], {n, 0, 10}, {m, 1, n, 2}] + = {{}, {1}, {1}, {1, 0}, {1, 1}, {1, -1, 0}, {1, 0, 1}, {1, 1, -1, 0}, {1, -1, -1, 1}, {1, 0, 1, 1, 0}, {1, 1, 0, -1, 1}} + """ + + attributes = A_LISTABLE | A_PROTECTED + summary_text = "Jacobi symbol" + + rules = { + "JacobiSymbol[a_, p_?PrimeQ]": "Which[Mod[a, p] == 0, 0, PowerMod[a, (p - 1)/2, p] == 1, 1, True, -1]", # Legendre symbol + "JacobiSymbol[a_, n_]": "Times @@ (JacobiSymbol[a, #1]^#2 & @@@ FactorInteger[n])", + } + + +class KroneckerSymbol(Builtin): + """ + + :Kronecker symbol: https://en.wikipedia.org/wiki/Kronecker_symbol ( + :WMA: https://reference.wolfram.com/language/ref/KroneckerSymbol.html) +
+
'KroneckerSymbol[$a$, $n$]' +
returns the Kronecker symbol ($a$/$n$). +
+ + >> Table[KroneckerSymbol[n, m], {n, 5}, {m, 5}] + = {{1, 1, 1, 1, 1}, {1, 0, -1, 0, -1}, {1, -1, 0, 1, -1}, {1, 0, 1, 0, 1}, {1, -1, -1, 1, 0}} + """ + + attributes = A_LISTABLE | A_PROTECTED | A_READ_PROTECTED + summary_text = "Kronecker symbol" + + rules = { + "KroneckerSymbol[a_, n_?(Positive[#] && OddQ[#] &)]": "JacobiSymbol[a, n]", + "KroneckerSymbol[a_, 0]": "If[Abs[a] == 1, 1, 0]", + "KroneckerSymbol[a_, -1]": "If[a < 0, -1, 1]", + "KroneckerSymbol[a_, 2]": "Which[EvenQ[a], 0, Mod[a, 8] == 1 || Mod[a, 8] == 7, 1, True, -1]", + "KroneckerSymbol[a_, n_]": "Times @@ (KroneckerSymbol[a, #1]^#2 & @@@ FactorInteger[n])", + } + + class MantissaExponent(Builtin): """ @@ -413,6 +597,57 @@ def eval_with_b(self, n, b, evaluation: Evaluation): return ListExpression(Expression(SymbolDivide, n, b**exp), exp) +class MersennePrimeExponent(SympyFunction): + """ + + :SymPy: https://docs.sympy.org/latest/modules/ntheory.html#sympy.ntheory.factor_.mersenne_prime_exponent, + :WMA: https://reference.wolfram.com/language/ref/MersennePrimeExponent.html + +
+
'MersennePrimeExponent[$n$]' +
returns the exponent of the $n$th Mersenne prime. +
+ + >> Table[MersennePrimeExponent[n], {n, 10}] + = {2, 3, 5, 7, 13, 17, 19, 31, 61, 89} + + """ + + attributes = A_LISTABLE | A_PROTECTED | A_READ_PROTECTED + summary_text = "Mersenne prime exponent" + sympy_name = "mersenne_prime_exponent" + + def eval(self, n: Integer, evaluation: Evaluation): + "MersennePrimeExponent[n_Integer]" + return super().eval(n, evaluation) + + +class MoebiusMu(SympyFunction): + """ + + :Mobius function: https://en.wikipedia.org/wiki/M%C3%B6bius_function ( + :SymPy: https://docs.sympy.org/latest/modules/functions/combinatorial.html#sympy.functions.combinatorial.numbers.mobius, + :WMA: https://reference.wolfram.com/language/ref/MoebiusMu.html) + +
+
'MoebiusMu[$n$]' +
returns μ($n$) +
+ + >> Array[MoebiusMu, 10] + = {1, -1, -1, 0, -1, 1, -1, 0, 0, 1} + + """ + + attributes = A_LISTABLE | A_PROTECTED + summary_text = "Mobius function" + sympy_name = "mobius" + + def eval(self, n: Integer, evaluation: Evaluation): + "MoebiusMu[n_Integer]" + return super().eval(n, evaluation) + + class NextPrime(Builtin): """ :WMA link:https://reference.wolfram.com/language/ref/NextPrime.html @@ -512,6 +747,28 @@ def eval(self, n, evaluation: Evaluation): return super().eval(n, evaluation) +class PowersRepresentations(Builtin): + """ + :WMA: https://reference.wolfram.com/language/ref/PowersRepresentations.html +
+
'PowersRepresentations[$n$, $k$, $p$]' +
represent $n$ as a sum of $k$ non-negative integers raised to the power of $p$. +
+ + >> PowersRepresentations[1729, 2, 3] + = {{1, 12}, {9, 10}} + >> PowersRepresentations[50, 3, 2] + = {{0, 1, 7}, {0, 5, 5}, {3, 4, 5}} + """ + + attributes = A_PROTECTED | A_READ_PROTECTED + summary_text = "represent a number as a sum of powers" + + rules = { + "PowersRepresentations[n_,k_,p_]": "Sort /@ IntegerPartitions[n, {k}, Range[0, Floor[n^(1/p)]]^p]^(1/p) // Sort", + } + + class Prime(SympyFunction): """ :WMA link: @@ -738,3 +995,38 @@ def eval(self, interval, n, evaluation: Evaluation): except ValueError: evaluation.message("RandomPrime", "noprime") return + + +class SquaresR(Builtin): + """ + + :Sum of squares function: https://en.wikipedia.org/wiki/Sum_of_squares_function ( + :WMA: https://reference.wolfram.com/language/ref/SquaresR.html) + +
+
'SquaresR[$d$, $n$]' +
returns the number of ways to represent $n$ as a sum of $d$ squares. +
+ + >> Table[SquaresR[2, n], {n, 10}] + = {4, 4, 0, 4, 8, 0, 0, 4, 4, 8} + >> Table[Sum[SquaresR[2, k], {k, 0, n^2}], {n, 5}] + = {5, 13, 29, 49, 81} + >> Table[SquaresR[4, n], {n, 10}] + = {8, 24, 32, 24, 48, 96, 64, 24, 104, 144} + >> Table[SquaresR[6, n], {n, 10}] + = {12, 60, 160, 252, 312, 544, 960, 1020, 876, 1560} + >> Table[SquaresR[8, n], {n, 10}] + = {16, 112, 448, 1136, 2016, 3136, 5504, 9328, 12112, 14112} + """ + + attributes = A_LISTABLE | A_PROTECTED | A_READ_PROTECTED + summary_text = "sum of squares function" + + rules = { + "SquaresR[d_Integer, 0]": "1", + "SquaresR[2, n_Integer?Positive]": "4 Total[(-1)^((# - 1)/2) & /@ Select[Divisors[n], Mod[#, 4] == 1 || Mod[#, 4] == 3 &]]", + "SquaresR[4, n_Integer?Positive]": "8 Total[Select[Divisors[n], Mod[#, 4] != 0 &]]", + "SquaresR[6, n_Integer?Positive]": "4 Total[#^2 * (4 * KroneckerSymbol[-4, n/#] - KroneckerSymbol[-4, #]) & /@ Divisors[n]]", + "SquaresR[8, n_Integer?Positive]": "16 Total[(-1)^(n + #) #^3 & /@ Divisors[n]]", + } diff --git a/mathics/builtin/statistics/orderstats.py b/mathics/builtin/statistics/orderstats.py index ebe750d50..1ff92c6c4 100644 --- a/mathics/builtin/statistics/orderstats.py +++ b/mathics/builtin/statistics/orderstats.py @@ -18,6 +18,7 @@ from mathics.algorithm.introselect import introselect from mathics.builtin.list.math import _RankedTakeLargest, _RankedTakeSmallest from mathics.core.atoms import Atom, Integer, Symbol, SymbolTrue +from mathics.core.attributes import A_PROTECTED, A_READ_PROTECTED from mathics.core.builtin import Builtin from mathics.core.expression import Evaluation, Expression from mathics.core.list import ListExpression @@ -85,6 +86,7 @@ class Quantile(Builtin): "nquan": "The quantile `1` has to be between 0 and 1.", } + attributes = A_PROTECTED | A_READ_PROTECTED rules = { "Quantile[list_List, q_, abcd_]": "Quantile[list, {q}, abcd]", "Quantile[list_List, q_]": "Quantile[list, q, {{0, 0}, {1, 0}}]", @@ -170,6 +172,7 @@ class Quartiles(Builtin): = {27 / 4, 13, 77 / 4} """ + attributes = A_PROTECTED | A_READ_PROTECTED rules = { "Quartiles[list_List]": "Quantile[list, {1/4, 1/2, 3/4}, {{1/2, 0}, {0, 1}}]", } @@ -194,6 +197,7 @@ class RankedMax(Builtin): "intpm": "Expected positive integer at position 2 in ``.", "rank": "The specified rank `1` is not between 1 and `2`.", } + attributes = A_PROTECTED | A_READ_PROTECTED summary_text = "the n-th largest item" def eval(self, element, n: Integer, evaluation: Evaluation): @@ -231,6 +235,7 @@ class RankedMin(Builtin): "intpm": "Expected positive integer at position 2 in ``.", "rank": "The specified rank `1` is not between 1 and `2`.", } + attributes = A_PROTECTED | A_READ_PROTECTED summary_text = "the n-th smallest item" def eval(self, element, n: Integer, evaluation: Evaluation): @@ -246,6 +251,32 @@ def eval(self, element, n: Integer, evaluation: Evaluation): return introselect(element.get_mutable_elements(), py_n - 1) +class ReverseSort(Builtin): + """ + :WMA link:https://reference.wolfram.com/language/ref/ReverseSort.html + +
+
'ReverseSort[$list$]' +
sorts $list$ (or the elements of any other expression) according \ + to reverse canonical ordering. + +
'ReverseSort[$list$, $p$]' +
sorts using $p$ to determine the order of two elements. +
+ + >> ReverseSort[{c, b, d, a}] + = {d, c, b, a} + """ + + attributes = A_PROTECTED + summary_text = "reverse sort" + + rules = { + "ReverseSort[list_]": "Reverse[Sort[list]]", + "ReverseSort[list_, p_]": "Reverse[Sort[list, p]]", + } + + class Sort(Builtin): """ :WMA link:https://reference.wolfram.com/language/ref/Sort.html @@ -276,6 +307,7 @@ class Sort(Builtin): = {x_ + n_ y_, x_ + y_} """ + attributes = A_PROTECTED summary_text = "sort lexicographically or with any comparison function" def eval(self, list, evaluation: Evaluation): @@ -334,6 +366,7 @@ class TakeLargest(_RankedTakeLargest): = {Missing[abc], 150} """ + attributes = A_PROTECTED summary_text = "sublist of n largest elements" def eval(self, element, n, evaluation, options): @@ -356,6 +389,7 @@ class TakeSmallest(_RankedTakeSmallest): = {-1, 10} """ + attributes = A_PROTECTED summary_text = "sublist of n smallest elements" def eval(self, element, n, evaluation, options):