File: distribution.rb

package info (click to toggle)
ruby-distribution 0.7.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster, stretch
  • size: 624 kB
  • ctags: 379
  • sloc: ruby: 4,283; makefile: 7
file content (153 lines) | stat: -rw-r--r-- 4,987 bytes parent folder | download | duplicates (2)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# = distribution.rb -
# Distribution - Statistical Distributions package for Ruby
#
# Copyright (C) 2011-2014  Claudio Bustos
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
# == Other Sources
#
# * Code of several Ruby engines came from statistics2.rb,
#   created by Shin-ichiro HARA(sinara@blade.nagaokaut.ac.jp).
#   Retrieve from http://blade.nagaokaut.ac.jp/~sinara/ruby/math/statistics2/
# * Code of Beta and Gamma distribution came from GSL project.
#   Ported by John O. Woods
# Specific notices will be placed where there are appropiate
#

require 'distribution/math_extension'
require 'distribution/version'

# Several distributions modules to calculate pdf, cdf, inverse cdf and generate
# pseudo-random numbers for several statistical distributions
#
# == Usage:
#    Distribution::Normal.cdf(1.96)
#    => 0.97500210485178
#    Distribution::Normal.p_value(0.95)
#    => 1.64485364660836
module Distribution
  SQ2PI = Math.sqrt(2 * Math::PI)

  module Shorthand
    EQUIVALENCES = { p_value: :p, cdf: :cdf, pdf: :pdf, rng: :r,
                     exact_pdf: :epdf, exact_cdf: :ecdf, exact_p_value: :ep }

    def self.add_shortcut(shortcut, method, &block)
      if EQUIVALENCES.include? method.to_sym
        name = shortcut + "_#{method}"
        define_method(name, &block)

        name = shortcut + "_#{EQUIVALENCES[method.to_sym]}"
        define_method(name, &block)

      end
    end
  end

  # Create a method 'has_<library>' on Module
  # which require a library and return true or false
  # according to success of failure
  def self.create_has_library(library) #:nodoc:
    define_singleton_method("has_#{library}?") do
      cv = "@@#{library}"
      unless class_variable_defined? cv
        begin
          require library.to_s
          class_variable_set(cv, true)
        rescue LoadError
          class_variable_set(cv, false)
        end
      end
      class_variable_get(cv)
    end
  end

  # Retrieves the libraries used to calculate
  # distributions
  def self.libraries_order
    order = [:Ruby_]
    order.unshift(:Statistics2_) if has_statistics2?
    order.unshift(:GSL_) if has_gsl?
    order.unshift(:Java_) if has_java?
    order
  end

  create_has_library :gsl
  create_has_library :statistics2
  create_has_library :java

  # Magic module
  module Distributable #:nodoc:
    # Create methods for each module and add methods to
    # Distribution::Shorthand.
    #
    # Traverse Distribution.libraries_order adding
    # methods availables for each engine module on
    # the current library
    #
    # Kids: Metaprogramming trickery! Don't do at work.
    # This section was created between a very long reunion
    # and a 456 Km. travel
    def create_distribution_methods
      Distribution.libraries_order.each do |l_name|
        if const_defined? l_name
          l = const_get(l_name)
          # Add methods from engine to base base, if not yet included
          l.singleton_methods.each do |m|
            unless singleton_methods.include? m
              define_method(m) do |*args|
                l.send(m, *args)
              end
              # Add method to Distribution::Shorthand
              sh = const_get(:SHORTHAND)
              Distribution::Shorthand.add_shortcut(sh, m) do |*args|
                l.send(m, *args)
              end

              module_function m
            end
          end
        end
      end
      # create alias for common methods
      alias_method :inverse_cdf, :p_value if singleton_methods.include? :p_value
    end
  end

  def self.init_java
    $LOAD_PATH.unshift File.expand_path('../../vendor/java', __FILE__)
    require 'commons-math-2.2.jar'
    java_import 'org.apache.commons.math.distribution.NormalDistributionImpl'
    java_import 'org.apache.commons.math.distribution.PoissonDistributionImpl'
  end

  require 'distribution/normal'
  require 'distribution/chisquare'
  require 'distribution/gamma'
  require 'distribution/beta'
  require 'distribution/t'
  require 'distribution/f'
  require 'distribution/bivariatenormal'
  require 'distribution/binomial'
  require 'distribution/hypergeometric'
  require 'distribution/exponential'
  require 'distribution/poisson'
  require 'distribution/logistic'
  require 'distribution/lognormal'
  require 'distribution/weibull'

  init_java if has_java?
end