From: notoria Date: Sat, 2 May 2020 01:36:01 +0000 (+0200) Subject: Implemented expmod/4 X-Git-Tag: v0.8.123~71^2^2 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=7df7901532bbf320830371eaebf404db0f2531da;p=scryer-prolog.git Implemented expmod/4 --- diff --git a/src/prolog/lib/arithmetic.pl b/src/prolog/lib/arithmetic.pl index d367d365..f0d2b58e 100644 --- a/src/prolog/lib/arithmetic.pl +++ b/src/prolog/lib/arithmetic.pl @@ -1,4 +1,4 @@ -:- module(arithmetic, [lsb/2, msb/2, number_to_rational/2, +:- module(arithmetic, [expmod/4, lsb/2, msb/2, number_to_rational/2, number_to_rational/3, rational_numerator_denominator/3]). @@ -6,6 +6,28 @@ :- use_module(library(error)). :- use_module(library(lists), [append/3, member/2]). +expmod(Base, Expo, Mod, R) :- + ( member(N, [Base, Expo, Mod]), var(N) -> instantiation_error(expmod/4) + ; member(N, [Base, Expo, Mod]), \+ integer(N) -> + type_error(integer, N, expmod/4) + ; Expo < 0 -> domain_error(not_less_than_zero, Expo, expmod/4) + ; expmod_(Base, Expo, Mod, 1, R) + ). + +expmod_(_, _, 1, _, 0) :- !. +expmod_(_, 0, _, R, R) :- !. +expmod_(Base0, Expo0, Mod, C0, R) :- + Expo0 /\ 1 =:= 1, + C is (C0 * Base0) mod Mod, + !, + Expo is Expo0 >> 1, + Base is (Base0 * Base0) mod Mod, + expmod_(Base, Expo, Mod, C, R). +expmod_(Base0, Expo0, Mod, C, R) :- + Expo is Expo0 >> 1, + Base is (Base0 * Base0) mod Mod, + expmod_(Base, Expo, Mod, C, R). + lsb(X, N) :- builtins:must_be_number(X, lsb/2), ( \+ integer(X) -> type_error(integer, X, lsb/2)