Skip to content

IntegerMod ​

k mod nk \bmod n as a VALUE, after Sage's Mod(k, n): ResidueClass whose classes of different moduli combine in Z/gcd⁡(m,n)\mathbb{Z}/\gcd(m, n).

IntegerMod(k, n)the class of kk, normalised into [0,n)[0, n), as for ResidueClass(k, n)
SageMathMod(k, n)SymPyGF(n, symmetric=False)(k)
IntegerMod(u/v, n)a rational reads as u⋅v−1u \cdot v^{-1}, when vv is a unit mod nn
SageMathMod(u/v, n)SymPyGF(n, symmetric=False)(u/v)
Typed signatures
TypePackageApplies
(any, any) -> valueresiduesalways

Domain: Modular arithmetic

Details
  • The Sage-flavoured sibling of ResidueClass, which is compute-engine's strict head and never combines classes of two moduli. IntegerMod is built on it: same normalisation, same ring arithmetic, and ChineseRemainder, MultiplicativeOrder and membership in QuotientRing(Integers, n) read it as the class it is
  • Two classes meet in Z/gcd⁡(m,n)\mathbb{Z}/\gcd(m, n), the largest ring both reduce to, and the answer lives there: (2 mod 4)+(1 mod 6)=1 mod 2(2 \bmod 4) + (1 \bmod 6) = 1 \bmod 2. This is Sage's coercion, and the divergence from compute-engine, which leaves that sum as written
  • A bare integer next to a class is read in the class's ring, never the other way: (2 mod 4)⋅5=2 mod 4(2 \bmod 4) \cdot 5 = 2 \bmod 4
  • Equality and != compare in the common ring too, so IntegerMod(2, 4) == IntegerMod(0, 2) is True
  • Moduli with gcd⁡=1\gcd = 1 have no ring but the trivial one, which Sage rejects; the call stays as written. Dividing by a class that is not a unit in the common ring stays unevaluated too, with a ResidueClass::ninv message
  • A ResidueClass next to an IntegerMod never combines: pick one head, as the two behaviours differ, and the sum stays as written
  • Mod and IntegerMod differ: Mod(17, 5) is the remainder 22, a plain number, while IntegerMod(17, 5) is the class 2 mod 52 \bmod 5 and keeps its modulus. Sage's Mod(a, m) builds a class, so it is IntegerMod(a, m) here, and compute-engine's Mod follows Wolfram's
  • Written and read as (a  mod  m)(a\;\mathrm{mod}\;m), fenced whole so sums and products of classes stay unambiguous. a \pmod{n} reads as ResidueClass and a \bmod n as Mod, so type this form or the call to get an IntegerMod

Examples

17 more kept as data, checked against the oracles
Basic #
live ↗
In(10  mod  7)({10}\;\mathrm{mod}\;7)Out(3  mod  7)(3\;\mathrm{mod}\;7)
Scope #

classes of different moduli meet in Z/gcd⁡(4,6)\mathbb{Z}/\gcd(4, 6): the sum is 1 mod 2, as in Sage

live ↗
In(2  mod  4)+(1  mod  6)(2\;\mathrm{mod}\;4)+(1\;\mathrm{mod}\;6)Out(1  mod  2)(1\;\mathrm{mod}\;2)
live ↗
In(2  mod  4)(1  mod  6)(2\;\mathrm{mod}\;4)(1\;\mathrm{mod}\;6)Out(0  mod  2)(0\;\mathrm{mod}\;2)

2 mod 4 and 0 mod 2 agree in Z/2\mathbb{Z}/2

live ↗
In(2  mod  4)=(0  mod  2)(2\;\mathrm{mod}\;4)=(0\;\mathrm{mod}\;2)OutTrue\mathrm{True}

the integer reads in Z/7\mathbb{Z}/7, so the answer keeps the modulus

live ↗
In5(3  mod  7)5(3\;\mathrm{mod}\;7)Out(1  mod  7)(1\;\mathrm{mod}\;7)

3100 mod 73^{100} \bmod 7, reduced without forming the integer

live ↗
In((3  mod  7))100((3\;\mathrm{mod}\;7))^{100}Out(4  mod  7)(4\;\mathrm{mod}\;7)

every step stays in Z/7\mathbb{Z}/7: ((5+4)⋅3+6)3=6((5 + 4)\cdot 3 + 6)^3 = 6

live ↗
In(((5  mod  7)+(4  mod  7))(3  mod  7)+(6  mod  7))3(((5\;\mathrm{mod}\;7)+(4\;\mathrm{mod}\;7))(3\;\mathrm{mod}\;7)+(6\;\mathrm{mod}\;7))^3Out(6  mod  7)(6\;\mathrm{mod}\;7)

Mod gives the remainder, a plain integer; IntegerMod(17, 5) is the class and keeps its modulus

live ↗
In17 mod 517\bmod5Out22
Possible issues #

gcd(4, 7) = 1: Sage rejects the sum, and so does this

live ↗
In(3  mod  4)+(5  mod  7)(3\;\mathrm{mod}\;4)+(5\;\mathrm{mod}\;7)Out(3  mod  4)+(5  mod  7)(3\;\mathrm{mod}\;4)+(5\;\mathrm{mod}\;7)

the divisor is 0 in Z/2\mathbb{Z}/2, not a unit

live ↗
In(1  mod  6)(2  mod  4)\frac{(1\;\mathrm{mod}\;6)}{(2\;\mathrm{mod}\;4)}Out(1  mod  6)(2  mod  4)\frac{(1\;\mathrm{mod}\;6)}{(2\;\mathrm{mod}\;4)}

the strict head leaves it unevaluated; IntegerMod combines the same classes in Z/2\mathbb{Z}/2 (see above)

live ↗
In2‾4+(1‾6)\overline{2}_{4}+(\overline{1}_{6})Out2‾4+(1‾6)\overline{2}_{4}+(\overline{1}_{6})
About
Examples28
Checked againstSageMath 23 agree2 differ2 errorSymPy 16 agree8 differ1 error
CrosswalkSageMathSymPy

Implementation

mappedwolframpackages/oracle/src/mappings.ts

Wolfram has no residue value that follows Sage's coercion: Mod/PowerMod answer a plain Integer, and FiniteField[n] keeps a residue as a persistent value but only for prime n (FiniteField[4] is GF(2^2), not Z/4Z), with no coercion between fields.

mappedsagepackages/oracle/src/mappings.ts
mappedsympypackages/oracle/src/mappings.ts

SymPy's Mod is the plain remainder; the residue value is the element of GF(n), which for a composite n is Z/n. A class of one modulus does not combine with one of another, where Sage's coercion takes them to Z/gcd. Power and Divide over a residue skip their S() wrap (emit.ts), which would lift a class to its integer.

See also: ResidueClass, QuotientRing, Mod, ChineseRemainder