%%% -*- erlang-indent-level: 2 -*- %%%------------------------------------------------------------------- %%% Author: Kostis Sagonas %%% %%% Contains code examples that test bignum arithmetic and matching. %%%------------------------------------------------------------------- -module(basic_bignums). -export([test/0, test_bsl/0]). test() -> ok = test_ops(), ok = test_big_fac(), ok = test_int_overfl_32(), ok = test_int_overfl_64(), ok = test_int_overfl_32_guard(), ok = test_int_overfl_64_guard(), ok. %%-------------------------------------------------------------------- %% Define some constants for the tests of arithmetic operators -define(X, 68719476736). -define(Y, 98765432101234). -define(Z, 4722366482869645213696). -define(W, 339254531512339254531512). -define(B1, 4398046511104). -define(B5, 1645504557321206042154969182557350504982735865633579863348609024). -define(B17, 86182066610968551542636378241108028056376767329454880514019834315878107616003372189510312530372009184902888961739623919010110377987011442493486117202360415845666384627768436296772219009176743399772868636439042064384). %%-------------------------------------------------------------------- test_ops() -> ok = test_mult(), ok = test_div(), ok = test_round(), ok = test_trunc(), ok = test_bsl(), ok. test_mult() -> ?Z = mult(?X, ?X), ok. mult(X, Y) -> X * Y. test_div() -> 4 = div_f(339254531512, ?X), 0 = div_f(?Y, ?Y+1), 64 = div_f(?B1, ?X), ?X = div_f(?Z, ?X), 1073741824 = div_f(?Z, ?B1), ok. div_f(X, Y) -> X div Y. test_round() -> 0 = round_f(?Z, ?W), 1 = round_f(?Y, ?Y), 71 = round_f(?W, ?Z), 1437 = round_f(?Y, ?X), 47813960 = round_f(?Z, ?Y), 4936803183406 = round_f(?W, ?X), ok. trunc_f(X, Y) -> round(X/Y). test_trunc() -> 0 = trunc_f(?Z, ?W), 1 = trunc_f(?Y, ?Y), 72 = trunc_f(?W, ?Z), 1437 = trunc_f(?Y, ?X), 47813961 = trunc_f(?Z, ?Y), 4936803183407 = trunc_f(?W, ?X), ok. round_f(X, Y) -> trunc(X/Y). test_bsl() -> ?B1 = bsl_f(1, 42), ?B5 = n(5, fun erlang:'bsl'/2, 1, 42), % use the operator ?B17 = n(17, fun bsl_f/2, 1, 42), % use the local function ok. bsl_f(X, Y) -> X bsl Y. %% applies a binary function N times n(1, F, X, Y) -> F(X, Y); n(N, F, X, Y) when N > 1 -> n(N-1, F, F(X, Y), Y). %%-------------------------------------------------------------------- -define(FAC42, 1405006117752879898543142606244511569936384000000000). test_big_fac() -> ?FAC42 = fac(42), ok. fac(0) -> 1; fac(N) -> N * fac(N-1). %%-------------------------------------------------------------------- %% Tests for correct handling of integer overflow test_int_overfl_32() -> 16#7FFFFFF = add(16#7FFFFFF, 0), 16#8000000 = add(16#8000000, 0), 16#8000001 = add(16#8000000, 1), case add(16#7FFFFFF, 1) of 16#8000000 -> ok; -16#7FFFFFF -> error end. test_int_overfl_64() -> 16#7FFFFFFFFFFFFFF = add(16#7FFFFFFFFFFFFFF, 0), 16#800000000000000 = add(16#800000000000000, 0), 16#800000000000001 = add(16#800000000000000, 1), case add(16#7FFFFFFFFFFFFFF, 1) of 16#800000000000000 -> ok; -16#7FFFFFFFFFFFFFF -> error end. add(X, Y) -> X + Y. %%-------------------------------------------------------------------- %% Tests for correct handling of integer overflow in guards test_int_overfl_32_guard() -> ok = overfl_in_guard(16#7ffffff, 0), ok = overfl_in_guard(16#7ffffff, 16#7ffffff), ok. test_int_overfl_64_guard() -> ok = overfl_in_guard(16#7ffffffffffffff, 0), ok = overfl_in_guard(16#7ffffffffffffff, 16#7ffffffffffffff), ok. overfl_in_guard(X, Y) -> case ok of V when X+Y > 12 -> V; _ -> bad end.