From c9d572fbf9d5995686999022842421d40171c2b4 Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 3 Sep 2026 12:35:59 -0400 Subject: [PATCH 1/6] Move get_int_value() method from BaseElement to Number.. and other relevant classes. --- mathics/builtin/forms/data.py | 4 ++-- mathics/builtin/functional/apply_fns_to_lists.py | 4 ++-- mathics/builtin/string/charcodes.py | 4 ++-- mathics/compile/ir.py | 8 ++++++-- mathics/core/atoms/numerics.py | 3 +++ mathics/core/element.py | 7 ------- mathics/core/expression.py | 6 +++++- mathics/core/expression_predefined.py | 7 ++++++- mathics/core/symbols.py | 3 +++ mathics/eval/list/eol.py | 4 ++-- mathics/eval/numbers/algebra/polynomial.py | 6 +++++- mathics/eval/parts.py | 4 ++-- 12 files changed, 38 insertions(+), 22 deletions(-) diff --git a/mathics/builtin/forms/data.py b/mathics/builtin/forms/data.py index 07edf64804..336ea5f1a4 100644 --- a/mathics/builtin/forms/data.py +++ b/mathics/builtin/forms/data.py @@ -14,7 +14,7 @@ from mathics.builtin.box.layout import RowBox, StyleBox, SuperscriptBox from mathics.builtin.forms.base import FormBaseClass -from mathics.core.atoms import Integer, Real, String +from mathics.core.atoms import Integer, Number, Real, String from mathics.core.builtin import Builtin from mathics.core.element import BaseElement from mathics.core.evaluation import Evaluation @@ -175,7 +175,7 @@ def check_DigitBlock(self, value, evaluation: Evaluation) -> Optional[List[int]] at the left and right of the decimal separator. `None` otherwise. """ - py_value = value.get_int_value() + py_value = value.get_int_value() if isinstance(value, Number) else None if value.sameQ(SymbolInfinity): return [0, 0] if py_value is not None and py_value > 0: diff --git a/mathics/builtin/functional/apply_fns_to_lists.py b/mathics/builtin/functional/apply_fns_to_lists.py index 1eeed7b38a..db12d090e7 100644 --- a/mathics/builtin/functional/apply_fns_to_lists.py +++ b/mathics/builtin/functional/apply_fns_to_lists.py @@ -11,7 +11,7 @@ from dataclasses import replace as dc_replace from typing import Iterable -from mathics.core.atoms import Integer, Integer0, Integer1, Integer3 +from mathics.core.atoms import Integer, Integer0, Integer1, Integer3, Number from mathics.core.builtin import Builtin, InfixOperator from mathics.core.convert.expression import to_mathics_list from mathics.core.evaluation import Evaluation @@ -384,7 +384,7 @@ def eval_n(self, f, expr, n, evaluation): full_expr = Expression(SymbolMapThread, f, expr) else: full_expr = Expression(SymbolMapThread, f, expr, n) - n = n.get_int_value() + n = n.get_int_value() if isinstance(n, Number) else None if n is None or n < 0: evaluation.message("MapThread", "intnm", Integer3, full_expr) diff --git a/mathics/builtin/string/charcodes.py b/mathics/builtin/string/charcodes.py index 9f33b07028..055d20f93b 100644 --- a/mathics/builtin/string/charcodes.py +++ b/mathics/builtin/string/charcodes.py @@ -5,7 +5,7 @@ import sys -from mathics.core.atoms import Integer, Integer1, String +from mathics.core.atoms import Integer, Integer1, Number, String from mathics.core.builtin import Builtin from mathics.core.convert.expression import to_mathics_list from mathics.core.evaluation import Evaluation @@ -177,7 +177,7 @@ def convert_codepoint_list(li): if encoding == "Unicode": s = "" for i, ni in enumerate(li): - pyni = ni.get_int_value() + pyni = ni.get_int_value() if isinstance(ni, Number) else None if not (pyni is not None and 0 <= pyni <= 0xFFFF): evaluation.message( "FromCharacterCode", diff --git a/mathics/compile/ir.py b/mathics/compile/ir.py index 7f1492b1d2..1838daac2d 100644 --- a/mathics/compile/ir.py +++ b/mathics/compile/ir.py @@ -7,7 +7,7 @@ from mathics.compile.base import CompileError from mathics.compile.types import bool_type, int_type, real_type, void_type from mathics.compile.utils import llvm_to_ctype, pairwise -from mathics.core.atoms import Integer, Real +from mathics.core.atoms import Integer, Number, Real from mathics.core.expression import Expression from mathics.core.symbols import Symbol from mathics.core.systemsymbols import SymbolE @@ -363,7 +363,11 @@ def _gen_Power(self, expr): return self.call_fp_intr("llvm.exp", [exponent]) # 2 ^ exponent - if elements[0].get_int_value() == 2 and exponent.type == real_type: + if ( + isinstance(elements[0], Number) + and elements[0].get_int_value() == 2 + and exponent.type == real_type + ): return self.call_fp_intr("llvm.exp2", [exponent]) # convert base diff --git a/mathics/core/atoms/numerics.py b/mathics/core/atoms/numerics.py index bd8efe29c7..e0402d7a9d 100644 --- a/mathics/core/atoms/numerics.py +++ b/mathics/core/atoms/numerics.py @@ -100,6 +100,9 @@ def get_float_value( except Exception: return None + def get_int_value(self) -> Optional[int]: + return None + @property def is_literal(self) -> bool: """Number can't change and has a Python representation, diff --git a/mathics/core/element.py b/mathics/core/element.py index 1379c48ddb..23c6d02a5d 100644 --- a/mathics/core/element.py +++ b/mathics/core/element.py @@ -196,13 +196,6 @@ def get_head_name(self) -> str: """ raise NotImplementedError - # FIXME: this behavior -- defining a specific default implementation - # that is basically saying: "it isn't implemented" -- is wrong. - # To remove this method, we need to fix up calls that expect this behavior, - # that I am not certain how to do right now. - rocky - def get_int_value(self) -> Optional[int]: - return None - def get_lookup_name(self) -> str: """ Returns symbol name of leftmost head. This method is used diff --git a/mathics/core/expression.py b/mathics/core/expression.py index 467e7806b4..ecdfbd9d43 100644 --- a/mathics/core/expression.py +++ b/mathics/core/expression.py @@ -1646,7 +1646,11 @@ def to_python(self, *args, **kwargs) -> Any: return value.to_python() if head is SymbolDirectedInfinity and len(self._elements) == 1: - direction = self._elements[0].get_int_value() + direction = ( + self._elements[0].get_int_value() + if isinstance(self._elements[0], Number) + else None + ) if direction == 1: return math.inf if direction == -1: diff --git a/mathics/core/expression_predefined.py b/mathics/core/expression_predefined.py index 875caa483d..a475434ccd 100644 --- a/mathics/core/expression_predefined.py +++ b/mathics/core/expression_predefined.py @@ -3,7 +3,7 @@ """ import math -from typing import Final +from typing import Final, Optional from sympy import I, S @@ -37,6 +37,11 @@ def __init__( if value is not None: self.value = value + def get_int_value(self) -> Optional[int]: + if isinstance(self.value, int): + return self.value + return None + MATHICS3_COMPLEX_INFINITY: Final = PredefinedExpression(SymbolDirectedInfinity) MATHICS3_INFINITY: Final = PredefinedExpression( diff --git a/mathics/core/symbols.py b/mathics/core/symbols.py index e998022483..38c23284ce 100644 --- a/mathics/core/symbols.py +++ b/mathics/core/symbols.py @@ -226,6 +226,9 @@ def get_head_name(self) -> "str": # 1/0 # return None if stop_on_error else {} + def get_int_value(self) -> Optional[int]: + return None + def get_lookup_name(self) -> str: """ By default, atoms that are not symbols diff --git a/mathics/eval/list/eol.py b/mathics/eval/list/eol.py index 9bb6975a62..57d9de47a4 100644 --- a/mathics/eval/list/eol.py +++ b/mathics/eval/list/eol.py @@ -4,7 +4,7 @@ from typing import List -from mathics.core.atoms import Integer +from mathics.core.atoms import Integer, Number from mathics.core.evaluation import Evaluation from mathics.core.exceptions import MessageException from mathics.core.expression import Expression @@ -20,7 +20,7 @@ def convert_seq(seq): """ start, stop, step = 1, None, 1 name = seq.get_name() - value = seq.get_int_value() + value = seq.get_int_value() if isinstance(seq, Number) else None if name == "System`All": pass elif name == "System`None": diff --git a/mathics/eval/numbers/algebra/polynomial.py b/mathics/eval/numbers/algebra/polynomial.py index 8e85bdc4e8..0c70c26b64 100644 --- a/mathics/eval/numbers/algebra/polynomial.py +++ b/mathics/eval/numbers/algebra/polynomial.py @@ -534,7 +534,11 @@ def convert_sympy(expr): if operator is SymbolPower: # sympy won't expand `(a + b) / x` to `a / x + b / x` if denominator is False # if denominator is False we store negative powers to prevent this. - n1 = elements[1].get_int_value() + n1 = ( + elements[1].get_int_value() + if isinstance(elements[1], Number) + else None + ) if not denominator and n1 is not None and n1 < 0: return store_sub_expr(expr) return tracing.run_sympy( diff --git a/mathics/eval/parts.py b/mathics/eval/parts.py index 4c417d145a..f9796a1bdf 100644 --- a/mathics/eval/parts.py +++ b/mathics/eval/parts.py @@ -6,7 +6,7 @@ from typing import List, Optional, Tuple -from mathics.core.atoms import Integer +from mathics.core.atoms import Integer, Number from mathics.core.convert.expression import make_expression from mathics.core.element import BaseElement, BoxElementMixin from mathics.core.exceptions import ( @@ -196,7 +196,7 @@ def walk_levels( def python_levelspec(levelspec) -> Tuple[int, Optional[int]]: def value_to_level(expr) -> Optional[int]: - value = expr.get_int_value() + value = expr.get_int_value() if isinstance(expr, Number) else None if value is None: if expr.sameQ(MATHICS3_INFINITY): return None From c215b2a98b519b987a0054a6e400b6d35dee6698 Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 3 Sep 2026 12:53:37 -0400 Subject: [PATCH 2/6] get_int_value -> property int_value --- mathics/builtin/atomic/numbers.py | 14 +++--- mathics/builtin/binary/io.py | 10 ++-- mathics/builtin/box/graphics.py | 6 +-- mathics/builtin/colors/color_directives.py | 18 ++----- mathics/builtin/distance/clusters.py | 6 +-- mathics/builtin/drawing/plot.py | 4 +- mathics/builtin/exp_structure/head_related.py | 2 +- mathics/builtin/files_io/files.py | 14 +++--- mathics/builtin/files_io/filesystem.py | 2 +- mathics/builtin/forms/data.py | 10 ++-- mathics/builtin/functional/application.py | 2 +- .../builtin/functional/apply_fns_to_lists.py | 2 +- .../functional/functional_iteration.py | 10 ++-- mathics/builtin/image/composition.py | 6 +-- mathics/builtin/intfns/combinatorial.py | 14 +++--- mathics/builtin/kernel_sessions.py | 2 +- mathics/builtin/layout.py | 2 +- mathics/builtin/list/constructing.py | 10 ++-- mathics/builtin/list/eol.py | 12 ++--- mathics/builtin/list/math.py | 4 +- mathics/builtin/list/rearrange.py | 22 ++++---- mathics/builtin/numbers/algebra.py | 10 ++-- mathics/builtin/numbers/calculus.py | 50 +++++++++---------- mathics/builtin/numbers/integer.py | 24 ++++----- mathics/builtin/numbers/numbertheory.py | 2 +- mathics/builtin/numbers/trig.py | 2 +- mathics/builtin/patterns/composite.py | 10 ++-- mathics/builtin/patterns/defaults.py | 2 +- mathics/builtin/patterns/rules.py | 4 +- mathics/builtin/scipy_utils/optimizers.py | 2 +- mathics/builtin/scoping.py | 2 +- mathics/builtin/sparse.py | 2 +- mathics/builtin/statistics/orderstats.py | 2 +- mathics/builtin/string/charcodes.py | 6 +-- mathics/builtin/string/operations.py | 8 +-- .../equality_inequality.py | 2 +- .../numerical_properties.py | 6 +-- mathics/compile/ir.py | 4 +- mathics/core/atoms/numerics.py | 8 +-- mathics/core/builtin.py | 13 ++--- mathics/core/definitions.py | 2 +- mathics/core/expression.py | 6 +-- mathics/core/expression_predefined.py | 3 +- mathics/core/number.py | 4 +- mathics/core/subexpression.py | 10 ++-- mathics/core/symbols.py | 19 +++---- mathics/eval/assignments/assignment.py | 16 +++--- mathics/eval/drawing/charts.py | 2 +- mathics/eval/list/eol.py | 16 +++--- mathics/eval/numbers/algebra/polynomial.py | 8 +-- mathics/eval/numbers/calculus/optimizers.py | 2 +- mathics/eval/numbers/calculus/series.py | 10 ++-- mathics/eval/parts.py | 2 +- mathics/eval/strings.py | 2 +- mathics/eval/tensors.py | 2 +- mathics/format/box/graphics.py | 2 +- mathics/format/box/numberform.py | 2 +- mathics/format/box/operators.py | 2 +- 58 files changed, 209 insertions(+), 232 deletions(-) diff --git a/mathics/builtin/atomic/numbers.py b/mathics/builtin/atomic/numbers.py index 4cdb56d086..2f55c71bcf 100644 --- a/mathics/builtin/atomic/numbers.py +++ b/mathics/builtin/atomic/numbers.py @@ -263,7 +263,7 @@ class IntegerLength(Builtin): def eval(self, n, b, evaluation): """IntegerLength[n_, b_]""" - n, b = n.get_int_value(), b.get_int_value() + n, b = n.int_value, b.int_value if n is None or b is None: evaluation.message("IntegerLength", "int") return @@ -399,7 +399,7 @@ def eval_rational_with_base(self, n, b, evaluation): # expr = Expression(SymbolRealDigits, n) py_n = abs(n.value) py_b = b.value - if check_finite_decimal(n.denominator().get_int_value()) and not py_b % 2: + if check_finite_decimal(n.denominator().int_value) and not py_b % 2: return self.eval_with_base(n, b, evaluation) else: exp = log_n_b(py_n, py_b) @@ -441,7 +441,7 @@ def eval_with_base(self, n, b, evaluation, nr_elements=None, pos=None): rational_no = ( True if isinstance(n, Rational) else False ) # it is used for checking whether the input n is a rational or not - py_b = b.get_int_value() + py_b = b.int_value if isinstance(n, (Expression, Symbol, Rational)): pos_len = abs(pos) + 1 if pos is not None and pos < 0 else 1 if nr_elements is not None: @@ -558,12 +558,12 @@ def eval_with_base_and_length(self, n, b, length, evaluation, pos=None): if pos is not None: elements.append(from_python(pos)) expr = Expression(SymbolRealDigits, n, b, length, *elements) - if not (isinstance(length, Integer) and length.get_int_value() >= 0): + if not (isinstance(length, Integer) and length.int_value >= 0): evaluation.message("RealDigits", "intnm", Integer3, expr) return return self.eval_with_base( - n, b, evaluation, nr_elements=length.get_int_value(), pos=pos + n, b, evaluation, nr_elements=length.int_value, pos=pos ) def eval_with_base_length_and_precision(self, n, b, length, p, evaluation): @@ -574,9 +574,7 @@ def eval_with_base_length_and_precision(self, n, b, length, p, evaluation): ) return - return self.eval_with_base_and_length( - n, b, length, evaluation, pos=p.get_int_value() - ) + return self.eval_with_base_and_length(n, b, length, evaluation, pos=p.int_value) class MaxPrecision(Predefined): diff --git a/mathics/builtin/binary/io.py b/mathics/builtin/binary/io.py index 680126cb63..e98715c02f 100644 --- a/mathics/builtin/binary/io.py +++ b/mathics/builtin/binary/io.py @@ -616,7 +616,7 @@ def eval(self, name, n, b, kind, evaluation): expr = Expression(SymbolBinaryWrite, channel, b, kind) # Check channel - stream = stream_manager.lookup_stream(n.get_int_value()) + stream = stream_manager.lookup_stream(n.int_value) if stream is None or stream.io.closed: evaluation.message("General", "openx", name) @@ -661,9 +661,9 @@ def eval(self, name, n, b, kind, evaluation): if isinstance(x, Real): x_py = x.to_python() elif x.has_form(SymbolDirectedInfinity, 1): - if x.elements[0].get_int_value() == 1: + if x.elements[0].int_value == 1: x_py = float("+inf") - elif x.elements[0].get_int_value() == -1: + elif x.elements[0].int_value == -1: x_py = float("-inf") else: x_py = None @@ -689,7 +689,7 @@ def eval(self, name, n, b, kind, evaluation): x_py = None elif t.startswith("Character"): if isinstance(x, Integer): - x_list = [String(char) for char in str(x.get_int_value())] + x_list = [String(char) for char in str(x.int_value)] pyb = list(chain(pyb[:i], x_list, pyb[i + 1 :])) x = pyb[i] assert isinstance(x, String) @@ -711,7 +711,7 @@ def eval(self, name, n, b, kind, evaluation): assert isinstance(x, String) x_py = ord(x.value) else: - x_py = x.get_int_value() + x_py = x.int_value if x_py is None: evaluation.message(SymbolBinaryWrite, "nocoerce", b) diff --git a/mathics/builtin/box/graphics.py b/mathics/builtin/box/graphics.py index 2bbf2c94fb..ad1cd6621a 100644 --- a/mathics/builtin/box/graphics.py +++ b/mathics/builtin/box/graphics.py @@ -433,7 +433,7 @@ def init(self, graphics, style, item, options): spline_degree = options.get("System`SplineDegree") if not isinstance(spline_degree, Integer): raise BoxExpressionError - self.spline_degree = spline_degree.get_int_value() + self.spline_degree = spline_degree.int_value class CircleBox(ArcBox): @@ -548,7 +548,7 @@ def parse_component(segments): spline_degree = options.get("SplineDegree", Integer(3)) if not isinstance(spline_degree, Integer): raise BoxExpressionError - k = spline_degree.get_int_value() + k = spline_degree.int_value elif head == "System`BSplineCurve": raise NotImplementedError # FIXME convert bspline to bezier here # parts = segment.elements @@ -864,7 +864,7 @@ def init(self, graphics, style, item): x = pos.elements[0].round_to_float() y = pos.elements[1].round_to_float() - n = item.elements[-1].get_int_value() + n = item.elements[-1].int_value if any(t is None for t in (x, y, r)) or n < 0: raise BoxExpressionError diff --git a/mathics/builtin/colors/color_directives.py b/mathics/builtin/colors/color_directives.py index 1fa972a722..22874cb65d 100644 --- a/mathics/builtin/colors/color_directives.py +++ b/mathics/builtin/colors/color_directives.py @@ -372,23 +372,13 @@ def compute(c1, c2): distance_function.elements[1].elements[1], Integer ): if ( - distance_function.elements[1].elements[0].get_int_value() - > 0 - and distance_function.elements[1] - .elements[1] - .get_int_value() - > 0 + distance_function.elements[1].elements[0].int_value > 0 + and distance_function.elements[1].elements[1].int_value > 0 ): lightness = ( - distance_function.elements[1] - .elements[0] - .get_int_value() - ) - chroma = ( - distance_function.elements[1] - .elements[1] - .get_int_value() + distance_function.elements[1].elements[0].int_value ) + chroma = distance_function.elements[1].elements[1].int_value def compute(c1, c2): return ( diff --git a/mathics/builtin/distance/clusters.py b/mathics/builtin/distance/clusters.py index 83f964e928..cb0a95fa9d 100644 --- a/mathics/builtin/distance/clusters.py +++ b/mathics/builtin/distance/clusters.py @@ -110,7 +110,7 @@ def _cluster(self, p, k, mode, evaluation, options, expr): if not isinstance(k, Integer): evaluation.message(self.get_name(), "intpm", expr) return - py_k = k.get_int_value() + py_k = k.int_value if py_k < 1: evaluation.message(self.get_name(), "intpm", expr) return @@ -131,7 +131,7 @@ def _cluster(self, p, k, mode, evaluation, options, expr): if seed_string == "Automatic": py_seed = 12345 elif isinstance(seed, Integer): - py_seed = seed.get_int_value() + py_seed = seed.int_value else: evaluation.message( self.get_name(), "rseed", Expression(SymbolRule, "RandomSeed", seed) @@ -447,7 +447,7 @@ def eval( py_r = None if isinstance(up_to, Integer): - py_n = up_to.get_int_value() + py_n = up_to.int_value elif up_to.get_name() == "System`All": py_n = None else: diff --git a/mathics/builtin/drawing/plot.py b/mathics/builtin/drawing/plot.py index 4bb61d594a..7e7e35c891 100644 --- a/mathics/builtin/drawing/plot.py +++ b/mathics/builtin/drawing/plot.py @@ -336,9 +336,7 @@ def graphics(distributions): def manual_bins(bspec, hspec): if isinstance(bspec, Integer): - distributions = [ - Distribution(data, bspec.get_int_value()) for data in matrix - ] + distributions = [Distribution(data, bspec.int_value) for data in matrix] return graphics(distributions) elif bspec.get_head_name() == "System`List" and len(bspec.elements) == 1: bin_width = bspec[0].to_mpmath() diff --git a/mathics/builtin/exp_structure/head_related.py b/mathics/builtin/exp_structure/head_related.py index ba3b71208f..8a5165300d 100644 --- a/mathics/builtin/exp_structure/head_related.py +++ b/mathics/builtin/exp_structure/head_related.py @@ -42,7 +42,7 @@ class Operate(Builtin): def eval(self, p, expr, n, evaluation: Evaluation): "Operate[p_, expr_, Optional[n_, 1]]" - head_depth = n.get_int_value() + head_depth = n.int_value if head_depth is None or head_depth < 0: evaluation.message( "Operate", "intnn", Expression(SymbolOperate, p, expr, n), 3 diff --git a/mathics/builtin/files_io/files.py b/mathics/builtin/files_io/files.py index 73068aeca8..68b5b2aae8 100644 --- a/mathics/builtin/files_io/files.py +++ b/mathics/builtin/files_io/files.py @@ -702,7 +702,7 @@ def eval(self, exprs, filename, evaluation: Evaluation): def eval_input(self, exprs, name, n, evaluation: Evaluation): "Put[exprs___, OutputStream[name_, n_]]" - stream = stream_manager.lookup_stream(n.get_int_value()) + stream = stream_manager.lookup_stream(n.int_value) if stream is None or stream.io.closed: evaluation.message("Put", "openx", evaluation.current_expression) @@ -799,7 +799,7 @@ def eval(self, exprs, filename, evaluation): def eval_input(self, exprs, name, n, evaluation: Evaluation): "PutAppend[exprs___, OutputStream[name_, n_]]" - stream = stream_manager.lookup_stream(n.get_int_value()) + stream = stream_manager.lookup_stream(n.int_value) if stream is None or stream.io.closed: evaluation.message("Put", "openx", evaluation.current_expression) @@ -1258,7 +1258,7 @@ class StreamPosition(Builtin): def eval_input(self, name, n, evaluation): "StreamPosition[InputStream[name_, n_]]" - stream = stream_manager.lookup_stream(n.get_int_value()) + stream = stream_manager.lookup_stream(n.int_value) if stream is None or stream.io is None or stream.io.closed: evaluation.message("General", "openx", name) @@ -1317,7 +1317,7 @@ class SetStreamPosition(Builtin): def eval_input(self, name, n, m, evaluation): "SetStreamPosition[InputStream[name_, n_], m_]" - stream = stream_manager.lookup_stream(n.get_int_value()) + stream = stream_manager.lookup_stream(n.int_value) if stream is None or stream.io is None or stream.io.closed: evaluation.message("General", "openx", name) @@ -1671,7 +1671,7 @@ def eval(self, channel, expr, evaluation): strm = channel_to_stream(channel, "w") if strm is None: return - stream = stream_manager.lookup_stream(strm.elements[1].get_int_value()) + stream = stream_manager.lookup_stream(strm.elements[1].int_value) if stream is None or stream.io is None or stream.io.closed: evaluation.message("General", "openx", channel) @@ -1740,9 +1740,7 @@ def eval(self, channel, expr, evaluation: Evaluation): stream_expr = channel_to_stream(channel, "w") if stream_expr is None: return - stream = stream_manager.lookup_stream( - stream_expr.elements[1].get_int_value() - ) + stream = stream_manager.lookup_stream(stream_expr.elements[1].int_value) else: evaluation.message("WriteString", "strml", channel) return diff --git a/mathics/builtin/files_io/filesystem.py b/mathics/builtin/files_io/filesystem.py index 9f9aeba57a..ca6ffe416e 100644 --- a/mathics/builtin/files_io/filesystem.py +++ b/mathics/builtin/files_io/filesystem.py @@ -808,7 +808,7 @@ def eval(self, filename, evaluation: Evaluation, options: dict): def eval_n(self, filename, n, evaluation: Evaluation, options: dict): "FileNameTake[filename_String, n_Integer, OptionsPattern[FileBaseName]]" - n_int = n.get_int_value() + n_int = n.int_value parts = pathlib.Path(filename.to_python()[1:-1]).parts if n_int >= 0: subparts = parts[:n_int] diff --git a/mathics/builtin/forms/data.py b/mathics/builtin/forms/data.py index 336ea5f1a4..f1309d2ef8 100644 --- a/mathics/builtin/forms/data.py +++ b/mathics/builtin/forms/data.py @@ -175,14 +175,14 @@ def check_DigitBlock(self, value, evaluation: Evaluation) -> Optional[List[int]] at the left and right of the decimal separator. `None` otherwise. """ - py_value = value.get_int_value() if isinstance(value, Number) else None + py_value = value.int_value if isinstance(value, Number) else None if value.sameQ(SymbolInfinity): return [0, 0] if py_value is not None and py_value > 0: return [py_value, py_value] if value.has_form("List", 2): nleft, nright = value.elements - py_left, py_right = nleft.get_int_value(), nright.get_int_value() + py_left, py_right = nleft.int_value, nright.int_value if nleft.sameQ(SymbolInfinity): nleft = 0 elif py_left is not None and py_left > 0: @@ -327,7 +327,7 @@ def check_ExponentStep( If the value is valid, the value of the option. `None` otherwise. """ - result = value.get_int_value() + result = value.int_value if result is None or result <= 0: evaluation.message(self.get_name(), "estep", "ExponentStep", value) return None @@ -522,7 +522,7 @@ class NumberForm(_NumberForm): def default_ExponentFunction(value: Integer): """The default function used to format exponent.""" - n = value.get_int_value() + n = value.int_value if -5 <= n <= 5: return SymbolNull @@ -575,7 +575,7 @@ def eval_makeboxes(self, fexpr, form, evaluation): py_f = py_n = None if prec_parms is None: if isinstance(target, Integer): - py_n = len(str(abs(target.get_int_value()))) + py_n = len(str(abs(target.int_value))) elif isinstance(target, Real): if target.is_machine_precision(): py_n = 6 diff --git a/mathics/builtin/functional/application.py b/mathics/builtin/functional/application.py index 414ec25b1a..5e6ea76b92 100644 --- a/mathics/builtin/functional/application.py +++ b/mathics/builtin/functional/application.py @@ -204,7 +204,7 @@ class Slot(SympyFunction, PrefixOperator): def to_sympy(self, expr: Expression, **kwargs): index: Integer = expr.elements[0] - return sympy.Symbol(f"{SYMPY_SLOT_PREFIX}{index.get_int_value()}") + return sympy.Symbol(f"{SYMPY_SLOT_PREFIX}{index.int_value}") class SlotSequence(PrefixOperator, Builtin): diff --git a/mathics/builtin/functional/apply_fns_to_lists.py b/mathics/builtin/functional/apply_fns_to_lists.py index db12d090e7..89159fc8bc 100644 --- a/mathics/builtin/functional/apply_fns_to_lists.py +++ b/mathics/builtin/functional/apply_fns_to_lists.py @@ -384,7 +384,7 @@ def eval_n(self, f, expr, n, evaluation): full_expr = Expression(SymbolMapThread, f, expr) else: full_expr = Expression(SymbolMapThread, f, expr, n) - n = n.get_int_value() if isinstance(n, Number) else None + n = n.int_value if isinstance(n, Number) else None if n is None or n < 0: evaluation.message("MapThread", "intnm", Integer3, full_expr) diff --git a/mathics/builtin/functional/functional_iteration.py b/mathics/builtin/functional/functional_iteration.py index a60738ed76..9fe382eb3d 100644 --- a/mathics/builtin/functional/functional_iteration.py +++ b/mathics/builtin/functional/functional_iteration.py @@ -49,7 +49,7 @@ def eval(self, f, expr, n, evaluation: Evaluation, options: dict): if n.sameQ(MATHICS3_INFINITY): count = None else: - count = n.get_int_value() + count = n.int_value if count is None or count < 0: evaluation.message("FixedPoint", "intnn") return @@ -57,7 +57,7 @@ def eval(self, f, expr, n, evaluation: Evaluation, options: dict): if count is None: count = self.get_option(options, "MaxIterations", evaluation) if count.is_numeric(evaluation): - count = count.get_int_value() + count = count.int_value else: count = None @@ -130,7 +130,7 @@ def eval(self, f, expr, n, evaluation: Evaluation): if n.sameQ(MATHICS3_INFINITY): count = None else: - count = n.get_int_value() + count = n.int_value if count is None or count < 0: evaluation.message("FixedPoint", "intnn") return @@ -229,7 +229,7 @@ class Nest(Builtin): def eval(self, f, expr, n, evaluation): "Nest[f_, expr_, n_Integer]" - n = n.get_int_value() + n = n.int_value if n is None or n < 0: return result = expr @@ -267,7 +267,7 @@ class NestList(Builtin): def eval(self, f, expr, n, evaluation): "NestList[f_, expr_, n_Integer]" - n = n.get_int_value() + n = n.int_value if n is None or n < 0: return diff --git a/mathics/builtin/image/composition.py b/mathics/builtin/image/composition.py index 7aedb542f6..6a75df3f96 100644 --- a/mathics/builtin/image/composition.py +++ b/mathics/builtin/image/composition.py @@ -247,7 +247,7 @@ def _word_cloud(self, words, evaluation, options): max_items = self.get_option(options, "MaxItems", evaluation) if isinstance(max_items, Integer): - py_max_items = max_items.get_int_value() + py_max_items = max_items.int_value else: py_max_items = 200 @@ -262,9 +262,9 @@ def _word_cloud(self, words, evaluation, options): for element in image_size.elements: if not isinstance(element, Integer): return - py_image_size.append(element.get_int_value()) + py_image_size.append(element.int_value) elif isinstance(image_size, Integer): - size = image_size.get_int_value() + size = image_size.int_value py_image_size = (size, size) else: return diff --git a/mathics/builtin/intfns/combinatorial.py b/mathics/builtin/intfns/combinatorial.py index 96ec4e317b..ee1d93d723 100644 --- a/mathics/builtin/intfns/combinatorial.py +++ b/mathics/builtin/intfns/combinatorial.py @@ -631,7 +631,7 @@ def eval_list_n(self, list, n, evaluation): else: head_t = list.head # Note: "n" does not have to be an Integer. - n_value = n.get_int_value() + n_value = n.int_value if n_value == 0: return ListExpression(ListExpression()) if n_value is None or n_value < 0: @@ -666,7 +666,7 @@ def eval_list_pattern(self, list, n, evaluation): return elif n_len == 1: - elem1 = n.elements[0].get_int_value() + elem1 = n.elements[0].int_value if elem1 is None or elem1 < 0: evaluation.message("Subsets", "nninfseq", expr) return @@ -675,9 +675,9 @@ def eval_list_pattern(self, list, n, evaluation): step_n = 1 elif n_len == 2: - elem1 = n.elements[0].get_int_value() + elem1 = n.elements[0].int_value elem2 = ( - n.elements[1].get_int_value() + n.elements[1].int_value if not n.elements[1].has_form("DirectedInfinity", 1) else len(list.elements) + 1 ) @@ -689,13 +689,13 @@ def eval_list_pattern(self, list, n, evaluation): step_n = 1 elif n_len == 3: - elem1 = n.elements[0].get_int_value() + elem1 = n.elements[0].int_value elem2 = ( - n.elements[1].get_int_value() + n.elements[1].int_value if not n.elements[1].has_form("DirectedInfinity", 1) else len(list.elements) + 1 ) - elem3 = n.elements[2].get_int_value() + elem3 = n.elements[2].int_value if ( elem1 is None or elem2 is None diff --git a/mathics/builtin/kernel_sessions.py b/mathics/builtin/kernel_sessions.py index 0b464744fe..6f448a2af9 100644 --- a/mathics/builtin/kernel_sessions.py +++ b/mathics/builtin/kernel_sessions.py @@ -83,7 +83,7 @@ def eval(self, evaluation: Evaluation, n): "%(name)s[n___]" exitcode = 0 if isinstance(n, Integer): - exitcode = n.get_int_value() + exitcode = n.int_value raise SystemExit(exitcode) diff --git a/mathics/builtin/layout.py b/mathics/builtin/layout.py index c374d4a99e..ef13b518b6 100644 --- a/mathics/builtin/layout.py +++ b/mathics/builtin/layout.py @@ -421,7 +421,7 @@ def eval_outerprecedenceform(self, expr, precedence, form, evaluation): """MakeBoxes[PrecedenceForm[expr_, precedence_], form:StandardForm|TraditionalForm]""" - py_precedence = precedence.get_int_value() + py_precedence = precedence.int_value boxes = format_element(expr, evaluation, form) return parenthesize(py_precedence, expr, boxes, True) diff --git a/mathics/builtin/list/constructing.py b/mathics/builtin/list/constructing.py index 9bcd1b64f6..8e43afdbcd 100644 --- a/mathics/builtin/list/constructing.py +++ b/mathics/builtin/list/constructing.py @@ -74,7 +74,7 @@ def eval(self, f, dimsexpr, origins, head, evaluation: Evaluation): else: dims = [dimsexpr] for index, dim in enumerate(dims): - value = dim.get_int_value() + value = dim.int_value if value is None: evaluation.message("Array", "ilsnn", 2) return @@ -87,7 +87,7 @@ def eval(self, f, dimsexpr, origins, head, evaluation: Evaluation): else: origins = [origins] * len(dims) for index, origin in enumerate(origins): - value = origin.get_int_value() + value = origin.int_value if value is None: evaluation.message("Array", "ilsnn", 3) return @@ -352,12 +352,12 @@ def eval_n(self, li, n, evaluation: Evaluation): rs: Optional[Tuple[int, ...]] = None if isinstance(n, Integer): - py_n = min(n.get_int_value(), len(li.elements)) + py_n = min(n.int_value, len(li.elements)) elif n.has_form("List", 1) and isinstance(n.elements[0], Integer): - py_n = n.elements[0].get_int_value() + py_n = n.elements[0].int_value rs = (py_n,) elif ( - n.has_form("DirectedInfinity", 1) and n.elements[0].get_int_value() == 1 + n.has_form("DirectedInfinity", 1) and n.elements[0].int_value == 1 ) or n.get_name() == "System`All": py_n = len(li.elements) else: diff --git a/mathics/builtin/list/eol.py b/mathics/builtin/list/eol.py index 3bf8ecab8c..5675172562 100644 --- a/mathics/builtin/list/eol.py +++ b/mathics/builtin/list/eol.py @@ -410,7 +410,7 @@ def eval(self, expr, positions, evaluation): positions.sort() newexpr = expr for position in positions[::-1]: - pos = [p.get_int_value() for p in position.get_elements()] + pos = [p.int_value for p in position.get_elements()] if None in pos: evaluation.message( "Delete", "psl", position.elements[pos.index(None)], expr @@ -869,13 +869,13 @@ def is_interger_list(expr_list): elif len_list == 0: min_Level = max_Level = None elif len_list == 1: - min_Level = max_Level = level.elements[0].get_int_value() + min_Level = max_Level = level.elements[0].int_value elif len_list == 2: - min_Level = level.elements[0].get_int_value() - max_Level = level.elements[1].get_int_value() + min_Level = level.elements[0].int_value + max_Level = level.elements[1].int_value elif isinstance(level, Integer): min_Level = 0 - max_Level = level.get_int_value() + max_Level = level.int_value else: evaluation.message("FirstPosition", "level", level) return @@ -1489,7 +1489,7 @@ def eval(self, expr, replacements, evaluation): else: position = [position] for index, pos in enumerate(position): - value = pos.get_int_value() + value = pos.int_value if value is None: position = None break diff --git a/mathics/builtin/list/math.py b/mathics/builtin/list/math.py index b6a27a7119..1b10cecca0 100644 --- a/mathics/builtin/list/math.py +++ b/mathics/builtin/list/math.py @@ -79,13 +79,13 @@ def exclude(item): if limit > len(filtered): if not limit.is_upper_limit(): evaluation.message( - self.get_name(), "rank", limit.get_int_value(), len(filtered) + self.get_name(), "rank", limit.int_value, len(filtered) ) return else: py_n = len(filtered) else: - py_n = limit.get_int_value() + py_n = limit.int_value if py_n < 1: return ListExpression() diff --git a/mathics/builtin/list/rearrange.py b/mathics/builtin/list/rearrange.py index a57d4ed6bc..298438b7b3 100644 --- a/mathics/builtin/list/rearrange.py +++ b/mathics/builtin/list/rearrange.py @@ -194,9 +194,9 @@ def _pad(self, in_l, in_n, in_x, in_m, evaluation, expr): py_n = _Pad._find_dims(in_l) elif in_n.get_head_name() == "System`List": if all(isinstance(element, Integer) for element in in_n.elements): - py_n = [element.get_int_value() for element in in_n.elements] + py_n = [element.int_value for element in in_n.elements] elif isinstance(in_n, Integer): - py_n = [in_n.get_int_value()] + py_n = [in_n.int_value] if py_n is None: evaluation.message(self.get_name(), "ilsm", 2, expr()) @@ -208,12 +208,12 @@ def _pad(self, in_l, in_n, in_x, in_m, evaluation, expr): py_x = [in_x] if isinstance(in_m, Integer): - py_m = in_m.get_int_value() + py_m = in_m.int_value else: if not all(isinstance(x, Integer) for x in in_m.elements): evaluation.message(self.get_name(), "ilsm", 4, expr()) return - py_m = [x.get_int_value() for x in in_m.elements] + py_m = [x.int_value for x in in_m.elements] try: return _Pad._build(in_l, py_n, py_x, py_m, 1, self._mode) @@ -391,11 +391,11 @@ def eval_one(self, expr, evaluation: Evaluation): def eval(self, expr, n, evaluation: Evaluation): "%(name)s[expr_, n_]" if isinstance(n, Integer): - py_cycles = [n.get_int_value()] + py_cycles = [n.int_value] elif n.get_head_name() == "System`List" and all( isinstance(x, Integer) for x in n.elements ): - py_cycles = [x.get_int_value() for x in n.elements] + py_cycles = [x.int_value for x in n.elements] if not py_cycles: return expr else: @@ -780,7 +780,7 @@ def eval(self, expr: BaseElement, n: Number, h, evaluation): if n.sameQ(MATHICS3_INFINITY): n_int = -1 # a negative number indicates an unbounded level else: - n_int = n.get_int_value() + n_int = n.int_value # Here we test for negative since in Mathics3 Flatten[] as opposed to flatten_with_respect_to_head() # negative numbers (and None) are not allowed. if n_int is None or n_int < 0: @@ -1030,12 +1030,12 @@ def slices(): def eval_no_overlap(self, li, n: Integer, evaluation: Evaluation): "Partition[li_List, n_Integer]" # TODO: Error checking - return self._partition(li, n.get_int_value(), n.get_int_value(), evaluation) + return self._partition(li, n.int_value, n.int_value, evaluation) def eval(self, li, n: Integer, d: Integer, evaluation: Evaluation): "Partition[li_List, n_Integer, d_Integer]" # TODO: Error checking - return self._partition(li, n.get_int_value(), d.get_int_value(), evaluation) + return self._partition(li, n.int_value, d.int_value, evaluation) class Reverse(Builtin): @@ -1110,7 +1110,7 @@ def eval_top_level(self, expr, evaluation: Evaluation): def eval(self, expr, levels, evaluation: Evaluation): "Reverse[expr_, levels_]" if isinstance(levels, Integer): - py_levels = [levels.get_int_value()] + py_levels = [levels.int_value] elif levels.get_head_name() == "System`List": if not levels.elements: return expr @@ -1118,7 +1118,7 @@ def eval(self, expr, levels, evaluation: Evaluation): py_levels = None else: py_levels = sorted( - list(set(level.get_int_value() for level in levels.elements)) + list(set(level.int_value for level in levels.elements)) ) else: py_levels = None diff --git a/mathics/builtin/numbers/algebra.py b/mathics/builtin/numbers/algebra.py index 525929fa43..2a88e10799 100644 --- a/mathics/builtin/numbers/algebra.py +++ b/mathics/builtin/numbers/algebra.py @@ -83,7 +83,7 @@ def convert_options( self, options: dict, evaluation: Evaluation, supports_modulus: bool = False ) -> Optional[AlgebraicOptions]: modulus = options["System`Modulus"] - py_modulus = modulus.get_int_value() + py_modulus = modulus.int_value if py_modulus is None: evaluation.message(self.get_name(), "modn", Symbol("Modulus"), modulus) return @@ -324,9 +324,7 @@ def eval_list(self, polys, varlist, evaluation: Evaluation, options: dict): return for idxcoeff in component: idx, coeff = idxcoeff - order = ( - Expression(SymbolPlus, *idx).evaluate(evaluation).get_int_value() - ) + order = Expression(SymbolPlus, *idx).evaluate(evaluation).int_value if order is None: evaluation.message("CoefficientArrays", "poly", polys, varlist) return @@ -350,7 +348,7 @@ def eval_list(self, polys, varlist, evaluation: Evaluation, options: dict): arrayidx = [ Integer(n + 1) for n, j in enumerate(idx) - for q in range(j.get_int_value()) + for q in range(j.int_value) ] if dim1 > 1: arrayidx = [Integer(i + 1)] + arrayidx @@ -651,7 +649,7 @@ class _Expand(Builtin): def convert_options(self, options: dict, evaluation: Evaluation): modulus = options["System`Modulus"] - py_modulus = modulus.get_int_value() + py_modulus = modulus.int_value if py_modulus is None: evaluation.message(self.get_name(), "modn", Symbol("Modulus"), modulus) return diff --git a/mathics/builtin/numbers/calculus.py b/mathics/builtin/numbers/calculus.py index 1f740e4753..75e1bc7b8e 100644 --- a/mathics/builtin/numbers/calculus.py +++ b/mathics/builtin/numbers/calculus.py @@ -525,7 +525,7 @@ def to_sympy(self, expr, **kwargs): func = exprs[1].elements[0] sym_func = sympy.Function(sympy_name(func))(*sym_args) - counts = [element.get_int_value() for element in exprs[2].elements] + counts = [element.int_value for element in exprs[2].elements] if None in counts: return @@ -590,7 +590,7 @@ def eval(self, f, n, n0, evaluation: Evaluation, options: dict = {}): if sympy_n0 != sympy.oo: return - trials = options["System`Trials"].get_int_value() + trials = options["System`Trials"].int_value if trials is None or trials <= 0: evaluation.message("DiscreteLimit", "dltrials") @@ -1311,7 +1311,7 @@ def eval(self, expr, x, x0, evaluation: Evaluation, options={}): return direction = self.get_option(options, "Direction", evaluation) - value = direction.get_int_value() + value = direction.int_value if value == -1: dir_sympy = "+" elif value == 1: @@ -2008,7 +2008,7 @@ def eval_reduce( return # if the lower order coeffs vanishes, moves xmin and xmax. if nonzeroidx_left: - nummin = Integer(nummin.get_int_value() + nonzeroidx_left) + nummin = Integer(nummin.int_value + nonzeroidx_left) if nonzeroidx_right: return Expression( SymbolSeriesData, @@ -2082,9 +2082,9 @@ def eval_plus( continue else: data_y, nmin_y, nmax_y, den_y = t.elements[2:] - nmin_val = nmin_y.get_int_value() - nmax_val = nmax_y.get_int_value() - den_val = den_y.get_int_value() + nmin_val = nmin_y.int_value + nmax_val = nmax_y.int_value + den_val = den_y.int_value tseries = (data_y, nmin_val, nmax_val, den_val) series_new = series_plus_series(series, tseries) if series_new: @@ -2100,14 +2100,14 @@ def eval_plus( if tnew.get_head() is SymbolSeriesData: y, y0, data_y, nmin_y, nmax_y, den_y = tnew.elements if y.sameQ(x) and y0.sameQ(x0): - nmin_val = nmin_y.get_int_value() - nmax_val = nmax_y.get_int_value() - den_val = den_y.get_int_value() + nmin_val = nmin_y.int_value + nmax_val = nmax_y.int_value + den_val = den_y.int_value tseries = (data_y, nmin_val, nmax_val, den_val) if tseries is None: data_y = ListExpression(t) - tseries = (data_y, 0, max_exponent.get_int_value(), 1) + tseries = (data_y, 0, max_exponent.int_value, 1) series_new = series_plus_series(series, tseries) if series_new: series = series_new @@ -2135,9 +2135,9 @@ def eval_times( """Times[SeriesData[x_, x0_, data_, nummin_, nummax_, den_], coeff__]""" series = ( data, - nummin.get_int_value(), - nummax.get_int_value(), - den.get_int_value(), + nummin.int_value, + nummax.int_value, + den.int_value, ) x_pattern = BasePattern.create(x, evaluation=evaluation) incompat_series = [] @@ -2167,9 +2167,9 @@ def eval_times( continue else: data_y, nmin_y, nmax_y, den_y = factor.elements[2:] - nmin_val = nmin_y.get_int_value() - nmax_val = nmax_y.get_int_value() - den_val = den_y.get_int_value() + nmin_val = nmin_y.int_value + nmax_val = nmax_y.int_value + den_val = den_y.int_value tseries = (data_y, nmin_val, nmax_val, den_val) series_new = series_times_series(series, tseries) if series_new: @@ -2186,14 +2186,14 @@ def eval_times( if factor_new.get_head() is SymbolSeriesData: y, y0, data_y, nmin_y, nmax_y, den_y = factor_new.elements if y.sameQ(x) and y0.sameQ(x0): - nmin_val = nmin_y.get_int_value() - nmax_val = nmax_y.get_int_value() - den_val = den_y.get_int_value() + nmin_val = nmin_y.int_value + nmax_val = nmax_y.int_value + den_val = den_y.int_value fseries = (data_y, nmin_val, nmax_val, den_val) if fseries is None: data_y = ListExpression(factor) - fseries = (data_y, 0, max_exponent.get_int_value(), 1) + fseries = (data_y, 0, max_exponent.int_value, 1) series_new = series_times_series(series, fseries) if series_new: series = series_new @@ -2213,14 +2213,14 @@ def eval_derivative( """D[SeriesData[x_, x0_, data_, nummin_, nummax_, den_], y_]""" series = ( data, - nummin.get_int_value(), - nummax.get_int_value(), - den.get_int_value(), + nummin.int_value, + nummax.int_value, + den.int_value, ) if isinstance(y, Symbol): order = 1 elif y.has_form("List", 2): - order = y.elements[1].get_int_value() + order = y.elements[1].int_value y = y.elements[0] else: return diff --git a/mathics/builtin/numbers/integer.py b/mathics/builtin/numbers/integer.py index 604bbcda39..2d280717c5 100644 --- a/mathics/builtin/numbers/integer.py +++ b/mathics/builtin/numbers/integer.py @@ -151,13 +151,9 @@ def eval_n_b_d(self, n, b, d, evaluation): base = self._valid_base(b, evaluation) if not base: return - match = d.get_int_value() + match = d.int_value return Integer( - sum( - 1 - for digit in _reversed_digits(n.get_int_value(), base) - if digit == match - ) + sum(1 for digit in _reversed_digits(n.int_value, base) if digit == match) ) def eval_n_b(self, n, b, evaluation): @@ -166,7 +162,7 @@ def eval_n_b(self, n, b, evaluation): if not base: return occurrence_count = [0] * base - for digit in _reversed_digits(n.get_int_value(), base): + for digit in _reversed_digits(n.int_value, base): occurrence_count[digit] += 1 # result list is rotated by one element to the left return to_mathics_list(*(occurrence_count[1:] + [occurrence_count[0]])) @@ -359,7 +355,7 @@ def eval_n_b(self, n, b, evaluation): ListExpression( *[ Integer(d) - for d in reversed(list(_reversed_digits(n.get_int_value(), base))) + for d in reversed(list(_reversed_digits(n.int_value, base))) ] ) if base @@ -374,11 +370,9 @@ def eval_n_b_length(self, n, b, length, evaluation): *_pad( [ Integer(d) - for d in reversed( - list(_reversed_digits(n.get_int_value(), base)) - ) + for d in reversed(list(_reversed_digits(n.int_value, base))) ], - length.get_int_value(), + length.int_value, self._padding, ) ) @@ -456,13 +450,13 @@ def _symbols(self, n, b, evaluation): def eval_n(self, n, b, evaluation): "IntegerString[n_Integer, b_Integer]" - s = self._symbols(n.get_int_value(), b.get_int_value(), evaluation) + s = self._symbols(n.int_value, b.int_value, evaluation) return String(s) if s else None def eval_n_b_length(self, n, b, length, evaluation): "IntegerString[n_Integer, b_Integer, length_Integer]" - s = self._symbols(n.get_int_value(), b.get_int_value(), evaluation) - return String(_pad(s, length.get_int_value(), "0")) if s else None + s = self._symbols(n.int_value, b.int_value, evaluation) + return String(_pad(s, length.int_value, "0")) if s else None class IntegerReverse(_IntBaseBuiltin): diff --git a/mathics/builtin/numbers/numbertheory.py b/mathics/builtin/numbers/numbertheory.py index 5ff343880e..73a5b9ead5 100644 --- a/mathics/builtin/numbers/numbertheory.py +++ b/mathics/builtin/numbers/numbertheory.py @@ -998,7 +998,7 @@ class PrimePowerQ(Builtin): def eval(self, n, evaluation: Evaluation): "PrimePowerQ[n_]" - n = n.get_int_value() + n = n.int_value if n is None: return SymbolFalse diff --git a/mathics/builtin/numbers/trig.py b/mathics/builtin/numbers/trig.py index 9a52864553..5d61d8d91c 100644 --- a/mathics/builtin/numbers/trig.py +++ b/mathics/builtin/numbers/trig.py @@ -281,7 +281,7 @@ def _operands(self, state, steps): def check_pos_operand(x): if x is not None: - if isinstance(x, Integer) and x.get_int_value() in (0, 1): + if isinstance(x, Integer) and x.int_value in (0, 1): pass elif not isinstance(x, Real): return SYMBOLIC diff --git a/mathics/builtin/patterns/composite.py b/mathics/builtin/patterns/composite.py index d97ddfb504..9be501d67d 100644 --- a/mathics/builtin/patterns/composite.py +++ b/mathics/builtin/patterns/composite.py @@ -588,13 +588,13 @@ def init( if len(expr.elements) == 2: element_1 = expr.elements[1] allnumbers = not any( - element.get_int_value() is None for element in element_1.get_elements() + element.int_value is None for element in element_1.get_elements() ) if element_1.has_form("List", 1, 2) and allnumbers: - self.max = element_1.elements[-1].get_int_value() - self.min = element_1.elements[0].get_int_value() - elif element_1.get_int_value(): - self.max = element_1.get_int_value() + self.max = element_1.elements[-1].int_value + self.min = element_1.elements[0].int_value + elif element_1.int_value: + self.max = element_1.int_value else: self.error("range", 2, expr) diff --git a/mathics/builtin/patterns/defaults.py b/mathics/builtin/patterns/defaults.py index ffdf0f4e06..7d5adf3359 100644 --- a/mathics/builtin/patterns/defaults.py +++ b/mathics/builtin/patterns/defaults.py @@ -64,7 +64,7 @@ def eval(self, f, i, evaluation): if len(i) > 2: evaluation.message(SymbolDefault, "argb", 1 + len(i), 1, 3) return - i = [index.get_int_value() for index in i] + i = [index.int_value for index in i] for index in i: if index is None or index < 1: evaluation.message(SymbolDefault.name, "intp") diff --git a/mathics/builtin/patterns/rules.py b/mathics/builtin/patterns/rules.py index 5555c00e20..c129295bb3 100644 --- a/mathics/builtin/patterns/rules.py +++ b/mathics/builtin/patterns/rules.py @@ -374,7 +374,7 @@ def eval( if maxidx == SymbolInfinity or MATHICS3_INFINITY == maxidx: max_count = None else: - max_count = maxidx.get_int_value() + max_count = maxidx.int_value if max_count is None or max_count < 0: evaluation.message( "ReplaceList", @@ -469,7 +469,7 @@ def eval_list( maxit = self.get_option(options, "MaxIterations", evaluation) if maxit is not None and maxit.is_numeric(evaluation): - maxit = maxit.get_int_value() + maxit = maxit.int_value else: maxit = -1 diff --git a/mathics/builtin/scipy_utils/optimizers.py b/mathics/builtin/scipy_utils/optimizers.py index b399b083dd..b935104443 100644 --- a/mathics/builtin/scipy_utils/optimizers.py +++ b/mathics/builtin/scipy_utils/optimizers.py @@ -60,7 +60,7 @@ def get_tolerance_and_maxit(opts: dict, scale: float, evaluation: Evaluation): else: if not isinstance(maxit_parm, Number): maxit_parm = eval_N(maxit_parm, evaluation) - maxit = maxit_parm.get_int_value() + maxit = maxit_parm.int_value return tol, maxit diff --git a/mathics/builtin/scoping.py b/mathics/builtin/scoping.py index 91d574d58d..0fcd523413 100644 --- a/mathics/builtin/scoping.py +++ b/mathics/builtin/scoping.py @@ -509,7 +509,7 @@ def eval(self, vars, expr, evaluation: Evaluation): scoping_vars = get_scoping_vars(vars, "Module", evaluation) replace = {} - number = Symbol("$ModuleNumber").evaluate(evaluation).get_int_value() + number = Symbol("$ModuleNumber").evaluate(evaluation).int_value if number is None: number = 1 evaluation.definitions.set_ownvalue("$ModuleNumber", Integer(number + 1)) diff --git a/mathics/builtin/sparse.py b/mathics/builtin/sparse.py index 3688edc9cd..eb4a92b7dc 100644 --- a/mathics/builtin/sparse.py +++ b/mathics/builtin/sparse.py @@ -147,7 +147,7 @@ def find_dimensions(self, rules, evaluation: Evaluation): dims = [0] * len(pos.elements) for i, idx in enumerate(pos.elements): if isinstance(idx, Integer): - j = idx.get_int_value() + j = idx.int_value dims[i] = max(dims[i], j) if any(d == 0 for d in dims): return diff --git a/mathics/builtin/statistics/orderstats.py b/mathics/builtin/statistics/orderstats.py index 34b27ac333..243e1eb206 100644 --- a/mathics/builtin/statistics/orderstats.py +++ b/mathics/builtin/statistics/orderstats.py @@ -136,7 +136,7 @@ def ranked(i): if py_x is None: return - if c.get_int_value() == 1 and d.get_int_value() == 0: # k == 1? + if c.int_value == 1 and d.int_value == 0: # k == 1? results.append(ranked(int(mpceil(py_x)))) else: py_floor_x = mpfloor(py_x) diff --git a/mathics/builtin/string/charcodes.py b/mathics/builtin/string/charcodes.py index 055d20f93b..3eac0df331 100644 --- a/mathics/builtin/string/charcodes.py +++ b/mathics/builtin/string/charcodes.py @@ -177,7 +177,7 @@ def convert_codepoint_list(li): if encoding == "Unicode": s = "" for i, ni in enumerate(li): - pyni = ni.get_int_value() if isinstance(ni, Number) else None + pyni = ni.int_value if isinstance(ni, Number) else None if not (pyni is not None and 0 <= pyni <= 0xFFFF): evaluation.message( "FromCharacterCode", @@ -189,7 +189,7 @@ def convert_codepoint_list(li): s += chr(pyni) return s else: - codes = [x.get_int_value() & 0xFF for x in li] + codes = [x.int_value & 0xFF for x in li] return pack_bytes(codes).decode(py_encoding) try: @@ -211,7 +211,7 @@ def convert_codepoint_list(li): else: return String(convert_codepoint_list(n.elements)) else: - pyn = n.get_int_value() + pyn = n.int_value if not (isinstance(pyn, int) and pyn > 0 and pyn < sys.maxsize): evaluation.message("FromCharacterCode", "intnm", Integer1, exp) return diff --git a/mathics/builtin/string/operations.py b/mathics/builtin/string/operations.py index 19050aa27b..bf39f03e8b 100644 --- a/mathics/builtin/string/operations.py +++ b/mathics/builtin/string/operations.py @@ -266,13 +266,13 @@ def eval(self, strsource, strnew, pos, evaluation): return strsource else: for i, posi in enumerate(elements): - py_posi = posi.get_int_value() + py_posi = posi.int_value if py_posi is None: evaluation.message("StringInsert", "psl", pos, exp) return listpos.append(py_posi) else: - py_pos = pos.get_int_value() + py_pos = pos.int_value if py_pos is None: evaluation.message("StringInsert", "psl", pos, exp) return @@ -436,7 +436,7 @@ def eval_n(self, string, patt, n, evaluation: Evaluation, options: dict): if n.has_form("DirectedInfinity", 1): py_n = float("inf") else: - py_n = n.get_int_value() + py_n = n.int_value if py_n is None or py_n < 0: evaluation.message("StringPosition", "innf", expr, Integer3) return @@ -877,7 +877,7 @@ def eval(self, string: String, seqspec, evaluation: Evaluation): return if isinstance(seqspec, Integer): - pos = seqspec.get_int_value() + pos = seqspec.int_value if pos >= 0: seq = (1, pos, 1) else: diff --git a/mathics/builtin/testing_expressions/equality_inequality.py b/mathics/builtin/testing_expressions/equality_inequality.py index 50ab74fa34..e22cce4dff 100644 --- a/mathics/builtin/testing_expressions/equality_inequality.py +++ b/mathics/builtin/testing_expressions/equality_inequality.py @@ -252,7 +252,7 @@ def eval_other(self, args, evaluation: Evaluation): "%(name)s[args___?(!ExactNumberQ[#]&)]" args = args.get_sequence() - max_extra_prec = SymbolMaxExtraPrecision.evaluate(evaluation).get_int_value() + max_extra_prec = SymbolMaxExtraPrecision.evaluate(evaluation).int_value if type(max_extra_prec) is not int: max_extra_prec = COMPARE_PREC # try to convert the exact arguments in inexact numbers. diff --git a/mathics/builtin/testing_expressions/numerical_properties.py b/mathics/builtin/testing_expressions/numerical_properties.py index 7c93568220..c4be5c4f80 100644 --- a/mathics/builtin/testing_expressions/numerical_properties.py +++ b/mathics/builtin/testing_expressions/numerical_properties.py @@ -98,7 +98,7 @@ class EvenQ(Test): summary_text = "test whether elements are even numbers" def test(self, n) -> bool: - value = n.get_int_value() + value = n.int_value return value is not None and value % 2 == 0 @@ -407,7 +407,7 @@ class OddQ(Test): summary_text = "test whether elements are odd numbers" def test(self, n) -> bool: - value = n.get_int_value() + value = n.int_value return value is not None and value % 2 != 0 @@ -556,7 +556,7 @@ class PrimeQ(SympyFunction): def eval(self, n, evaluation: Evaluation) -> BooleanType: "PrimeQ[n_]" - n = n.get_int_value() + n = n.int_value if n is None: return SymbolFalse diff --git a/mathics/compile/ir.py b/mathics/compile/ir.py index 1838daac2d..94138bb134 100644 --- a/mathics/compile/ir.py +++ b/mathics/compile/ir.py @@ -224,7 +224,7 @@ def _gen_ir(self, expr): raise CompileError() return arg elif isinstance(expr, Integer): - return int_type(expr.get_int_value()) + return int_type(expr.int_value) elif isinstance(expr, Real): return real_type(expr.round_to_float()) elif not isinstance(expr, Expression): @@ -365,7 +365,7 @@ def _gen_Power(self, expr): # 2 ^ exponent if ( isinstance(elements[0], Number) - and elements[0].get_int_value() == 2 + and elements[0].int_value == 2 and exponent.type == real_type ): return self.call_fp_intr("llvm.exp2", [exponent]) diff --git a/mathics/core/atoms/numerics.py b/mathics/core/atoms/numerics.py index e0402d7a9d..62861c8ffe 100644 --- a/mathics/core/atoms/numerics.py +++ b/mathics/core/atoms/numerics.py @@ -100,7 +100,8 @@ def get_float_value( except Exception: return None - def get_int_value(self) -> Optional[int]: + @property + def int_value(self) -> Optional[int]: return None @property @@ -172,7 +173,7 @@ def value(self) -> T: def _ExponentFunction(value): - n = value.get_int_value() + n = value.int_value if -5 <= n <= 5: return SymbolNull else: @@ -317,7 +318,8 @@ def atom_to_boxes(self, f, evaluation): # return int_to_string_shorter_repr(self._value, form) raise - def get_int_value(self) -> int: + @property + def int_value(self) -> int: return self._value @property diff --git a/mathics/core/builtin.py b/mathics/core/builtin.py index bb3b83f66b..b275d870b9 100644 --- a/mathics/core/builtin.py +++ b/mathics/core/builtin.py @@ -991,10 +991,6 @@ def __init__(self, value: Union[int, str] = "Infinity", upper_limit=True): def is_upper_limit(self) -> bool: return self._upper_limit - def get_int_value(self) -> int: - assert self._finite - return cast(int, self._integer) - def __eq__(self, other) -> bool: if isinstance(other, CountableInteger): if self._finite: @@ -1050,13 +1046,18 @@ def from_expression(expr): n.get_head_name() == "System`DirectedInfinity" and len(n.elements) == 1 ): - if n.elements[0].get_int_value() > 0: + if n.elements[0].int_value > 0: return CountableInteger("Infinity", upper_limit=True) else: return CountableInteger(0, upper_limit=True) return None # leave original expression unevaluated + @property + def int_value(self) -> int: + assert self._finite + return cast(int, self._integer) + class AtomBuiltin(Builtin): """ @@ -1182,7 +1183,7 @@ def eval_iter_nostep(self, expr, i, imin, imax, evaluation): def eval_iter(self, expr, i, imin, imax, di, evaluation): "%(name)s[expr_, {i_Symbol, imin_, imax_, di_}]" - if isinstance(self, SympyFunction) and di.get_int_value() == 1: + if isinstance(self, SympyFunction) and di.int_value == 1: whole_expr = to_expression( self.get_name(), expr, ListExpression(i, imin, imax) ) diff --git a/mathics/core/definitions.py b/mathics/core/definitions.py index 3059d60813..19efc539fc 100644 --- a/mathics/core/definitions.py +++ b/mathics/core/definitions.py @@ -840,7 +840,7 @@ def get_config_value( SymbolDirectedInfinity, 1 ): return None - return int(value.to_python()) # .get_int_value()) + return int(value.to_python()) # .int_value) def set_config_value(self, name: str, new_value: int) -> None: """Set the (own)value of an integer variable""" diff --git a/mathics/core/expression.py b/mathics/core/expression.py index ecdfbd9d43..f3eeedafcb 100644 --- a/mathics/core/expression.py +++ b/mathics/core/expression.py @@ -1647,7 +1647,7 @@ def to_python(self, *args, **kwargs) -> Any: if head is SymbolDirectedInfinity and len(self._elements) == 1: direction = ( - self._elements[0].get_int_value() + self._elements[0].int_value if isinstance(self._elements[0], Number) else None ) @@ -1840,7 +1840,7 @@ def replace_slots(self, slots, evaluation): if len(self._elements) != 1: evaluation.message_args("Slot", len(self._elements), 1) else: - slot = self._elements[0].get_int_value() + slot = self._elements[0].int_value if slot is None or slot < 0: evaluation.message("Function", "slot", self._elements[0]) elif slot > len(slots) - 1: @@ -1851,7 +1851,7 @@ def replace_slots(self, slots, evaluation): if len(self._elements) != 1: evaluation.message_args("SlotSequence", len(self._elements), 1) else: - slot = self._elements[0].get_int_value() + slot = self._elements[0].int_value if slot is None or slot < 1: evaluation.error("Function", "slot", self._elements[0]) return Expression(SymbolSequence, *slots[slot:]) diff --git a/mathics/core/expression_predefined.py b/mathics/core/expression_predefined.py index a475434ccd..ff870dc487 100644 --- a/mathics/core/expression_predefined.py +++ b/mathics/core/expression_predefined.py @@ -37,7 +37,8 @@ def __init__( if value is not None: self.value = value - def get_int_value(self) -> Optional[int]: + @property + def int_value(self) -> Optional[int]: if isinstance(self.value, int): return self.value return None diff --git a/mathics/core/number.py b/mathics/core/number.py index 7df4f2d03e..c4fa024858 100644 --- a/mathics/core/number.py +++ b/mathics/core/number.py @@ -60,9 +60,9 @@ def __init__(self, name) -> None: def _get_float_inf(value, evaluation) -> Optional[float]: evaluated_value = value.evaluate(evaluation) if evaluated_value.has_form(SymbolDirectedInfinity, 1): - if evaluated_value.elements[0].get_int_value() == 1: + if evaluated_value.elements[0].int_value == 1: return float("inf") - elif evaluated_value.elements[0].get_int_value() == -1: + elif evaluated_value.elements[0].int_value == -1: return float("-inf") else: return None diff --git a/mathics/core/subexpression.py b/mathics/core/subexpression.py index 89ffef33d7..c4b16f99b4 100644 --- a/mathics/core/subexpression.py +++ b/mathics/core/subexpression.py @@ -26,9 +26,9 @@ def _pspec_span_to_tuple(pspec, expr): if len(elements) > 3: raise MessageException("Part", "span", elements) if len(elements) > 0: - start = elements[0].get_int_value() + start = elements[0].int_value if len(elements) > 1: - stop = elements[1].get_int_value() + stop = elements[1].int_value if stop is None: if elements[1].get_name() == "System`All": stop = None @@ -38,7 +38,7 @@ def _pspec_span_to_tuple(pspec, expr): stop = stop - 1 if stop > 0 else len(expr.elements) + stop if len(pspec.elements) > 2: - step = elements[2].get_int_value() + step = elements[2].int_value if start is None or step is None: raise MessageException("Part", "span", pspec) @@ -229,13 +229,13 @@ def __new__(cls, expr, pos=None): # Trivial conversion: if pos is an `Integer`, convert # to a Python native int if type(pos) is Integer: - pos = pos.get_int_value() + pos = pos.int_value # pos == `System`All` elif isinstance(pos, Symbol) and pos.get_name() == "System`All": pos = None elif type(pos) is Expression: if pos.has_form(SymbolList, None): - tuple_pos = [i.get_int_value() for i in pos.elements] + tuple_pos = [i.int_value for i in pos.elements] if any(i is None for i in tuple_pos): raise MessageException("Part", "pspec", pos) pos = tuple_pos diff --git a/mathics/core/symbols.py b/mathics/core/symbols.py index 38c23284ce..547d7649de 100644 --- a/mathics/core/symbols.py +++ b/mathics/core/symbols.py @@ -177,6 +177,14 @@ def copy(self, reevaluate=False) -> "Atom": result.original = self return result + @property + def element_order(self) -> tuple: + """ + Return a tuple value that is used in ordering elements + of an expression. The tuple is ultimately compared lexicographically. + """ + raise NotImplementedError + def equal2(self, rhs: Any) -> Optional[bool]: """Mathics3 two-argument Equal (==) returns True if self and rhs are identical. @@ -226,9 +234,6 @@ def get_head_name(self) -> "str": # 1/0 # return None if stop_on_error else {} - def get_int_value(self) -> Optional[int]: - return None - def get_lookup_name(self) -> str: """ By default, atoms that are not symbols @@ -237,12 +242,8 @@ def get_lookup_name(self) -> str: return self.class_head_name @property - def element_order(self) -> tuple: - """ - Return a tuple value that is used in ordering elements - of an expression. The tuple is ultimately compared lexicographically. - """ - raise NotImplementedError + def int_value(self) -> Optional[int]: + return None @property def pattern_precedence(self) -> tuple: diff --git a/mathics/eval/assignments/assignment.py b/mathics/eval/assignments/assignment.py index 740d177378..19fc3cfc46 100644 --- a/mathics/eval/assignments/assignment.py +++ b/mathics/eval/assignments/assignment.py @@ -571,7 +571,7 @@ def eval_assign_iteration_limit( Set ownvalue for the $IterationLimit symbol. """ - rhs_int_value = rhs.get_int_value() + rhs_int_value = rhs.int_value if ( not rhs_int_value or rhs_int_value < 20 ) and not rhs.get_name() == "System`Infinity": @@ -612,7 +612,7 @@ def eval_assign_line_number_and_history_length( """ lhs_name = lhs.get_name() - rhs_int_value = rhs.get_int_value() + rhs_int_value = rhs.int_value if rhs_int_value is None or rhs_int_value < 0: evaluation.message(lhs_name, "intnn", rhs) raise AssignmentException(lhs, None) @@ -759,7 +759,7 @@ def eval_assign_minprecision( """ lhs_name = lhs.get_name() - rhs_int_value = rhs.get_int_value() + rhs_int_value = rhs.int_value # $MinPrecision = Infinity is not allowed if rhs_int_value is not None and rhs_int_value >= 0: max_prec = evaluation.definitions.get_config_value("$MaxPrecision") @@ -803,8 +803,8 @@ def eval_assign_maxprecision( """ lhs_name = lhs.get_name() - rhs_int_value = rhs.get_int_value() - if rhs.has_form(SymbolDirectedInfinity, 1) and rhs.elements[0].get_int_value() == 1: + rhs_int_value = rhs.int_value + if rhs.has_form(SymbolDirectedInfinity, 1) and rhs.elements[0].int_value == 1: return False if rhs_int_value is not None and rhs_int_value > 0: min_prec = evaluation.definitions.get_config_value("$MinPrecision") @@ -887,7 +887,7 @@ def eval_assign_module_number( """ Set ownvalue for the $ModuleNumber symbol. """ - rhs_int_value = rhs.get_int_value() + rhs_int_value = rhs.int_value if not rhs_int_value or rhs_int_value <= 0: evaluation.message("$ModuleNumber", "set", rhs) raise AssignmentException(lhs, None) @@ -1193,7 +1193,7 @@ def eval_assign_random_state( # from call here mathics.builtin.numbers.randomnumbers import ( # set_random_state, # ) - # set_random_state(rhs.get_int_value()) + # set_random_state(rhs.int_value) # evaluation.message("$RandomState", "rndst", rhs) return False @@ -1205,7 +1205,7 @@ def eval_assign_recursion_limit( """ Set ownvalue for the $RecursionLimit symbol. """ - rhs_int_value = rhs.get_int_value() + rhs_int_value = rhs.int_value # if (not rhs_int_value or rhs_int_value < 20) and not # rhs.get_name() == 'System`Infinity': if ( diff --git a/mathics/eval/drawing/charts.py b/mathics/eval/drawing/charts.py index 76c1a5ede0..97a2f5aff2 100644 --- a/mathics/eval/drawing/charts.py +++ b/mathics/eval/drawing/charts.py @@ -61,7 +61,7 @@ def eval_chart(self, points, evaluation: Evaluation, options: dict): def to_number(x): if isinstance(x, Integer): - return float(x.get_int_value()) + return float(x.int_value) return x.round_to_float(evaluation=evaluation) data = [[to_number(x) for x in group.elements] for group in groups] diff --git a/mathics/eval/list/eol.py b/mathics/eval/list/eol.py index 57d9de47a4..0db5206827 100644 --- a/mathics/eval/list/eol.py +++ b/mathics/eval/list/eol.py @@ -20,7 +20,7 @@ def convert_seq(seq): """ start, stop, step = 1, None, 1 name = seq.get_name() - value = seq.get_int_value() if isinstance(seq, Number) else None + value = seq.int_value if isinstance(seq, Number) else None if name == "System`All": pass elif name == "System`None": @@ -32,16 +32,16 @@ def convert_seq(seq): start = value elif seq.has_form("List", 1, 2, 3): if len(seq.elements) == 1: - start = stop = seq.elements[0].get_int_value() + start = stop = seq.elements[0].int_value if stop is None: return None else: - start = seq.elements[0].get_int_value() - stop = seq.elements[1].get_int_value() + start = seq.elements[0].int_value + stop = seq.elements[1].int_value if start is None or stop is None: return None if len(seq.elements) == 3: - step = seq.elements[2].get_int_value() + step = seq.elements[2].int_value if step is None: return None else: @@ -285,16 +285,16 @@ def parts_span_selector(pspec): stop = None step = 1 if len(pspec.elements) > 0: - start = pspec.elements[0].get_int_value() + start = pspec.elements[0].int_value if len(pspec.elements) > 1: - stop = pspec.elements[1].get_int_value() + stop = pspec.elements[1].int_value if stop is None: if pspec.elements[1].get_name() == "System`All": stop = None else: raise MessageException("Part", "span", pspec) if len(pspec.elements) > 2: - step = pspec.elements[2].get_int_value() + step = pspec.elements[2].int_value if start == 0 or stop == 0: # index 0 is undefined diff --git a/mathics/eval/numbers/algebra/polynomial.py b/mathics/eval/numbers/algebra/polynomial.py index 0c70c26b64..1033996364 100644 --- a/mathics/eval/numbers/algebra/polynomial.py +++ b/mathics/eval/numbers/algebra/polynomial.py @@ -525,7 +525,7 @@ def convert_sympy(expr): "converts top-level to sympy" elements = expr.get_elements() if isinstance(expr, Integer): - return sympy.Integer(expr.get_int_value()) + return sympy.Integer(expr.int_value) if target_pat is not None and not isinstance(expr, Number): if expr.is_free(target_pat, evaluation): return store_sub_expr(expr) @@ -534,11 +534,7 @@ def convert_sympy(expr): if operator is SymbolPower: # sympy won't expand `(a + b) / x` to `a / x + b / x` if denominator is False # if denominator is False we store negative powers to prevent this. - n1 = ( - elements[1].get_int_value() - if isinstance(elements[1], Number) - else None - ) + n1 = elements[1].int_value if isinstance(elements[1], Number) else None if not denominator and n1 is not None and n1 < 0: return store_sub_expr(expr) return tracing.run_sympy( diff --git a/mathics/eval/numbers/calculus/optimizers.py b/mathics/eval/numbers/calculus/optimizers.py index c02ff8b1ba..04e373038a 100644 --- a/mathics/eval/numbers/calculus/optimizers.py +++ b/mathics/eval/numbers/calculus/optimizers.py @@ -192,7 +192,7 @@ def find_root_secant(f, x0, x, opts, evaluation) -> (Number, bool): if maxit is SymbolAutomatic: maxit = 100 else: - maxit = maxit.evaluate(evaluation).get_int_value() + maxit = maxit.evaluate(evaluation).int_value x0 = from_python(region[0]) x1 = from_python(region[1]) diff --git a/mathics/eval/numbers/calculus/series.py b/mathics/eval/numbers/calculus/series.py index 52c090b9d3..cf67ce3496 100644 --- a/mathics/eval/numbers/calculus/series.py +++ b/mathics/eval/numbers/calculus/series.py @@ -340,9 +340,9 @@ def reduce_series_plus(series, terms, x, x0): series, ( data, - nummin.get_int_value(), - nummax.get_int_value(), - den.get_int_value(), + nummin.int_value, + nummax.int_value, + den.int_value, ), ) if new_series: @@ -384,7 +384,7 @@ def build_series( data = [f.replace_vars(vars)] df = f - for i in range(n.get_int_value()): + for i in range(n.int_value): df = Expression(SymbolD, df, x).evaluate(evaluation) newcoeff = df.replace_vars(vars).evaluate(evaluation) factorial = Expression(SymbolFactorial, Integer(i + 1)) @@ -407,7 +407,7 @@ def build_series( ) data.append(newcoeff) data = ListExpression(*data).evaluate(evaluation) - series = reduce_series_trailing_zeros((data, 0, n.get_int_value() + 1, 1)) + series = reduce_series_trailing_zeros((data, 0, n.int_value + 1, 1)) return Expression( SymbolSeriesData, x, diff --git a/mathics/eval/parts.py b/mathics/eval/parts.py index f9796a1bdf..4d4ad6cefc 100644 --- a/mathics/eval/parts.py +++ b/mathics/eval/parts.py @@ -196,7 +196,7 @@ def walk_levels( def python_levelspec(levelspec) -> Tuple[int, Optional[int]]: def value_to_level(expr) -> Optional[int]: - value = expr.get_int_value() if isinstance(expr, Number) else None + value = expr.int_value if isinstance(expr, Number) else None if value is None: if expr.sameQ(MATHICS3_INFINITY): return None diff --git a/mathics/eval/strings.py b/mathics/eval/strings.py index c401c0428c..fc816190a2 100644 --- a/mathics/eval/strings.py +++ b/mathics/eval/strings.py @@ -135,7 +135,7 @@ def convert_rule(r): elif n.sameQ(MATHICS3_INFINITY): py_n = 0 else: - py_n = n.get_int_value() + py_n = n.int_value if py_n is None or py_n < 0: evaluation.message(self.get_name(), "innf", Integer3, expr) return diff --git a/mathics/eval/tensors.py b/mathics/eval/tensors.py index ea9d675c7b..3e7eb4ebe1 100644 --- a/mathics/eval/tensors.py +++ b/mathics/eval/tensors.py @@ -314,7 +314,7 @@ def eval_LeviCivitaTensor(d, type): "Evaluates Levi-Civita tensor of rank d" if isinstance(d, Integer) and type == SymbolSparseArray: - d = d.get_int_value() + d = d.int_value perms = list(permutations(list(range(1, d + 1)))) rules = [ Expression( diff --git a/mathics/format/box/graphics.py b/mathics/format/box/graphics.py index edb6983749..637d1f38dc 100644 --- a/mathics/format/box/graphics.py +++ b/mathics/format/box/graphics.py @@ -741,7 +741,7 @@ def get_image_size( image_size = graphics_options["System`ImageSize"] if isinstance(image_size, Integer): - base_width = image_size.get_int_value() + base_width = image_size.int_value base_height = None # will be computed later in calc_dimensions elif image_size.has_form(SymbolList, 2): base_width, base_height = ( diff --git a/mathics/format/box/numberform.py b/mathics/format/box/numberform.py index 26448870b6..a3638198b0 100644 --- a/mathics/format/box/numberform.py +++ b/mathics/format/box/numberform.py @@ -627,7 +627,7 @@ def _format_exponent( pexp = "" else: method = options["ExponentFunction"] - pexp_val = method(Integer(rexp)).get_int_value() + pexp_val = method(Integer(rexp)).int_value if pexp_val is not None: exp -= pexp_val pexp = str(pexp_val) diff --git a/mathics/format/box/operators.py b/mathics/format/box/operators.py index 829467cbbe..af62bd5ca6 100644 --- a/mathics/format/box/operators.py +++ b/mathics/format/box/operators.py @@ -84,7 +84,7 @@ def eval_postprefix(self, p, expr, h, precedence, form, evaluation): if not isinstance(h, String): h = Expression(SymbolMakeBoxes, h, form) - py_precedence = precedence.get_int_value() + py_precedence = precedence.int_value elements = expr.elements if len(elements) == 1: From 6f543b7cce7414e9c3c3122bc4e9ab87fc67ea28 Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 3 Sep 2026 14:23:07 -0400 Subject: [PATCH 3/6] Add function (not method) get_int_value() --- mathics/builtin/forms/data.py | 17 +++++++++++------ .../builtin/functional/apply_fns_to_lists.py | 4 ++-- mathics/builtin/string/charcodes.py | 4 ++-- mathics/core/atoms/__init__.py | 6 +++++- mathics/core/atoms/numerics.py | 10 ++++++++++ mathics/eval/list/eol.py | 4 ++-- mathics/eval/numbers/algebra/polynomial.py | 3 ++- mathics/eval/parts.py | 4 ++-- 8 files changed, 36 insertions(+), 16 deletions(-) diff --git a/mathics/builtin/forms/data.py b/mathics/builtin/forms/data.py index f1309d2ef8..f8a0c32e8c 100644 --- a/mathics/builtin/forms/data.py +++ b/mathics/builtin/forms/data.py @@ -14,14 +14,19 @@ from mathics.builtin.box.layout import RowBox, StyleBox, SuperscriptBox from mathics.builtin.forms.base import FormBaseClass -from mathics.core.atoms import Integer, Number, Real, String +from mathics.core.atoms import Integer, Real, String, get_int_value from mathics.core.builtin import Builtin from mathics.core.element import BaseElement from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression from mathics.core.number import dps from mathics.core.symbols import Atom, Symbol, SymbolFalse, SymbolNull, SymbolTrue -from mathics.core.systemsymbols import SymbolAutomatic, SymbolInfinity, SymbolMakeBoxes +from mathics.core.systemsymbols import ( + SymbolAutomatic, + SymbolInfinity, + SymbolList, + SymbolMakeBoxes, +) from mathics.eval.strings import eval_StringForm_MakeBoxes, eval_ToString from mathics.format.box import ( StringLParen, @@ -175,12 +180,12 @@ def check_DigitBlock(self, value, evaluation: Evaluation) -> Optional[List[int]] at the left and right of the decimal separator. `None` otherwise. """ - py_value = value.int_value if isinstance(value, Number) else None + py_value = get_int_value(value) if value.sameQ(SymbolInfinity): return [0, 0] if py_value is not None and py_value > 0: return [py_value, py_value] - if value.has_form("List", 2): + if value.has_form(SymbolList, 2): nleft, nright = value.elements py_left, py_right = nleft.int_value, nright.int_value if nleft.sameQ(SymbolInfinity): @@ -363,7 +368,7 @@ def check_SignPadding( def _check_List2str( self, value, msg, evaluation: Evaluation ) -> Optional[List[str]]: - if value.has_form("List", 2): + if value.has_form(SymbolList, 2): result = [element.get_string_value() for element in value.elements] if None not in result: return result @@ -584,7 +589,7 @@ def eval_makeboxes(self, fexpr, form, evaluation): elif isinstance(prec_parms, Integer): if isinstance(target, (Integer, Real)): py_n = prec_parms.value - elif prec_parms.has_form("List", 2): + elif prec_parms.has_form(SymbolList, 2): if isinstance(target, (Integer, Real)): n, f = prec_parms.elements py_n = n.value diff --git a/mathics/builtin/functional/apply_fns_to_lists.py b/mathics/builtin/functional/apply_fns_to_lists.py index 89159fc8bc..ad0e5f56c5 100644 --- a/mathics/builtin/functional/apply_fns_to_lists.py +++ b/mathics/builtin/functional/apply_fns_to_lists.py @@ -11,7 +11,7 @@ from dataclasses import replace as dc_replace from typing import Iterable -from mathics.core.atoms import Integer, Integer0, Integer1, Integer3, Number +from mathics.core.atoms import Integer, Integer0, Integer1, Integer3, get_int_value from mathics.core.builtin import Builtin, InfixOperator from mathics.core.convert.expression import to_mathics_list from mathics.core.evaluation import Evaluation @@ -384,7 +384,7 @@ def eval_n(self, f, expr, n, evaluation): full_expr = Expression(SymbolMapThread, f, expr) else: full_expr = Expression(SymbolMapThread, f, expr, n) - n = n.int_value if isinstance(n, Number) else None + n = get_int_value(n) if n is None or n < 0: evaluation.message("MapThread", "intnm", Integer3, full_expr) diff --git a/mathics/builtin/string/charcodes.py b/mathics/builtin/string/charcodes.py index 3eac0df331..c038c2b055 100644 --- a/mathics/builtin/string/charcodes.py +++ b/mathics/builtin/string/charcodes.py @@ -5,7 +5,7 @@ import sys -from mathics.core.atoms import Integer, Integer1, Number, String +from mathics.core.atoms import Integer, Integer1, String, get_int_value from mathics.core.builtin import Builtin from mathics.core.convert.expression import to_mathics_list from mathics.core.evaluation import Evaluation @@ -177,7 +177,7 @@ def convert_codepoint_list(li): if encoding == "Unicode": s = "" for i, ni in enumerate(li): - pyni = ni.int_value if isinstance(ni, Number) else None + pyni = get_int_value(ni) if not (pyni is not None and 0 <= pyni <= 0xFFFF): evaluation.message( "FromCharacterCode", diff --git a/mathics/core/atoms/__init__.py b/mathics/core/atoms/__init__.py index 876a01bf4b..08569d183f 100644 --- a/mathics/core/atoms/__init__.py +++ b/mathics/core/atoms/__init__.py @@ -2,6 +2,8 @@ Mathics3 Atoms from which compound Mathics3 compound Expressions are made of. """ +from typing import Final + from mathics.core.atoms.arrays import ByteArray, NumericArray from mathics.core.atoms.numerics import ( COMPARE_PREC, @@ -29,12 +31,13 @@ RationalOneHalf, Real, SymbolI, + get_int_value, is_integer_rational_or_real, min_prec, ) from mathics.core.atoms.strings import String, StringFromPython -__all__ = [ +__all__: Final[list[str]] = [ "ByteArray", "COMPARE_PREC", "Complex", @@ -65,6 +68,7 @@ "String", "StringFromPython", "SymbolI", + "get_int_value", "is_integer_rational_or_real", "min_prec", ] diff --git a/mathics/core/atoms/numerics.py b/mathics/core/atoms/numerics.py index 62861c8ffe..c45c1c842d 100644 --- a/mathics/core/atoms/numerics.py +++ b/mathics/core/atoms/numerics.py @@ -1101,6 +1101,16 @@ def user_hash(self, update) -> None: } +def get_int_value(element) -> Optional[int]: + """ + Return the rounded (or exact) integer value of "element" if it is + a dataype that could be interpreted as a Python int. + + Otherwise, return None. + """ + return element.int_value if hasattr(element, "int_value") else None + + def is_integer_rational_or_real(expr) -> bool: """ Return True is expr is either an Integer, Rational, or Real. diff --git a/mathics/eval/list/eol.py b/mathics/eval/list/eol.py index 0db5206827..7738ce3e88 100644 --- a/mathics/eval/list/eol.py +++ b/mathics/eval/list/eol.py @@ -4,7 +4,7 @@ from typing import List -from mathics.core.atoms import Integer, Number +from mathics.core.atoms import Integer, get_int_value from mathics.core.evaluation import Evaluation from mathics.core.exceptions import MessageException from mathics.core.expression import Expression @@ -20,7 +20,7 @@ def convert_seq(seq): """ start, stop, step = 1, None, 1 name = seq.get_name() - value = seq.int_value if isinstance(seq, Number) else None + value = get_int_value(seq) if name == "System`All": pass elif name == "System`None": diff --git a/mathics/eval/numbers/algebra/polynomial.py b/mathics/eval/numbers/algebra/polynomial.py index 1033996364..3ad2a55a54 100644 --- a/mathics/eval/numbers/algebra/polynomial.py +++ b/mathics/eval/numbers/algebra/polynomial.py @@ -14,6 +14,7 @@ IntegerM1, Number, RationalOneHalf, + get_int_value, ) from mathics.core.convert.sympy import from_sympy from mathics.core.element import BaseElement @@ -534,7 +535,7 @@ def convert_sympy(expr): if operator is SymbolPower: # sympy won't expand `(a + b) / x` to `a / x + b / x` if denominator is False # if denominator is False we store negative powers to prevent this. - n1 = elements[1].int_value if isinstance(elements[1], Number) else None + n1 = get_int_value(elements[1]) if not denominator and n1 is not None and n1 < 0: return store_sub_expr(expr) return tracing.run_sympy( diff --git a/mathics/eval/parts.py b/mathics/eval/parts.py index 4d4ad6cefc..57ec64dbbb 100644 --- a/mathics/eval/parts.py +++ b/mathics/eval/parts.py @@ -6,7 +6,7 @@ from typing import List, Optional, Tuple -from mathics.core.atoms import Integer, Number +from mathics.core.atoms import Integer, get_int_value from mathics.core.convert.expression import make_expression from mathics.core.element import BaseElement, BoxElementMixin from mathics.core.exceptions import ( @@ -196,7 +196,7 @@ def walk_levels( def python_levelspec(levelspec) -> Tuple[int, Optional[int]]: def value_to_level(expr) -> Optional[int]: - value = expr.int_value if isinstance(expr, Number) else None + value = get_int_value(expr) if value is None: if expr.sameQ(MATHICS3_INFINITY): return None From ac2c82e1659dbb9bec829ef1613c652dd84745ea Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 3 Sep 2026 16:01:41 -0400 Subject: [PATCH 4/6] Replace CountableInteger casts with assert. However the definition of probably could be improved to redu handling "Infinity". --- mathics/core/builtin.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/mathics/core/builtin.py b/mathics/core/builtin.py index b275d870b9..549e233acd 100644 --- a/mathics/core/builtin.py +++ b/mathics/core/builtin.py @@ -746,7 +746,7 @@ def get_constant(self, precision, evaluation, have_mpmath=False): else: return PrecisionReal(sympy_fn.n(d)) - def get_sympy_function(self, elements=None) -> Optional[Callable]: + def get_sympy_function(self, _elements=None) -> Optional[Callable]: if self.sympy_name: return getattr(sympy, self.sympy_name) return None @@ -994,24 +994,26 @@ def is_upper_limit(self) -> bool: def __eq__(self, other) -> bool: if isinstance(other, CountableInteger): if self._finite: - return other._finite and cast(int, self._integer) == other._integer + assert isinstance(self._integer, int) + return other._finite and self._integer == other._integer else: return not other._finite elif isinstance(other, int): - return self._finite and cast(int, self._integer) == other + assert isinstance(self._integer, int) + return self._finite and self._integer == other else: return False def __lt__(self, other) -> bool: if isinstance(other, CountableInteger): if self._finite: - return other._finite and cast(int, self._integer) < cast( - int, other._integer - ) + assert isinstance(self._integer, int) + return other._finite and self._integer < cast(int, other._integer) else: return False elif isinstance(other, int): - return self._finite and cast(int, self._integer) < other + assert isinstance(self._integer, int) + return self._finite and self._integer < other else: return False @@ -1055,8 +1057,8 @@ def from_expression(expr): @property def int_value(self) -> int: - assert self._finite - return cast(int, self._integer) + assert self._finite and isinstance(self._integer, int) + return self._integer class AtomBuiltin(Builtin): From fff169af3a68529363e4733f216974a20e72eaaf Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 3 Sep 2026 16:22:31 -0400 Subject: [PATCH 5/6] Consoldate assert tests into `int_value` --- mathics/core/builtin.py | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/mathics/core/builtin.py b/mathics/core/builtin.py index 549e233acd..ce93349562 100644 --- a/mathics/core/builtin.py +++ b/mathics/core/builtin.py @@ -14,7 +14,18 @@ from functools import total_ordering from itertools import chain from types import ModuleType -from typing import Any, Callable, Iterable, List, Optional, Sequence, Tuple, Union, cast +from typing import ( + Any, + Callable, + Iterable, + List, + Literal, + Optional, + Sequence, + Tuple, + Union, + cast, +) import mpmath import sympy @@ -975,7 +986,7 @@ class CountableInteger: # _support_infinity to False. _finite: bool _upper_limit: bool - _integer: Union[str, int, None] + _integer: Union[int, Literal["Infinity"], None] _support_infinity = False def __init__(self, value: Union[int, str] = "Infinity", upper_limit=True): @@ -994,26 +1005,22 @@ def is_upper_limit(self) -> bool: def __eq__(self, other) -> bool: if isinstance(other, CountableInteger): if self._finite: - assert isinstance(self._integer, int) - return other._finite and self._integer == other._integer + return other._finite and self.int_value == other._integer else: return not other._finite elif isinstance(other, int): - assert isinstance(self._integer, int) - return self._finite and self._integer == other + return self._finite and self.int_value == other else: return False def __lt__(self, other) -> bool: if isinstance(other, CountableInteger): if self._finite: - assert isinstance(self._integer, int) - return other._finite and self._integer < cast(int, other._integer) + return other._finite and self.int_value < other.int_value else: return False elif isinstance(other, int): - assert isinstance(self._integer, int) - return self._finite and self._integer < other + return self._finite and self.int_value < other else: return False @@ -1057,7 +1064,17 @@ def from_expression(expr): @property def int_value(self) -> int: - assert self._finite and isinstance(self._integer, int) + """ + Get the Python int value for a CountableInteger. + The caller should ensure that self is an integer, as opposed + to None or Infinity. + """ + assert ( + self._finite + ), "int_value does not make sense for infinite CountableInteger" + assert isinstance( + self._integer, int + ), f"int_value should only be called when we have an integer; we have in {self}, {self._integer}" return self._integer From 386125ca43a1532ac5b442323f32ec6752ac0a35 Mon Sep 17 00:00:00 2001 From: "R. Bernstein" Date: Thu, 3 Sep 2026 16:36:45 -0400 Subject: [PATCH 6/6] Fix comments for clarity and consistency --- mathics/core/atoms/numerics.py | 38 ++++++++++++++++------------------ mathics/core/element.py | 15 ++++++++++++++ 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/mathics/core/atoms/numerics.py b/mathics/core/atoms/numerics.py index c45c1c842d..0aa7a9b926 100644 --- a/mathics/core/atoms/numerics.py +++ b/mathics/core/atoms/numerics.py @@ -33,7 +33,7 @@ SymbolInputForm, ) -# The below value is an empirical number for comparison precedence +# The value below is an empirical number for comparison precedence # that seems to work. We have to be able to match mpmath values with # sympy values COMPARE_PREC = 50 @@ -63,7 +63,7 @@ def __getnewargs__(self) -> tuple: __getnewargs__ is used in pickle loading to ensure __new__ is called with the right value. - Most of the time a number takes one argument - its value + Most of the time, a number takes one argument - its value When there is a kind of number, like Rational or Complex, that has more than one argument, it should define this method accordingly. @@ -166,7 +166,7 @@ def to_python(self, *_, **kwargs): @property def value(self) -> T: """Equivalent value in either SymPy's or Python's native - datatype if that exist. Note the SymPy value + datatype if that exists. Note that the SymPy value and the Python value might be the same thing. """ return self._value @@ -337,18 +337,17 @@ def round(self, d: Optional[int] = None) -> Union["MachineReal", "PrecisionReal" 1024. 1024 is a common internal Mathematica implementation limit where it switches from using MachineReal to PrecisionReal. - If a decimal precision ``d`` is not None, then we convert to + If a decimal precision ``d`` isn't ``None``, then we convert to a PrecisionReal using that value d. When ``d`` is ``None`` but the mantissa does not fit into a - Python float, we implement the value as a mpmath.mpf value. + Python float, we implement the value as an mpmath.mpf value. """ if d is None: d = self.value.bit_length() # Many WMA implementations seem to change behavior of the integer - # representation that has more than 1024 digits. In theory, this is - # number can vary depending on hardware characteristics. - # In practice, a reasonable + # representation that has more than 1024 digits. In theory, this number can vary depending + # on hardware characteristics. if d <= 1024: return MachineReal(self.value) else: @@ -384,7 +383,7 @@ def user_hash(self, update): IntegerM1 = Integer(-1) -# This has to come before Complex which uses Real. +# This has to come before Complex, which uses Real. class Real(Number[T]): class_head_name = "System`Real" @@ -569,7 +568,7 @@ def is_zero(self) -> bool: def sameQ(self, rhs) -> bool: """Mathics3 SameQ for MachineReal. If the rhs comparison value is a MachineReal, the values - have to be equal. If the rhs value is a PrecisionReal though, then + have to be equal. If the rhs value is a PrecisionReal, though, then the two values have to be within 1/2 ** (precision) of rhs-value's precision. For any rhs type, sameQ is False. """ @@ -617,7 +616,7 @@ class PrecisionReal(Real[sympy_Float]): # Dictionary of PrecisionReal constant values defined so far. # We use this for object uniqueness. - # The key is the PrecisionReal's sympy.Float, and the + # The key is the PrecisionReal's `sympy.Float`, and the # dictionary's value is the corresponding Mathics3 PrecisionReal object. _precision_reals: Dict[Any, "PrecisionReal"] = {} @@ -733,7 +732,7 @@ class Complex(Number[Tuple[Number[T], Number[T], Optional[int]]]): Note that Mathics3 complex values are more precise than complex values in Python, NumPy, or mpmath. Both the Real and Imaginary parts can be Mathics3-kinds of numbers, as opposed to a generic - floating point number (which does not distinguish exact from approximate + floating-point number (which does not distinguish exact from approximate values like an integer does). Also, there can be a precision associated with a Mathics3 complex number. """ @@ -746,7 +745,7 @@ class Complex(Number[Tuple[Number[T], Number[T], Optional[int]]]): # Dictionary of Complex constant values defined so far. # We use this for object uniqueness. # The key is the Complex value's real and imaginary parts as a tuple, - # dictionary's value is the corresponding Mathics3 Complex object. + # the dictionary's value is the corresponding Mathics3 Complex object. _complex_numbers: Dict[Any, "Complex"] = {} # The precise value: a real number, an imaginary number, and a @@ -758,7 +757,7 @@ class Complex(Number[Tuple[Number[T], Number[T], Optional[int]]]): _value: complex # We use __new__ here to ensure that two Complex number that have - # down to the type on the imaginary and real parts and precision of those -- + # down to the type of the imaginary and real parts and the precision of those -- # the same value return the same object, and to set an object hash # value. Consider also @lru_cache, and mechanisms for limiting # and clearing the cache and the object store which might be @@ -777,7 +776,7 @@ def __new__(cls, real, imag): # Note: for the below test, imag.value == 0 catches more # reals. In particular, MachineReals that have an imaginary - # value of floating point 0.0. But MachineReal 0.0 is "approximate 0", + # value of floating-point 0.0. But MachineReal 0.0 is "approximate 0", # not exactly 0. So "Complex[0., 0.]" is "0. + 0." and not "0." if imag.sameQ(Integer0): return real @@ -882,7 +881,7 @@ def element_order(self) -> tuple: """ order_real, order_imag = self.real.element_order, self.imag.element_order - # If the real of the imag parts are real numbers, sort according + # If the real or the imaginary parts are real numbers, sort according # the minimum precision. # Example: # Sort[{1+2I, 1.+2.I, 1.`4+2.`5I, 1.`2+2.`7 I}] @@ -902,7 +901,7 @@ def get_float_value( def get_precision(self) -> Optional[int]: """Returns the default specification for precision in N and other numerical functions. - When `None` is be returned no precision is has been defined and this object's value is + When `None` is returned, no precision has been defined, and this object's value is exact. This function is called by method `is_inexact()`. @@ -1103,8 +1102,7 @@ def user_hash(self, update) -> None: def get_int_value(element) -> Optional[int]: """ - Return the rounded (or exact) integer value of "element" if it is - a dataype that could be interpreted as a Python int. + Return the integer value of "element" if it is a data type that could be interpreted as a Python int. Otherwise, return None. """ @@ -1113,6 +1111,6 @@ def get_int_value(element) -> Optional[int]: def is_integer_rational_or_real(expr) -> bool: """ - Return True is expr is either an Integer, Rational, or Real. + Return True if expr is either an Integer, Rational, or Real. """ return isinstance(expr, (Integer, Rational, Real)) diff --git a/mathics/core/element.py b/mathics/core/element.py index 23c6d02a5d..35b0b44871 100644 --- a/mathics/core/element.py +++ b/mathics/core/element.py @@ -215,6 +215,9 @@ def get_option_values( ) -> Optional[dict]: pass + # FIXME: this should be a *function* in mathics.core.atom.numeric.Number. + # It should be a method *only* in Numeric (or Symbol) classes where it + # makes sense. def get_precision(self) -> Optional[int]: """Returns the default specification for precision in N and other numerical functions. It is expected to be redefined in those @@ -273,10 +276,16 @@ def is_uncertain_final_definitions(self, definitions) -> bool: """ raise NotImplementedError + # FIXME: this should be a *function* in mathics.core.atom.numeric.Number. + # It should be a method *only* in Numeric (or Symbol) classes where it + # makes sense. def is_machine_precision(self) -> bool: """Check if the number represents a floating point number""" return False + # FIXME: this should be a *function* in mathics.core.atom.numeric.Number. + # It should be a method *only* in Numeric (or Symbol) classes where it + # makes sense. def is_numeric(self, evaluation=None) -> bool: """Check if the expression is a number. If evaluation is given, tries to determine if the expression can be evaluated as a number. @@ -295,6 +304,9 @@ def has_form( """ return False + # FIXME: this should be a *function* in mathics.core.atom.numeric.Number. + # It should be a method *only* in Numeric (or Symbol) classes where it + # makes sense. @property def is_zero(self) -> bool: return False @@ -307,6 +319,9 @@ def is_free(self, form, evaluation) -> bool: return item_is_free(self, form, evaluation) + # FIXME: this should be a *function* in mathics.core.atom.numeric.Number. + # It should be a method *only* in Numeric (or Symbol) classes where it + # makes sense. def is_inexact(self) -> bool: return self.get_precision() is not None