57 lines
1.6 KiB
Plaintext
57 lines
1.6 KiB
Plaintext
%% -*- mode: mercury; prolog-indent-width: 2; -*-
|
|
|
|
:- module modular_arithmetic_task.
|
|
:- interface.
|
|
:- import_module io.
|
|
:- pred main(io::di, io::uo) is det.
|
|
|
|
:- implementation.
|
|
:- import_module exception.
|
|
:- import_module integer.
|
|
|
|
:- type modular_integer
|
|
---> modular(integer, integer)
|
|
; ordinary(integer).
|
|
|
|
:- func operate((func(integer, integer) = integer),
|
|
modular_integer, modular_integer) = modular_integer.
|
|
operate(OP, modular(A, M1), modular(B, M2)) = C :-
|
|
if (M1 = M2)
|
|
then (C = modular(mod(OP(A, B), M1), M1))
|
|
else throw("mismatched moduli").
|
|
operate(OP, modular(A, M), ordinary(B)) = C :-
|
|
C = modular(mod(OP(A, B), M), M).
|
|
operate(OP, ordinary(A), modular(B, M)) = C :-
|
|
C = modular(mod(OP(A, B), M), M).
|
|
operate(OP, ordinary(A), ordinary(B)) = C :-
|
|
C = ordinary(OP(A, B)).
|
|
|
|
:- func '+'(modular_integer, modular_integer) = modular_integer.
|
|
(A : modular_integer) + (B : modular_integer) = operate(+, A, B).
|
|
|
|
:- func pow(modular_integer, modular_integer) = modular_integer.
|
|
pow(A : modular_integer, B : modular_integer) = operate(pow, A, B).
|
|
|
|
:- pred display(modular_integer::in, io::di, io::uo) is det.
|
|
display(X, !IO) :-
|
|
if (X = modular(A, _)) then print(A, !IO)
|
|
else if (X = ordinary(A)) then print(A, !IO)
|
|
else true.
|
|
|
|
:- func f(modular_integer) = modular_integer.
|
|
f(X) = Y :-
|
|
Y = pow(X, ordinary(integer(100))) + X
|
|
+ ordinary(integer(1)).
|
|
|
|
main(!IO) :-
|
|
X1 = ordinary(integer(10)),
|
|
X2 = modular(integer(10), integer(13)),
|
|
print("No modulus: ", !IO),
|
|
display(f(X1), !IO),
|
|
nl(!IO),
|
|
print("modulus 13: ", !IO),
|
|
display(f(X2), !IO),
|
|
nl(!IO).
|
|
|
|
:- end_module modular_arithmetic_task.
|