Modular arithmetic: Difference between revisions

Line 745:
'''Works with gojq, the Go implementation of jq'''
 
This entry focuses on the requirement that the function, f, "should behave the same way with normal and modular integers."
'''Adapted from [[#C|C]]'''
 
To illustrate that the function `ring::f` defined here does satisfy this requirement, we will evaluate it at both the integer 1 and the
The following presentation uses jq's support for modules and includes some error-checking.
element «10 % 13» of Z/13Z.
 
To keep the distinctions between functions defined on different
If all the functions are placed in a file, say "modint.jq", we can
types clear, this entry uses jq's support for name
then execute the function named "main" by first importing the
spaces. Specifically, we will use the prefix "modint::" for the
module, and then prefixing the function name with the name of the
modular arithmetic functions, and "ring::" for the generic ring
module:
functions.
<lang jq>import "modint" as modint {search: "."};
modint::main</lang>
'''module "modint"'''
<lang jq>
module {name: "modint"};
 
Since jq supports neither redefining any of the symbolic operators
# In this module, "ModularArithmetic" objects are represented by JSON objects of the form: {value, mod}.
(such as "+") nor dynamic dispatch, ring functions (such as
# The function modint::assert/0 checks the input is of this form with integer values.
`ring::add`) must be written with the specific rings that are to be
supported in mind.
 
# '''Preliminaries'''
<lang jq>def assert($e; $msg): if $e then . else "assertion violation @ \($msg)" | error end;
 
def is_integer: type=="number" and floor == .;
 
# To take advantage of gojq's arbitrary-precision integer arithmetic:
def assert:
def power($b): . as $in | reduce range(0;$b) as $i (1; . * $in);
</lang jq>
'''Modular Arithmetic'''
<lang jq># In this module, "ModularArithmetic" objects are represented by JSON objects of the form: {value, mod}.
# The function modint::assert/0 checks the input is of this form with integer values.
 
def is_modint: type=="object" and has("value") and has("mod");
 
def modint::assert:
assert(type=="object"; "object expected")
| assert(has("value"); "object should have a value")
Line 774 ⟶ 782:
| assert(.mod | is_integer; "mod should be an integer");
 
#def modint::make($value; $mod):
def make($value; $mod):
assert($value|is_integer; "value should be an integer")
| assert($mod|is_integer; "mod should be an integer")
| { value: ($value % $mod), mod: $mod};
 
def modint::add($modintAA; $B):
if ($B|type) == "object"
then assert($modintAA.mod == $B.mod ; "modint::add")
| modint::make( $modintAA.value + $B.value; $modintAA.mod )
else modint::make( $modintAA.value + $B; $modintAA.mod )
end;
 
def modint::mul($modintAA; $B):
if ($B|type) == "object"
then assert($modintAA.mod == $B.mod ; "mul")
| modint::make( $modintAA.value * $B.value; $modintAA.mod )
else modint::make( $modintAA.value * $B; $modintAA.mod )
end;
 
def modint::pow($modintAA; $pow):
assert($pow | is_integer; "pow")
| reduce range(0; $pow) as $i ( modint::make(1; $modintAA.mod);
modint::mul( .; $modintAA) );
 
# pretty print
def modint::pp: "«\(.value) % \(.mod)»";</lang>
''' Ring Functions'''
<lang jq>def ring::add($A; $B):
if $A|is_modint then modint::add($A; $B)
elif $A|is_integer then $A + $B
else "ring::add" | error
end;
 
def fring::mul($xA; $B):
if $A|is_modint then modint::mul($A; $B)
add( add( pow($x; 100); $x); 1);
elif $A|is_integer then $A * $B
else "ring::mul" | error
end;
 
def ring::pow($A; $B):
if $A|is_modint then modint::pow($A; $B)
elif $A|is_integer then $A|power($B)
else "ring::pow" | error
end;
 
def ring::pp:
if is_modint then modint::pp
elif is_integer then .
else "ring::pp" | error
end;
 
def mainring::f($x):
ring::add( ring::add( ring::pow($x; 100); $x); 1);</lang>
make(10;13)
'''Evaluating ring::f'''
| f(.) as $out
<lang jq>def main:
| "f(\(pp)) => \($out|pp)";</lang>
(ring::f(1) | "f(\(1)) => \(.)"),
(modint::make(10;13)
| ring::f(.) as $out
| "f(\(ring::pp)) => \($out|ring::pp)");</lang>
{{out}}
<pre>
f(1) => 3
f(«10 % 13») => «1 % 13»
</pre>
2,465

edits