distribution 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.autotest +23 -0
  3. data/History.txt +3 -0
  4. data/Manifest.txt +39 -0
  5. data/README.txt +71 -0
  6. data/Rakefile +19 -0
  7. data/bin/distribution +3 -0
  8. data/lib/distribution.rb +148 -0
  9. data/lib/distribution/bivariatenormal.rb +25 -0
  10. data/lib/distribution/bivariatenormal/gsl.rb +11 -0
  11. data/lib/distribution/bivariatenormal/ruby.rb +281 -0
  12. data/lib/distribution/bivariatenormal/statistics2.rb +0 -0
  13. data/lib/distribution/chisquare.rb +29 -0
  14. data/lib/distribution/chisquare/gsl.rb +27 -0
  15. data/lib/distribution/chisquare/ruby.rb +85 -0
  16. data/lib/distribution/chisquare/statistics2.rb +21 -0
  17. data/lib/distribution/f.rb +28 -0
  18. data/lib/distribution/f/gsl.rb +28 -0
  19. data/lib/distribution/f/ruby.rb +117 -0
  20. data/lib/distribution/f/statistics2.rb +26 -0
  21. data/lib/distribution/math_extension.rb +72 -0
  22. data/lib/distribution/normal.rb +36 -0
  23. data/lib/distribution/normal/gsl.rb +24 -0
  24. data/lib/distribution/normal/ruby.rb +99 -0
  25. data/lib/distribution/normal/statistics2.rb +14 -0
  26. data/lib/distribution/normalmultivariate.rb +73 -0
  27. data/lib/distribution/t.rb +27 -0
  28. data/lib/distribution/t/gsl.rb +29 -0
  29. data/lib/distribution/t/ruby.rb +105 -0
  30. data/lib/distribution/t/statistics2.rb +28 -0
  31. data/spec/bivariatenormal_spec.rb +63 -0
  32. data/spec/chisquare_spec.rb +89 -0
  33. data/spec/distribution_spec.rb +19 -0
  34. data/spec/f_spec.rb +107 -0
  35. data/spec/normal_spec.rb +105 -0
  36. data/spec/shorthand_function.rb +6 -0
  37. data/spec/shorthand_spec.rb +14 -0
  38. data/spec/spec.opts +3 -0
  39. data/spec/spec_helper.rb +23 -0
  40. data/spec/t_spec.rb +98 -0
  41. metadata +160 -0
  42. metadata.gz.sig +1 -0
data.tar.gz.sig ADDED
Binary file
data/.autotest ADDED
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ # Autotest.add_hook :initialize do |at|
6
+ # at.extra_files << "../some/external/dependency.rb"
7
+ #
8
+ # at.libs << ":../some/external"
9
+ #
10
+ # at.add_exception 'vendor'
11
+ #
12
+ # at.add_mapping(/dependency.rb/) do |f, _|
13
+ # at.files_matching(/test_.*rb$/)
14
+ # end
15
+ #
16
+ # %w(TestA TestB).each do |klass|
17
+ # at.extra_class_map[klass] = "test/test_misc.rb"
18
+ # end
19
+ # end
20
+
21
+ # Autotest.add_hook :run_command do |at|
22
+ # system "rake build"
23
+ # end
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ === 0.1.0 / 2011-01-26
2
+
3
+ * Basic set (pdf, cdf, p_value) for Normal, Chi Square, F and T distributions
data/Manifest.txt ADDED
@@ -0,0 +1,39 @@
1
+ .autotest
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ bin/distribution
7
+ lib/distribution.rb
8
+ lib/distribution/bivariatenormal.rb
9
+ lib/distribution/bivariatenormal/gsl.rb
10
+ lib/distribution/bivariatenormal/ruby.rb
11
+ lib/distribution/bivariatenormal/statistics2.rb
12
+ lib/distribution/chisquare.rb
13
+ lib/distribution/chisquare/gsl.rb
14
+ lib/distribution/chisquare/ruby.rb
15
+ lib/distribution/chisquare/statistics2.rb
16
+ lib/distribution/f.rb
17
+ lib/distribution/f/gsl.rb
18
+ lib/distribution/f/ruby.rb
19
+ lib/distribution/f/statistics2.rb
20
+ lib/distribution/math_extension.rb
21
+ lib/distribution/normal.rb
22
+ lib/distribution/normal/gsl.rb
23
+ lib/distribution/normal/ruby.rb
24
+ lib/distribution/normal/statistics2.rb
25
+ lib/distribution/normalmultivariate.rb
26
+ lib/distribution/t.rb
27
+ lib/distribution/t/gsl.rb
28
+ lib/distribution/t/ruby.rb
29
+ lib/distribution/t/statistics2.rb
30
+ spec/bivariatenormal_spec.rb
31
+ spec/chisquare_spec.rb
32
+ spec/distribution_spec.rb
33
+ spec/f_spec.rb
34
+ spec/normal_spec.rb
35
+ spec/shorthand_function.rb
36
+ spec/shorthand_spec.rb
37
+ spec/spec.opts
38
+ spec/spec_helper.rb
39
+ spec/t_spec.rb
data/README.txt ADDED
@@ -0,0 +1,71 @@
1
+ = distribution
2
+
3
+ * https://github.com/clbustos/distribution
4
+
5
+ == DESCRIPTION:
6
+
7
+ Statistical Distributions multi library wrapper.
8
+ Uses Ruby by default and C (statistics2/GSL) or Java extensions where available.
9
+
10
+ Includes code from statistics2
11
+
12
+ == FEATURES/PROBLEMS:
13
+
14
+ * Base API
15
+ * Shorthand for easy use
16
+
17
+ == API structure
18
+
19
+ Distribution::<name>.(cdf|pdf|p_value|rng)
20
+
21
+ module Distribution::Shorthand provides (you guess?) shortands method to call all methods
22
+
23
+ <Distribution shortname>_(cdf|pdf|p|r)
24
+
25
+ Shortnames are:
26
+
27
+ * Normal: norm
28
+ * Bivariate Normal: bnor
29
+ * T: t
30
+ * F: f
31
+ * Chi Square: chisq
32
+
33
+ For example
34
+
35
+ Distribution::T.rng
36
+
37
+ could be called after including Distribution::Shorthand
38
+
39
+ t_r
40
+
41
+ == SYNOPSIS:
42
+ # Returns Gaussian PDF for x
43
+ pdf=Distribution::Normal.pdf(x)
44
+ # Returns Gaussian CDF for x
45
+ cdf=Distribution::Normal.cdf(x)
46
+ # Returns inverse CDF (or p-value) for x
47
+ pv =Distribution::Normal.p_value(x)
48
+
49
+ == REQUIREMENTS:
50
+
51
+ I try to provide a Ruby version for each method. But to increase (notably!) the speed, please install
52
+
53
+ * Ruby 1.8-1.9: gsl or statistics2
54
+ * Java: Apache Math
55
+
56
+ == INSTALL:
57
+
58
+ gem install distribution
59
+
60
+ == DEVELOPERS:
61
+
62
+ After checking out the source, run:
63
+
64
+ $ rake newb
65
+
66
+ This task will install any missing dependencies, run the tests/specs,
67
+ and generate the RDoc.
68
+
69
+ == LICENSE:
70
+
71
+ GPL V2
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ # -*- ruby -*-
2
+ $:.unshift(File.expand_path(File.dirname(__FILE__)+"/lib/"))
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require 'distribution'
6
+ require 'rubyforge'
7
+ # Hoe.plugin :compiler
8
+ # Hoe.plugin :gem_prelude_sucks
9
+ Hoe.plugin :git
10
+ # Hoe.plugin :inline
11
+ # Hoe.plugin :racc
12
+ Hoe.plugin :rubyforge
13
+
14
+ Hoe.spec 'distribution' do
15
+ self.developer('Claudio Bustos', 'clbustos_at_gmail.com')
16
+ self.version=Distribution::VERSION
17
+ end
18
+
19
+ # vim: syntax=ruby
data/bin/distribution ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ abort "you need to write me"
@@ -0,0 +1,148 @@
1
+ # = distribution.rb -
2
+ # Distribution - Statistical Distributions package for Ruby
3
+ #
4
+ # Copyright (C) 2011 Claudio Bustos
5
+ #
6
+ # This program is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU General Public License
8
+ # as published by the Free Software Foundation; either version 2
9
+ # of the License, or (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
+ #
20
+ # == Other Sources
21
+ #
22
+ # * Code of Ruby engines came from statistics2.rb,
23
+ # created by Shin-ichiro HARA(sinara@blade.nagaokaut.ac.jp).
24
+ # Retrieve from http://blade.nagaokaut.ac.jp/~sinara/ruby/math/statistics2/
25
+ #
26
+ # Specific notices will be placed where there are appropiate
27
+ #
28
+ if !respond_to? :define_singleton_method
29
+ class Module
30
+ public :define_method
31
+ end
32
+
33
+ class Object
34
+ def define_singleton_method(name,&block)
35
+ sc=class <<self;self;end
36
+ sc.define_method(name,&block)
37
+ end
38
+ end
39
+ end
40
+ require 'distribution/math_extension'
41
+
42
+ # Several distributions modules to calculate pdf, cdf, inverse cdf and generate
43
+ # pseudo-random numbers for several statistical distributions
44
+ #
45
+ # == Usage:
46
+ # Distribution::Normal.cdf(1.96)
47
+ # => 0.97500210485178
48
+ # Distribution::Normal.p_value(0.95)
49
+ # => 1.64485364660836
50
+ module Distribution
51
+ VERSION="0.1.0"
52
+
53
+ module Shorthand
54
+ EQUIVALENCES={:p_value=>:p, :cdf=>:cdf, :pdf=>:pdf, :rng=>:r}
55
+ def self.add_shortcut(sh,m,&block)
56
+ if EQUIVALENCES.include? m.to_sym
57
+ sh_name=sh+"_#{m}"
58
+ define_method(sh_name,&block)
59
+ sh_name=sh+"_#{EQUIVALENCES[m]}"
60
+ define_method(sh_name,&block)
61
+
62
+ end
63
+ end
64
+ end
65
+
66
+
67
+ SQ2PI = Math.sqrt(2 * Math::PI)
68
+
69
+ # Create a method 'has_<library>' on Module
70
+ # which require a library and return true or false
71
+ # according to success of failure
72
+ def self.create_has_library(library) #:nodoc:
73
+ define_singleton_method("has_#{library}?") do
74
+ cv="@@#{library}"
75
+ if !class_variable_defined? cv
76
+ begin
77
+ require library.to_s
78
+ class_variable_set(cv, true)
79
+ rescue LoadError
80
+ class_variable_set(cv, false)
81
+ end
82
+ end
83
+ class_variable_get(cv)
84
+ end
85
+ end
86
+ # Retrieves the libraries used to calculate
87
+ # distributions
88
+ def self.libraries_order
89
+ order=[:Ruby_]
90
+ order.unshift(:Statistics2_) if has_statistics2?
91
+ order.unshift(:GSL_) if has_gsl?
92
+ order.unshift(:Java_) if has_java?
93
+ order
94
+ end
95
+ create_has_library :gsl
96
+ create_has_library :statistics2
97
+ create_has_library :java
98
+
99
+ # Magic module
100
+ module Distributable #:nodoc:
101
+ # Create methods for each module and add methods to
102
+ # Distribution::Shorthand.
103
+ #
104
+ # Traverse Distribution.libraries_order adding
105
+ # methods availables for each engine module on
106
+ # the current library
107
+ #
108
+ # Kids: Metaprogramming trickery! Don't do at work.
109
+ # This section was created between a very long reunion
110
+ # and a travel of 456 Km.
111
+ def create_distribution_methods()
112
+ Distribution.libraries_order.each do |l_name|
113
+ if const_defined? l_name
114
+ l =const_get(l_name)
115
+ # Add methods from engine to base base, if not yet included
116
+ l.singleton_methods.each do |m|
117
+ if !singleton_methods.include? m
118
+ define_method(m) do |*args|
119
+ l.send(m,*args)
120
+ end
121
+ # Add method to Distribution::Shorthand
122
+ sh=const_get(:SHORTHAND)
123
+
124
+ Distribution::Shorthand.add_shortcut(sh,m) do |*args|
125
+ l.send(m,*args)
126
+ end
127
+
128
+ module_function m
129
+ end
130
+ end
131
+ end
132
+
133
+ end
134
+ # create alias for common methods
135
+ alias_method :inverse_cdf,:p_value if singleton_methods.include? :p_value
136
+ end
137
+
138
+ end
139
+
140
+ autoload(:Normal, 'distribution/normal')
141
+ autoload(:ChiSquare, 'distribution/chisquare')
142
+ autoload(:T, 'distribution/t')
143
+ autoload(:F, 'distribution/f')
144
+ autoload(:BivariateNormal, 'distribution/bivariatenormal')
145
+ end
146
+
147
+
148
+
@@ -0,0 +1,25 @@
1
+ require 'distribution/bivariatenormal/ruby'
2
+ require 'distribution/bivariatenormal/gsl'
3
+ module Distribution
4
+ # Calculate pdf and cdf for bivariate normal distribution.
5
+ #
6
+ # Pdf if easy to calculate, but CDF is not trivial. Several papers
7
+ # describe methods to calculate the integral.
8
+ module BivariateNormal
9
+ SHORTHAND='bnor'
10
+
11
+ extend Distributable
12
+ create_distribution_methods
13
+
14
+ ##
15
+ # :singleton-method: pdf(x,y, rho, s1=1.0, s2=1.0)
16
+ # Probability density function for a given x, y and rho value.
17
+ #
18
+
19
+ ##
20
+ # :singleton-method: cdf(x,y,rho)
21
+ # CDF for a given x, y and rho value.
22
+ #
23
+
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ module Distribution
2
+ module BivariateNormal
3
+ module GSL_
4
+ class <<self
5
+ def pdf(x,y,rho,s1=1.0,s2=1.0)
6
+ GSL::Ran::bivariate_gaussian_pdf(x, y, s1,s2,rho)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,281 @@
1
+ module Distribution
2
+ #
3
+ # Ruby version implements three methods on this module:
4
+ # * Genz:: Used by default, with improvement to calculate p on rho > 0.95
5
+ # * Hull:: Port from a C++ code
6
+ # * Jantaravareerat:: Iterative (slow and buggy)
7
+ #
8
+
9
+ module BivariateNormal
10
+ module Ruby_
11
+ class << self
12
+ SIDE=0.1 # :nodoc:
13
+ LIMIT=5 # :nodoc:
14
+ # Return the partial derivative of cdf over x, with y and rho constant
15
+ # Reference:
16
+ # * Tallis, 1962, p.346, cited by Olsson, 1979
17
+ def partial_derivative_cdf_x(x,y,rho)
18
+ Distribution::Normal.pdf(x) * Distribution::Normal.cdf((y-rho*x).quo( Math::sqrt( 1 - rho**2 )))
19
+ end
20
+ alias :pd_cdf_x :partial_derivative_cdf_x
21
+ # Probability density function for a given x, y and rho value.
22
+ #
23
+ # Source: http://en.wikipedia.org/wiki/Multivariate_normal_distribution
24
+ def pdf(x,y, rho, s1=1.0, s2=1.0)
25
+ 1.quo(2 * Math::PI * s1 * s2 * Math::sqrt( 1 - rho**2 )) * (Math::exp(-(1.quo(2*(1-rho**2))) *
26
+ ((x**2.quo(s1)) + (y**2.quo(s2)) - (2*rho*x*y).quo(s1*s2))))
27
+ end
28
+
29
+ def f(x,y,aprime,bprime,rho)
30
+ r=aprime*(2*x-aprime)+bprime*(2*y-bprime)+2*rho*(x-aprime)*(y-bprime)
31
+ Math::exp(r)
32
+ end
33
+
34
+ # CDF for a given x, y and rho value.
35
+ # Uses Genz algorithm (cdf_genz method).
36
+ #
37
+ def cdf(a,b,rho)
38
+ cdf_genz(a,b,rho)
39
+ end
40
+
41
+ def sgn(x)
42
+ if(x>=0)
43
+ 1
44
+ else
45
+ -1
46
+ end
47
+ end
48
+
49
+ # Normal cumulative distribution function (cdf) for a given x, y and rho.
50
+ # Based on Hull (1993, cited by Arne, 2003)
51
+ #
52
+ # References:
53
+ # * Arne, B.(2003). Financial Numerical Recipes in C ++. Available on http://finance.bi.no/~bernt/gcc_prog/recipes/recipes/node23.html
54
+ def cdf_hull(a,b,rho)
55
+ #puts "a:#{a} - b:#{b} - rho:#{rho}"
56
+ if (a<=0 and b<=0 and rho<=0)
57
+ # puts "ruta 1"
58
+ aprime=a.quo(Math::sqrt(2.0*(1.0-rho**2)))
59
+ bprime=b.quo(Math::sqrt(2.0*(1.0-rho**2)))
60
+ aa=[0.3253030, 0.4211071, 0.1334425, 0.006374323]
61
+ bb=[0.1337764, 0.6243247, 1.3425378, 2.2626645]
62
+ sum=0
63
+ 4.times do |i|
64
+ 4.times do |j|
65
+ sum+=aa[i]*aa[j] * f(bb[i], bb[j], aprime, bprime,rho)
66
+ end
67
+ end
68
+ sum=sum*(Math::sqrt(1.0-rho**2).quo(Math::PI))
69
+ return sum
70
+ elsif(a*b*rho<=0.0)
71
+
72
+ #puts "ruta 2"
73
+ if(a<=0 and b>=0 and rho>=0)
74
+ return Distribution::Normal.cdf(a) - cdf(a,-b,-rho)
75
+ elsif (a>=0.0 and b<=0.0 and rho>=0)
76
+ return Distribution::Normal.cdf(b) - cdf(-a,b,-rho)
77
+ elsif (a>=0.0 and b>=0.0 and rho<=0)
78
+ return Distribution::Normal.cdf(a) + Distribution::Normal.cdf(b) - 1.0 + cdf(-a,-b,rho)
79
+ end
80
+ elsif (a*b*rho>=0.0)
81
+ #puts "ruta 3"
82
+ denum=Math::sqrt(a**2 - 2*rho*a*b + b**2)
83
+ rho1=((rho*a-b)*sgn(a)).quo(denum)
84
+ rho2=((rho*b-a)*sgn(b)).quo(denum)
85
+ delta=(1.0-sgn(a)*sgn(b)).quo(4)
86
+ #puts "#{rho1} - #{rho2}"
87
+ return cdf(a, 0.0, rho1) + cdf(b, 0.0, rho2) - delta
88
+ end
89
+ raise "Should'nt be here! #{a} - #{b} #{rho}"
90
+ end
91
+
92
+ # CDF. Iterative method by Jantaravareerat (n/d)
93
+ #
94
+ # Reference:
95
+ # * Jantaravareerat, M. & Thomopoulos, N. (n/d). Tables for standard bivariate normal distribution
96
+
97
+ def cdf_jantaravareerat(x,y,rho,s1=1,s2=1)
98
+ # Special cases
99
+ return 1 if x>LIMIT and y>LIMIT
100
+ return 0 if x<-LIMIT or y<-LIMIT
101
+ return Distribution::Normal.cdf(y) if x>LIMIT
102
+ return Distribution::Normal.cdf(x) if y>LIMIT
103
+
104
+ #puts "x:#{x} - y:#{y}"
105
+ x=-LIMIT if x<-LIMIT
106
+ x=LIMIT if x>LIMIT
107
+ y=-LIMIT if y<-LIMIT
108
+ y=LIMIT if y>LIMIT
109
+
110
+ x_squares=((LIMIT+x) / SIDE).to_i
111
+ y_squares=((LIMIT+y) / SIDE).to_i
112
+ sum=0
113
+ x_squares.times do |i|
114
+ y_squares.times do |j|
115
+ z1=-LIMIT+(i+1)*SIDE
116
+ z2=-LIMIT+(j+1)*SIDE
117
+ #puts " #{z1}-#{z2}"
118
+ h=(pdf(z1,z2,rho,s1,s2)+pdf(z1-SIDE,z2,rho,s1,s2)+pdf(z1,z2-SIDE,rho,s1,s2) + pdf(z1-SIDE,z2-SIDE,rho,s1,s2)).quo(4)
119
+ sum+= (SIDE**2)*h # area
120
+ end
121
+ end
122
+ sum
123
+ end
124
+ # Normal cumulative distribution function (cdf) for a given x, y and rho.
125
+ # Ported from Fortran code by Alan Genz
126
+ #
127
+ # Original documentation
128
+ # DOUBLE PRECISION FUNCTION BVND( DH, DK, R )
129
+ # A function for computing bivariate normal probabilities.
130
+ #
131
+ # Alan Genz
132
+ # Department of Mathematics
133
+ # Washington State University
134
+ # Pullman, WA 99164-3113
135
+ # Email : alangenz_AT_wsu.edu
136
+ #
137
+ # This function is based on the method described by
138
+ # Drezner, Z and G.O. Wesolowsky, (1989),
139
+ # On the computation of the bivariate normal integral,
140
+ # Journal of Statist. Comput. Simul. 35, pp. 101-107,
141
+ # with major modifications for double precision, and for |R| close to 1.
142
+ #
143
+ # Original location:
144
+ # * http://www.math.wsu.edu/faculty/genz/software/fort77/tvpack.f
145
+ def cdf_genz(x,y,rho)
146
+ dh=-x
147
+ dk=-y
148
+ r=rho
149
+ twopi = 6.283185307179586
150
+
151
+ w=11.times.collect {[nil]*4};
152
+ x=11.times.collect {[nil]*4}
153
+
154
+ data=[
155
+ 0.1713244923791705E+00, -0.9324695142031522E+00,
156
+ 0.3607615730481384E+00, -0.6612093864662647E+00,
157
+ 0.4679139345726904E+00, -0.2386191860831970E+00]
158
+
159
+ (1..3).each {|i|
160
+ w[i][1]=data[(i-1)*2]
161
+ x[i][1]=data[(i-1)*2+1]
162
+
163
+ }
164
+ data=[
165
+ 0.4717533638651177E-01,-0.9815606342467191E+00,
166
+ 0.1069393259953183E+00,-0.9041172563704750E+00,
167
+ 0.1600783285433464E+00,-0.7699026741943050E+00,
168
+ 0.2031674267230659E+00,-0.5873179542866171E+00,
169
+ 0.2334925365383547E+00,-0.3678314989981802E+00,
170
+ 0.2491470458134029E+00,-0.1252334085114692E+00]
171
+ (1..6).each {|i|
172
+ w[i][2]=data[(i-1)*2]
173
+ x[i][2]=data[(i-1)*2+1]
174
+
175
+
176
+ }
177
+ data=[
178
+ 0.1761400713915212E-01,-0.9931285991850949E+00,
179
+ 0.4060142980038694E-01,-0.9639719272779138E+00,
180
+ 0.6267204833410906E-01,-0.9122344282513259E+00,
181
+ 0.8327674157670475E-01,-0.8391169718222188E+00,
182
+ 0.1019301198172404E+00,-0.7463319064601508E+00,
183
+ 0.1181945319615184E+00,-0.6360536807265150E+00,
184
+ 0.1316886384491766E+00,-0.5108670019508271E+00,
185
+ 0.1420961093183821E+00,-0.3737060887154196E+00,
186
+ 0.1491729864726037E+00,-0.2277858511416451E+00,
187
+ 0.1527533871307259E+00,-0.7652652113349733E-01]
188
+
189
+ (1..10).each {|i|
190
+ w[i][3]=data[(i-1)*2]
191
+ x[i][3]=data[(i-1)*2+1]
192
+
193
+
194
+ }
195
+
196
+
197
+ if ( r.abs < 0.3 )
198
+ ng = 1
199
+ lg = 3
200
+ elsif ( r.abs < 0.75 )
201
+ ng = 2
202
+ lg = 6
203
+ else
204
+ ng = 3
205
+ lg = 10
206
+ end
207
+
208
+
209
+ h = dh
210
+ k = dk
211
+ hk = h*k
212
+ bvn = 0
213
+ if ( r.abs < 0.925 )
214
+ if ( r.abs > 0 )
215
+ hs = ( h*h + k*k ).quo(2)
216
+ asr = Math::asin(r)
217
+ (1..lg).each do |i|
218
+ [-1,1].each do |is|
219
+ sn = Math::sin(asr*(is* x[i][ng]+1).quo(2) )
220
+ bvn = bvn + w[i][ng] * Math::exp( ( sn*hk-hs ).quo( 1-sn*sn ) )
221
+ end # do
222
+ end # do
223
+ bvn = bvn*asr.quo( 2*twopi )
224
+ end # if
225
+ bvn = bvn + Distribution::Normal.cdf(-h) * Distribution::Normal.cdf(-k)
226
+
227
+
228
+ else # r.abs
229
+ if ( r < 0 )
230
+ k = -k
231
+ hk = -hk
232
+ end
233
+
234
+ if ( r.abs < 1 )
235
+ as = ( 1 - r )*( 1 + r )
236
+ a = Math::sqrt(as)
237
+ bs = ( h - k )**2
238
+ c = ( 4 - hk ).quo(8)
239
+ d = ( 12 - hk ).quo(16)
240
+ asr = -( bs.quo(as) + hk ).quo(2)
241
+ if ( asr > -100 )
242
+ bvn = a*Math::exp(asr) * ( 1 - c*( bs - as )*( 1 - d*bs.quo(5) ).quo(3) + c*d*as*as.quo(5) )
243
+ end
244
+ if ( -hk < 100 )
245
+ b = Math::sqrt(bs)
246
+ bvn = bvn - Math::exp( -hk.quo(2) ) * Math::sqrt(twopi)*Distribution::Normal.cdf(-b.quo(a))*b *
247
+ ( 1 - c*bs*( 1 - d*bs.quo(5) ).quo(3) )
248
+ end
249
+
250
+
251
+ a = a.quo(2)
252
+ (1..lg).each do |i|
253
+ [-1,1].each do |is|
254
+ xs = (a*( is*x[i][ng] + 1 ) )**2
255
+ rs = Math::sqrt( 1 - xs )
256
+ asr = -( bs/xs + hk ).quo(2)
257
+ if ( asr > -100 )
258
+ bvn = bvn + a*w[i][ng] * Math::exp( asr ) *
259
+ ( Math::exp( -hk*( 1 - rs ).quo(2*( 1 + rs ) ) ) .quo(rs) - ( 1 + c*xs*( 1 + d*xs ) ) )
260
+ end
261
+ end
262
+ end
263
+ bvn = -bvn/twopi
264
+ end
265
+
266
+ if ( r > 0 )
267
+ bvn = bvn + Distribution::Normal.cdf(-[h,k].max)
268
+ else
269
+ bvn = -bvn
270
+ if ( k > h )
271
+ bvn = bvn + Distribution::Normal.cdf(k) - Distribution::Normal.cdf(h)
272
+ end
273
+ end
274
+ end
275
+ bvn
276
+ end
277
+ private :f, :sgn
278
+ end
279
+ end
280
+ end
281
+ end