%% -*- mode: erlang; tab-width: 4; indent-tabs-mode: 1; st-rulers: [70] -*- %% vim: ts=4 sw=4 ft=erlang noet %%%------------------------------------------------------------------- %%% @author Andrew Bennett %%% @copyright 2014-2016, Andrew Bennett %%% @doc %%% %%% @end %%% Created : 06 Jan 2016 by Andrew Bennett %%%------------------------------------------------------------------- -module(jose_jwa_math). %% Public API -export([expmod/3]). -export([exprem/3]). -export([intpow/2]). -export([mod/2]). -export([mod_pow/3]). %% Private API -export([expmod_fast/3]). -export([expmod_slow/3]). -export([exprem_fast/3]). -export([exprem_slow/3]). %%==================================================================== %% Public API %%==================================================================== expmod(B, E, M) -> expmod_fast(B, E, M). exprem(B, E, M) -> exprem_fast(B, E, M). intpow(B, E) when is_integer(B) andalso is_integer(E) andalso E >= 0 -> case B of 0 -> 0; 1 -> 1; 2 -> 1 bsl E; _ -> intpow(B, E, 1) end. mod(B, M) -> (B rem M + M) rem M. mod_pow(B, E, M) -> Bytes = crypto:mod_pow(B, E, M), Size = byte_size(Bytes), << ((crypto:bytes_to_integer(Bytes) + M) rem M):Size/signed-big-integer-unit:8 >>. %%==================================================================== %% Private API %%==================================================================== % @private expmod_fast(B, E, M) -> (exprem_fast(B, E, M) + M) rem M. % @private expmod_slow(B, E, M) -> (exprem_slow(B, E, M) + M) rem M. % @private exprem_fast(B, E, M) when B < 0 andalso E rem 2 =/= 0 -> -exprem_fast(abs(B), E, M); exprem_fast(B, E, M) when B < 0 -> exprem_fast(abs(B), E, M); exprem_fast(B, E, M) -> crypto:bytes_to_integer(crypto:mod_pow(B, E, M)). %% @private exprem_slow(_B, 0, _M) -> 1; exprem_slow(B, E, M) -> T0 = exprem_slow(B, E div 2, M), T = (T0 * T0) rem M, case E rem 2 of 0 -> T band M; _ -> (T * B) rem M end. %%%------------------------------------------------------------------- %%% Internal functions %%%------------------------------------------------------------------- %% @private intpow(B, E, R) when (E rem 2) =:= 0 -> intpow(B * B, E div 2, R); intpow(B, E, R) when (E div 2) =:= 0 -> B * R; intpow(B, E, R) -> intpow(B * B, E div 2, B * R).