1 | initial version |

Let us do the search explicitly. The `multiplicative_order`

function cited in the question, applied on some object `x`

delegates the work to the *method* with the same name of the object `x`

, if any. In our case, this is - using a sample ring -

```
N = 202200002022
Z = IntegerModRing(N)
x = Z(101)
print(x.multiplicative_order())
```

We get

```
5882352
```

and the question is why. So let us ask for

```
sage: ??x.multiplicative_order
```

with the object `x`

being the unit above, and we get the source and the location, here truncated info:

```
Source:
def multiplicative_order(self):
"""...
"""
try:
return sage.rings.integer.Integer(self.__pari__().znorder())
except PariError:
raise ArithmeticError("multiplicative order of %s not defined since it is not a unit modulo %s"%(
self, self.__modulus.sageInteger))
File: /usr/lib/python3.10/site-packages/sage/rings/finite_rings/integer_mod.pyx
```

So the code delegates the work to pari, and effectuates basicly

```
sage: x.__pari__()
Mod(101, 202200002022)
sage: x.__pari__().znorder()
5882352
sage: type(_)
<class 'cypari2.gen.Gen'>
```

and the obtained number is converted to a specific class, so that sage can handle it in the sequel.

2 | No.2 Revision |

Let us do the search explicitly. The `multiplicative_order`

function cited in the question, applied on some object `x`

delegates the work to the *method* with the same name of the object `x`

, if any. In our case, this is - using a sample ring -

```
N = 202200002022
Z = IntegerModRing(N)
x = Z(101)
print(x.multiplicative_order())
```

We get

```
5882352
```

and the question is why. So let us ask for

```
sage: ??x.multiplicative_order
```

with the object `x`

being the unit above, and we get the source and the location, here truncated info:

```
Source:
def multiplicative_order(self):
"""...
"""
try:
return sage.rings.integer.Integer(self.__pari__().znorder())
except PariError:
raise ArithmeticError("multiplicative order of %s not defined since it is not a unit modulo %s"%(
self, self.__modulus.sageInteger))
File: /usr/lib/python3.10/site-packages/sage/rings/finite_rings/integer_mod.pyx
```

So the code delegates the work to pari, and effectuates basicly

```
sage: x.__pari__()
Mod(101, 202200002022)
sage: x.__pari__().znorder()
5882352
sage: type(_)
<class 'cypari2.gen.Gen'>
```

and the obtained number is converted to a specific class, so that sage can handle it in the sequel.

So the algorithm used is inside `pari/gp`

, the corresponding call in there would be:

```
[dan@k9 ~]$ gp
GP/PARI CALCULATOR Version 2.13.4 (released)
amd64 running linux (x86-64/GMP-6.2.1 kernel) 64-bit version
compiled: Apr 5 2022, gcc version 11.2.0 (GCC)
threading engine: pthread
(readline v8.1 enabled, extended help enabled)
Copyright (C) 2000-2020 The PARI Group
PARI/GP is free software, covered by the GNU General Public License, and comes WITHOUT ANY WARRANTY
WHATSOEVER.
Type ? for help, \q to quit.
Type ?17 for how to get moral (and possibly technical) support.
parisize = 8000000, primelimit = 500000, nbthreads = 8
? x = Mod(101, 202200002022)
%1 = Mod(101, 202200002022)
? znorder(x)
%2 = 5882352
?
```

Copyright Sage, 2010. Some rights reserved under creative commons license. Content on this site is licensed under a Creative Commons Attribution Share Alike 3.0 license.