aboutsummaryrefslogblamecommitdiffstats
path: root/lib/hipe/test/basic_SUITE_data/basic_floats.erl
blob: a3df73b928ca902083929167789e0c569813788f (plain) (tree)



























































































































































                                                                                                                                                                                                                                                                                                                                                                                                              
%%% -*- erlang-indent-level: 2 -*-
%%%-------------------------------------------------------------------
%%% Author: Kostis Sagonas
%%%
%%% Contains tests that manipulate floating point numbers.
%%%-------------------------------------------------------------------
-module(basic_floats).

-export([test/0]).

test() ->
  ok = test_arith_ops(),
  ok = test_fp_ebb(),
  ok = test_fp_phi(),
  ok = test_big_bad_float(),
  ok = test_catch_bad_fp_arith(),
  ok = test_catch_fp_conv(),
  ok = test_fp_with_fp_exceptions(),
  ok.

%%--------------------------------------------------------------------

test_arith_ops() ->
  E = 2.5617,
  5.703200000000001  = add(E),
  0.5798000000000001 = sub(E),
  8.047580550000001 = mult(E),
  -6.023e23 = negate(6.023e23),
  ok.

add(X) ->
  3.1415 + X.

sub(X) ->
  3.1415 - X.

mult(X) ->
  3.1415 * X.
        
%% tests the translation of the fnegate BEAM instruction.
negate(X) ->
  - (X + 0.0).

%%--------------------------------------------------------------------
%% Test the construction of overlapping extended basic blocks where
%% BEAM has constructed one and hipe_icode_fp constructs the other.
%%--------------------------------------------------------------------

test_fp_ebb() ->
  1.0 = foo(2*math:pi()),
  1.0 = bar(2*math:pi()),
  ok.

foo(X) ->
  X / (2 * math:pi()).

bar(X) ->
  F = float_two(),
  case F < 3.0 of
    true -> (X * F) / ((2 * F) * math:pi());
    false -> weird
  end.

float_two() ->
  2.0.

%%--------------------------------------------------------------------

test_fp_phi() ->
  10 = fp_phi(10, 100),
  undefined = fp_phi(1.1e302, 0.000000001),
  ok.

fp_phi(A, B) ->
  case catch A / B of
    {'EXIT', _Reason} -> undefined;
    _ -> round(100 * (A / B))
  end.

%%--------------------------------------------------------------------

-define(BS, "93904329458954829589425849258998492384932849328493284932849328493284932389248329432932483294832949245827588578423578435783475834758375837580745807304258924584295924588459834958349589348589345934859384958349583945893458934859438593485995348594385943859438593458934589345938594385934859483958348934589435894859485943859438594594385938459438595034950439504395043950495043593485943758.0").

test_big_bad_float() ->
  ok = try f2l(?BS) catch error:badarg -> ok end,
  ok = case catch f2l(?BS) of {'EXIT', {badarg, _}} -> ok end,
  ok.

f2l(F) ->
  float_to_list(list_to_float(F)).

%%--------------------------------------------------------------------
%% Tests catching of floating point bad arithmetic.

test_catch_bad_fp_arith() ->
 5.7 = f(2.56),
 {'EXIT', {badarith, _}} = bad_arith(9.9),
 ok.

f(F) when is_float(F) -> F + 3.14.

bad_arith(F) when is_float(F) ->
  catch F * 1.70000e+308.

%%--------------------------------------------------------------------
%% Tests proper catching of exceptions due to illegal convertion of
%% bignums to floating point numbers.

test_catch_fp_conv() ->
  F = 1.7e308, %% F is a number very close to a maximum float.
  ok = big_arith(F),
  ok = big_const_float(F),
  ok.

big_arith(F) ->
  I = trunc(F),
  {'EXIT', {badarith, _}} = big_int_arith(I),
  ok.

big_int_arith(I) when is_integer(I) ->
  catch(3.0 + 2*I).

big_const_float(F) ->
  I = trunc(F),
  badarith = try (1/(2*I)) catch error:Err -> Err end,
  _Ignore = 2/I,
  {'EXIT', _} = (catch 4/(2*I)),
  ok.

%%--------------------------------------------------------------------
%% Forces floating point exceptions and tests that subsequent, legal,
%% operations are calculated correctly.

test_fp_with_fp_exceptions() ->
  0.0 = math:log(1.0),
  badarith = try math:log(minus_one_float()) catch error:E1 -> E1 end,
  0.0 = math:log(1.0),
  badarith = try math:log(zero_float()) catch error:E2 -> E2 end,
  0.0 = math:log(1.0),
  %% An old-fashioned exception here just so as to test this case also
  {'EXIT',_} = (catch fp_mult(3.23e133, 3.57e257)),
  0.0 = math:log(1.0),
  badarith = try fp_div(5.0,0.0) catch error:E3 -> E3 end,
  0.0 = math:log(1.0),
  ok.

fp_mult(X, Y) -> X * Y.

fp_div(X, Y) -> X / Y.

%% The following two function definitions appear here just to shut
%% off 'expression will fail with a badarg' warnings from the compiler

zero_float() -> 0.0.

minus_one_float() -> -1.0.