Hatena::Grouperlang

檜山正幸のErlang未確認情報 RSSフィード

 | 

2008-12-18 (木)

無限大を含む整数算術

| 15:05

必要性があったので書いてみた。

  • 確かに、こういうのはErlang向きだろう。表を見ながらそのまま引き写すだけ。
  • だが、表を見ながらの転記は、退屈でつまんなくて、そのくせ注意力がいる。
  • ので、えれーツマンネー。辛い。Erlangでも辛い!
  • ライブラリ設計として、考えるべき点も二三はあるのだが、目が疲れたから後にする。

%% -*- coding: utf-8 -*-

%% @doc 正負の無限大を含む整数の算術
-module(x_arith).

-export([ % 定数
          infinity/0, negative_infinity/0
         ]).
-export([ % 各種の述語
         is_x_integer/1, is_x_positive/1, is_x_nonnegative/1,
         is_finite/1, is_not_finite/1, is_infinite/1, is_negative_infinite/1
        ]).
-export([ % 加減乗除、符号反転
         x_add/2, x_sub/2, x_mul/2, x_div/2, x_neg/1
        ]).
-export([ % エラー情報の可読文字列化
          format_error/1
         ]).

%% マクロ定数定義
-define(INF, infinity).
-define(NEGINF, negative_infinity).

%% @type x_integer() = integer() | infinity | negative_infinity .
%% 正負の無限大を含む拡張整数

%% @type x_arith_excep() = {{Mod, Id}, Hint}
%% where
%%   Mod = atom()
%%   Id = atom()
%%   Hint = any().
%% 例外として投げるデータ.

%% @doc 正の無限大(定数)
%% @spec () -> atom()
infinity() ->
  ?INF.

%% @doc 負の無限大(定数)
%% @spec () -> atom()
negative_infinity() ->
  ?NEGINF.

%% @doc 拡張整数か
%% @spec (any()) -> bool()
is_x_integer(X) ->
  is_integer(X) orelse X =:= ?INF orelse X =:= ?NEGINF.

%% @doc 拡張正整数か
%% @spec (any()) -> bool()
is_x_positive(X) ->
  (is_integer(X) andalso X > 0) orelse X =:= ?INF.

%% @doc 拡張非負整数か
%% @spec (any()) -> bool()
is_x_nonnegative(X) ->
  (is_integer(X) andalso X >= 0) orelse X =:= ?INF.

%% @doc 有限整数か
%% @spec (any()) -> bool()
is_finite(X) ->
  is_integer(X).

%% @doc 非有限整数(正負の無限大)か
%% @spec (any()) -> bool()
is_not_finite(X) ->
  X =:= ?INF orelse X =:= ?NEGINF.

%% @doc 正の無限大か
%% @spec (any()) -> bool()
is_infinite(X) ->
  X =:= ?INF.

%% @doc 負の無限大か
%% @spec (any()) -> bool()
is_negative_infinite(X) ->
  X =:= ?NEGINF.

%%%%%%
%% addition, subtraction, multiplication and division
%%%%%% 

%% 場合分け:
%%        X=NEGINF, X=INF X=other 
%% Y=NEGINF  1      4       7
%% Y=INF     2      5       8
%% Y=other   3      6       9

%% @doc 足し算
%% @spec (X::x_integer(), Y::x_integer()) -> x_integer()
%% @throws x_arith_excep()

x_add(?NEGINF, ?NEGINF) -> % 1
  ?NEGINF;
x_add(?NEGINF, ?INF) -> % 2
  throw({{?MODULE, undef}, none});
x_add(?NEGINF, Y) when is_integer(Y) -> % 3
  ?NEGINF;

x_add(?INF, ?NEGINF) -> % 4
  throw({{?MODULE, undef}, none});
x_add(?INF, ?INF) -> % 5
  ?INF;
x_add(?INF, Y) when is_integer(Y) -> %6
  ?INF;

x_add(X, ?NEGINF) when is_integer(X) -> %7
  ?NEGINF;
x_add(X, ?INF) when is_integer(X) -> %8
  ?INF;
x_add(X, Y) when is_integer(X), is_integer(Y) -> %9
  X + Y.

%% @doc 引き算
%% @spec (X::x_integer(), Y::x_integer()) -> x_integer()
%% @throws x_arith_excep()

x_sub(?NEGINF, ?NEGINF) -> % 1
  throw({{?MODULE, undef}, none});  
x_sub(?NEGINF, ?INF) -> %2
  ?NEGINF;  
x_sub(?NEGINF, Y) when is_integer(Y) -> %3
  ?NEGINF;

x_sub(?INF, ?NEGINF) -> % 4
  ?INF;
x_sub(?INF, ?INF) -> % 5
  throw({{?MODULE, undef}, none});
x_sub(?INF, Y) when is_integer(Y) -> % 6
  ?INF;

x_sub(X, ?NEGINF) when is_integer(X) -> %7
  ?INF;
x_sub(X, ?INF) when is_integer(X) -> %8
  ?NEGINF;
x_sub(X, Y) when is_integer(X), is_integer(Y) -> %9
  X - Y.

%% 場合分け:
%% 印(*, #, /)が付いているケースはまとめて処理する
%%        X=NEGINF,X=INF, X<0, X=0, X>0, 
%% Y=NEGINF  1      6     11   16#  21
%% Y=INF     2      7     12   17#  22
%% Y<0       3      8     13/  18#  23/
%% Y=0       4*     9*    14*  19#  24*
%% Y>0       5     10     15/  20#  25/

%% @doc 掛け算
%% @spec (X::x_integer(), Y::x_integer()) -> x_integer()

x_mul(0, Y) -> % 16, 17, 18, 19, 20
  case is_x_integer(Y) of
    true ->
      0
  end;
x_mul(X, 0) -> % 4, 9, 14, 24
  case is_x_integer(X) of
    true ->
      0
  end;
x_mul(?NEGINF, ?NEGINF) -> % 1
  ?INF;
x_mul(?NEGINF, ?INF) -> % 2
  ?NEGINF;
x_mul(?NEGINF, Y) when is_integer(Y), Y < 0 -> % 3
  ?INF;
%x_mul(?NEGINF, 0) ->
%  0;
x_mul(?NEGINF, Y) when is_integer(Y), Y > 0 -> % 5
  ?NEGINF;

x_mul(?INF, ?NEGINF) -> % 6
  ?NEGINF;
x_mul(?INF, ?INF) -> % 7
  ?INF;
x_mul(?INF, Y) when is_integer(Y), Y < 0 -> % 8
  ?NEGINF;
%x_mul(?INF, 0) ->
%  0;
x_mul(?INF, Y) when is_integer(Y), Y > 0 -> % 10
  ?INF;

x_mul(X, ?NEGINF) when is_integer(X), X < 0 -> % 11
  ?INF;
x_mul(X, ?INF) when is_integer(X), X < 0 -> % 12
  ?NEGINF;

x_mul(X, ?NEGINF) when is_integer(X), X > 0 -> % 21
  ?NEGINF;
x_mul(X, ?INF) when is_integer(X), X > 0 ->  % 22
  ?INF;
x_mul(X, Y) when is_integer(X), is_integer(Y) -> % 13, 15, 23, 25
  X * Y.

%% @doc 割り算
%% @spec (X::x_integer(), Y::x_integer()) -> x_integer()
%% @throws x_arith_excep()

x_div(0, Y) -> % 16, 17, 18, 19, 20
  case is_x_integer(Y) of
    true ->
      0
  end;
x_div(X, 0) -> % 4, 9, 14, 24
  case is_x_integer(X) of
    true ->
      throw({{?MODULE, devided_by_zero}, none})
  end;

x_div(?NEGINF, ?NEGINF) -> % 1
  throw({{?MODULE, undef}, none});
x_div(?NEGINF, ?INF) -> % 2
  throw({{?MODULE, undef}, none});
x_div(?NEGINF, Y) when is_integer(Y), Y < 0 -> % 3
  ?INF;
%x_div(?NEGINF, 0) ->
%  0;
x_div(?NEGINF, Y) when is_integer(Y), Y > 0 -> % 5
  ?NEGINF;

x_div(?INF, ?NEGINF) -> % 6
  throw({{?MODULE, undef}, none});
x_div(?INF, ?INF) -> % 7
  throw({{?MODULE, undef}, none});
x_div(?INF, Y) when is_integer(Y), Y < 0 -> % 8
  ?NEGINF;
%x_div(?INF, 0) ->
%  0;
x_div(?INF, Y) when is_integer(Y), Y > 0 -> % 10
  ?INF;

x_div(X, ?NEGINF) when is_integer(X)  -> % 11, 12
  throw({{?MODULE, undef}, none});
x_div(X, ?INF) when is_integer(X)  -> % 21, 22
  throw({{?MODULE, undef}, none});
x_div(X, Y) when is_integer(X), is_integer(Y) -> % 13, 15, 23, 25
  X / Y.

%% @doc 符号反転
%% @spec (X::x_integer()) -> x_integer()
x_neg(?NEGINF) ->
  ?INF;
x_neg(?INF) ->
  ?NEGINF;
x_neg(X) when is_integer(X) ->
  -X.

%% @doc エラー情報の可読文字列化
%% @spec (x_arith_excep() | atom()) -> string()
format_error({{?MODULE, Id}, _Hint}) ->
  message(Id);
format_error(Id) when is_atom(Id) ->
  message(Id).

%% @spec (atom()) -> string()
message(undef) ->
  "operation undefined";
message(devided_by_zero) ->
  "devided by zero".

RasadRasad2012/02/09 19:39So much info in so few words. Tosotly could learn a lot.

fttosrpfqrfttosrpfqr2012/02/09 22:04xtmx4I <a href="http://dcwmuvowvxrk.com/">dcwmuvowvxrk</a>

qbwziqzqbwziqz2012/02/11 03:45EuHBqE , [url=http://vmxmmwylocyl.com/]vmxmmwylocyl[/url], [link=http://ewgoxruwespg.com/]ewgoxruwespg[/link], http://oyqkypsxrner.com/

zygmbyzygmby2012/02/12 23:23Gr6C5f <a href="http://foeilrknewxy.com/">foeilrknewxy</a>

iigwhkksnsiigwhkksns2012/02/14 01:05eCy3ac , [url=http://boynrsvpwqyg.com/]boynrsvpwqyg[/url], [link=http://dbgndaxgwozh.com/]dbgndaxgwozh[/link], http://pqhcxmcmdrlj.com/

 |