mathpaqs_20230121.0.0_773568e5/random/generic_random_functions.adb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
with Ada.Numerics;                      use Ada.Numerics;
with Ada.Numerics.Generic_Elementary_Functions;

with Beta_function, Phi_function;

package body Generic_Random_Functions is

  -- Ada 95 Quality and Style Guide, 7.2.7:
  -- Tests for
  --
  -- (1) absolute "equality" to 0 in storage,
  -- (2) absolute "equality" to 0 in computation,
  -- (3) relative "equality" to 0 in storage, and
  -- (4) relative "equality" to 0 in computation:
  --
  --  abs X <= Float_Type'Model_Small                      -- (1)
  --  abs X <= Float_Type'Base'Model_Small                 -- (2)
  --  abs X <= abs X * Float_Type'Model_Epsilon            -- (3)
  --  abs X <= abs X * Float_Type'Base'Model_Epsilon       -- (4)

  function Almost_zero(X: Real) return Boolean is
  begin
    return  abs X <= Real'Base'Model_Small;
  end Almost_zero;

  package RPhF is new Phi_function (Real);
  function Normal_CDF (x: Real) return Real renames RPhF.Phi;
  function Normal_inverse_CDF (y : Real) return Real renames RPhF.Inverse_Phi;

  package RBF is new Beta_function (Real);
  function Beta_CDF (x, a, b: Real) return Real renames RBF.Regularized_Beta;
  function Beta_inverse_CDF (x, a, b: Real) return Real renames RBF.Inverse_Regularized_Beta;

  package GEF is new Ada.Numerics.Generic_Elementary_Functions(Real);
  use GEF;

  procedure Box_Muller(u1,u2: in Real; n1,n2: out Real) is
    phi, r: Real;
    Two_Pi  : constant:= 2.0 * Pi;
    m2 : constant:= -2.0;
  begin
    r:= Sqrt(m2 * Log(u2));
    phi:= Two_Pi * u1;
    n1:= r * Cos(phi);
    n2:= r * Sin(phi);
  end Box_Muller;

  function Poisson(lambda: Real) return Natural is
    lower_limit, product: Real;
    k: Integer;
  begin
    -- Algo found in:
    -- http://en.wikipedia.org/wiki/Poisson_distribution
    --   #Generating_Poisson-distributed_random_variables
    -- referring to:
    -- Knuth (whom else ?!), The Art of Computer Programming,
    -- Volume 2, Seminumerical algorithms, 3.4.1. Numerical Distributions,
    -- F. Important integer-valued distributions.
    lower_limit:= Exp(-lambda);
    k:= -1;
    product:= 1.0;
    loop
      k:= k + 1;
      product:= product * U;
      exit when product <= lower_limit;
    end loop;
    return k;
  end Poisson;

  function Pareto_inverse_CDF(q, threshold, minus_inv_alpha: Real) return Real is
  begin
    if Almost_zero(q) then
      return Real'Last;
    end if;
    return threshold * q ** (minus_inv_alpha);
  end Pareto_inverse_CDF;

  function Pareto_CDF(x, threshold, alpha: Real) return Real is
  begin
    return 1.0 - (threshold / x) ** alpha;
  end Pareto_CDF;

end Generic_Random_Functions;