distribution 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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