distribution-0.7.3/0000755000004100000410000000000012540356202014267 5ustar www-datawww-datadistribution-0.7.3/Rakefile0000644000004100000410000000101112540356202015725 0ustar www-datawww-datarequire 'bundler' require 'bundler/gem_tasks' require 'rake' require 'rspec/core/rake_task' # Setup the necessary gems, specified in the gemspec. begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e $stderr.puts e.message $stderr.puts "Run `bundle install` to install missing gems" exit e.status_code end desc "Open an irb session preloaded with distribution" task :console do sh "irb -rubygems -I lib -r distribution.rb" end RSpec::Core::RakeTask.new(:spec) task :default => :spec distribution-0.7.3/data/0000755000004100000410000000000012540356202015200 5ustar www-datawww-datadistribution-0.7.3/data/template/0000755000004100000410000000000012540356202017013 5ustar www-datawww-datadistribution-0.7.3/data/template/distribution/0000755000004100000410000000000012540356202021532 5ustar www-datawww-datadistribution-0.7.3/data/template/distribution/gsl.erb0000644000004100000410000000042012540356202023005 0ustar www-datawww-datamodule Distribution module <%= distribution.capitalize %> module GSL_ class << self def pdf(x <% parameters %>) end def cdf(x <% parameters %>) end def p_value(pr <% parameters %>) end end end end enddistribution-0.7.3/data/template/distribution/ruby.erb0000644000004100000410000000042112540356202023202 0ustar www-datawww-datamodule Distribution module <%= distribution.capitalize %> module Ruby_ class << self def pdf(x <% parameters %>) end def cdf(x <% parameters %>) end def p_value(pr <% parameters %>) end end end end enddistribution-0.7.3/data/template/distribution.erb0000644000004100000410000000107312540356202022225 0ustar www-datawww-datarequire 'distribution/<%= distribution.downcase %>/ruby' require 'distribution/<%= distribution.downcase %>/gsl' #require 'distribution/<%= distribution.downcase %>/java' module Distribution # TODO: Document this Distribution module <%= distribution.capitalize %> SHORTHAND='<%= distribution.downcase[0,4] %>' extend Distributable create_distribution_methods ## # :singleton-method: pdf(x <%= parameters %>) ## # :singleton-method: cdf(x <%= parameters %>) ## # :singleton-method: p_value(pr <%= parameters %>) end end distribution-0.7.3/data/template/spec.erb0000644000004100000410000000241512540356202020441 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") describe Distribution::<%= distribution.capitalize %> do shared_examples_for "<%= distribution %> engine" do it "should return correct pdf" do if @engine.respond_to? :pdf else pending("No #{@engine}.pdf") end end it "should return correct cdf" do if @engine.respond_to? :cdf else pending("No #{@engine}.cdf") end end it "should return correct p_value" do if @engine.respond_to? :p_value else pending("No #{@engine}.cdf") end end end describe "singleton" do before do @engine=Distribution::<%= distribution.capitalize %> end it_should_behave_like "<%= distribution %> engine" end describe Distribution::<%= distribution.capitalize %>::Ruby_ do before do @engine=Distribution::<%= distribution.capitalize %>::Ruby_ end it_should_behave_like "<%= distribution %> engine" end if Distribution.has_gsl? describe Distribution::<%= distribution.capitalize %>::GSL_ do before do @engine=Distribution::<%= distribution.capitalize %>::GSL_ end it_should_behave_like "<%= distribution %> engine" end end end distribution-0.7.3/bin/0000755000004100000410000000000012540356202015037 5ustar www-datawww-datadistribution-0.7.3/bin/distribution0000755000004100000410000000323612540356202017510 0ustar www-datawww-data#!/usr/bin/env ruby require 'optparse' require 'fileutils' require 'erb' gem_base=File.expand_path(File.dirname(__FILE__)+"/..") require gem_base+"/lib/distribution" new=false parameters="" OptionParser.new do |opts| opts.banner="Usage: distribution [--new] [--params parameters] distribution" opts.on("-n", "--new", "Create a new template for distribution") do new=true end opts.on("-PMANDATORY", "--params MANDATORY", String, "Parameters for distribution") do |n_param| parameters=", #{n_param}" end opts.on("-h", "--help", "Show this message") do puts opts exit end begin ARGV << "-h" if ARGV.empty? opts.parse!(ARGV) rescue OptionParser::ParseError => e STDERR.puts e.message, "\n", opts exit(-1) end end ARGV.each do |distribution| if new basename=distribution.downcase raise "You should be inside distribution lib directory" unless File.exists? "../distribution.rb" raise "Distribution already created" if File.exists? basename+".rb" main=ERB.new(File.read(gem_base+"/data/template/distribution.erb")) ruby=ERB.new(File.read(gem_base+"/data/template/distribution/ruby.erb")) gsl=ERB.new(File.read(gem_base+"/data/template/distribution/gsl.erb")) spec=ERB.new(File.read(gem_base+"/data/template/spec.erb")) FileUtils.mkdir(basename) unless File.exists? basename File.open(basename+".rb","w") {|fp| fp.write(main.result(binding))} File.open(basename+"/ruby.rb","w") {|fp| fp.write(ruby.result(binding))} File.open(basename+"/gsl.rb","w") {|fp| fp.write(gsl.result(binding))} File.open("../../spec/#{basename}_spec.rb","w") {|fp| fp.write(spec.result(binding))} end end distribution-0.7.3/Gemfile0000644000004100000410000000010012540356202015551 0ustar www-datawww-datasource "https://rubygems.org" gem 'rb-gsl', '~> 1.16' gemspec distribution-0.7.3/LICENCE.md0000644000004100000410000000275512540356202015664 0ustar www-datawww-data## LICENSE: Copyright (c) 2011-2012, Claudio Bustos All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Claudio Bustos BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. distribution-0.7.3/History.txt0000644000004100000410000000703312540356202016474 0ustar www-datawww-data=== 0.7.3 / 2015-05-28 * Fixed F::Ruby_.p_value. === 0.7.2 / 2015-04-03 * Formatting files according to the community's best practices. * Other minor improvements in gemspec, Rakefile, etc. === 0.7.0 / 2011-11-30 + Basic log-normal distribution support, with pdf and cdf for ruby [dennyabraham and clbustos] * Matthew Peterson add Java support for Poisson and Normal distributions. * Updated Logistic, Normal spec. Added LogNormal spec [clbustos] * Updated template for new distributions === 0.6.0 / 2011-09-23 * Incomplete Beta functions on math renamed to Regularized beta, because MathExtension::IncompleteBeta calculates regularized beta function, not Incomplete Beta. * Corrected documention on F distribution and added comments on gamma and beta[Claudio Bustos] * Moved ported methods from GSL to lib/math_extension. Updated spec for gamma and beta distributions[Claudio Bustos] * Added beta distribution functions. p_value does not seem to work yet.[John Woods] * Added most incomplete beta function GSL translations, also log_beta from GSL.[John Woods] * Added header information to the incomplete gamma files translated from GSL[John Woods] * Removed left-over invgammp function.[John Woods] * Fixed lots of bugs, translated most GSL error tests into rspec.[John Woods] * Added Gamma distribution, spec. No statistics2 functions for Gamma, so only implemented pure Ruby and GSL.[John Woods] * Added console task to rakefile[John Woods] === 0.5.0 / 2011-05-03 * Exception raises on calculation of T's cdf with ruby engine. For now, stick to gsl implementation * Added logistic distribution. * Raises an error on binomial if k>n. * New rng for exponential distribution, based on F^-1 [clbustos] * Added power benchmark === 0.4.0 / 2011-02-01 * Poisson and exponential distributions implemented. Implementation of inverse cdf for poisson is not perfect, yet. * +distribution+ executable can create template files for new distributions. * MathExtension should work fine with Ruby 1.8. Fixed shadowed variable on MathExtension.naive_factorial * Added factorial lookup table for n<20. * Added exact cdf for Binomial * Binomial coefficient in function of permutations. Deleted incomplete beta until we found a faster way to calculate it === 0.3.0 / 2011-01-28 * Included support for binomial distribution. p_value is not accurate * Included alias for ruby exact methods on discrete distributions, when they are available * Works on Jruby and Ruby 1.8.7 * Binomial coefficient optimized. Falling factorial method with Swing Prime on factorial provides a 10x improvement over naive version. * Working on binomial coefficient using gamma. The same problem as using Sterling: faster than exact version, but when it requires BigDecimal, is 2-3x slower * Deleted Fixnum extension on Hypergeometric === 0.2.0 / 2011-01-27 * Shorthands for F and T are 'fdist' and 'tdist' now, to avoid confussions * Added Hypergeometric distribution with pdf, cdf, p_value. The Ruby version uses a very slow factorial process, but also has pdf_with_stirling if you don't care about accuracy at all. This latter method needs to be improved, actually, in terms of which choose function it calls for the numerator and denominator. Once that's done, it can replace the slower pdf function. [John Woods] * Spec for cdf and p_value of Hypergeometric * New cdf and p_value on Hypergeometric[clbustos] * Hypergeometric#pdf returns 0 on max(0,n+m-t)<=k<=min(m,n) * Improved factorial calculation, using Luschny algorithms === 0.1.0 / 2011-01-26 * Basic set (pdf, cdf, p_value) for Normal, Chi Square, F and T distributions distribution-0.7.3/spec/0000755000004100000410000000000012540356202015221 5ustar www-datawww-datadistribution-0.7.3/spec/beta_spec.rb0000644000004100000410000000475012540356202017501 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") include ExampleWithGSL describe Distribution::Beta do shared_examples_for "Beta engine" do it_only_with_gsl "should return correct pdf" do if @engine.respond_to? :pdf 1.upto(101) do |x| a=rand * x b=1 + rand * 5 g=GSL::Ran.beta_pdf(x,a,b) @engine.pdf(x,a,b).should be_within(1e-09).of(g) end else skip("No #{@engine}.pdf") end end it_only_with_gsl "should return correct cdf" do if @engine.respond_to? :cdf # From GSL-1.9. tol = 1048576.0*Float::EPSILON @engine.cdf(0.0, 1.2, 1.3).should eq(0.0) @engine.cdf(1e-100, 1.2, 1.3).should be_within(tol).of(1.34434944656489596e-120) @engine.cdf(0.001, 1.2, 1.3).should be_within(tol).of(3.37630042504535813e-4) @engine.cdf(0.01, 1.2, 1.3).should be_within(tol).of(5.34317264038929473e-3) @engine.cdf(0.1, 1.2, 1.3).should be_within(tol).of(8.33997828306748346e-2) @engine.cdf(0.325, 1.2, 1.3).should be_within(tol).of(3.28698654180583916e-1) @engine.cdf(0.5, 1.2, 1.3).should be_within(tol).of(5.29781429451299081e-1) @engine.cdf(0.9, 1.2, 1.3).should be_within(tol).of(9.38529397224430659e-1) @engine.cdf(0.99, 1.2, 1.3).should be_within(tol).of(9.96886438341254380e-1) @engine.cdf(0.999, 1.2, 1.3).should be_within(tol).of(9.99843792833067634e-1) @engine.cdf(1.0, 1.2, 1.3).should be_within(tol).of(1.0) else skip("No #{@engine}.cdf") end end it "should return correct p_value" do if @engine.respond_to? :p_value 2.upto(99) do |x| a=rand() * x b=1 + rand() * 5 pr=@engine.cdf(x/100.0,a,b) @engine.p_value(pr,a, b).should be_within(1e-09).of(x/100.0) end else skip("No #{@engine}.p_value") end end end describe "singleton" do before do @engine=Distribution::Beta end it_should_behave_like "Beta engine" end describe Distribution::Beta::Ruby_ do before do @engine=Distribution::Beta::Ruby_ end it_should_behave_like "Beta engine" end if Distribution.has_gsl? describe Distribution::Beta::GSL_ do before do @engine=Distribution::Beta::GSL_ end it_should_behave_like "Beta engine" end end if Distribution.has_java? describe Distribution::Beta::Java_ do before do @engine=Distribution::Beta::Java_ end it_should_behave_like "Beta engine" end end end distribution-0.7.3/spec/gamma_spec.rb0000644000004100000410000000527212540356202017650 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") include ExampleWithGSL describe Distribution::Gamma do shared_examples_for "Gamma engine" do it_only_with_gsl "should return correct pdf" do if @engine.respond_to? :pdf 1.upto(101) do |x| a=rand * x b=1 + rand * 5 g=GSL::Ran.gamma_pdf(x,a,b) @engine.pdf(x,a,b).should be_within(1e-10).of(g) end else pending("No #{@engine}.pdf") end end it_only_with_gsl "should return correct cdf" do if @engine.respond_to? :cdf # From GSL-1.9. tol = 1048576.0*Float::EPSILON @engine.cdf(0.0, 1.0, 1.0).should eq(0.0) @engine.cdf(1e-100, 1.0, 1.0).should be_within(tol).of(1e-100) @engine.cdf(0.001, 1.0, 1.0).should be_within(tol).of(9.99500166625008332e-4) @engine.cdf(0.01, 1.0, 1.0).should be_within(tol).of(9.95016625083194643e-3) @engine.cdf(0.1, 1.0, 1.0).should be_within(tol).of(9.51625819640404268e-2) @engine.cdf(0.325, 1.0, 1.0).should be_within(tol).of(2.77472646357927811e-1) @engine.cdf(1.0, 1.0, 1.0).should be_within(tol).of(6.32120558828557678e-1) @engine.cdf(1.5, 1.0, 1.0).should be_within(tol).of(7.76869839851570171e-1) @engine.cdf(2.0, 1.0, 1.0).should be_within(tol).of(8.64664716763387308e-1) @engine.cdf(10.0, 1.0, 1.0).should be_within(tol).of(9.99954600070237515e-1) @engine.cdf(20.0, 1.0, 1.0).should be_within(tol).of(9.99999997938846378e-1) @engine.cdf(100.0, 1.0, 1.0).should be_within(tol).of(1e0) @engine.cdf(1000.0, 1.0, 1.0).should be_within(tol).of(1e0) @engine.cdf(10000.0, 1.0, 1.0).should be_within(tol).of(1e0) else pending("No #{@engine}.cdf") end end it "should return correct p_value" do if @engine.respond_to? :p_value 1.upto(20) do |x| a=rand()*0.5 b=1 + rand() * 5 pr=@engine.cdf(x,a,b) @engine.p_value(pr,a,b).should be_within(1e-3).of(x) end else skip("No #{@engine}.p_value") end end end describe "singleton" do before do @engine=Distribution::Gamma end it_should_behave_like "Gamma engine" end describe Distribution::Gamma::Ruby_ do before do @engine=Distribution::Gamma::Ruby_ end it_should_behave_like "Gamma engine" end if Distribution.has_gsl? describe Distribution::Gamma::GSL_ do before do @engine=Distribution::Gamma::GSL_ end it_should_behave_like "Gamma engine" end end if Distribution.has_java? describe Distribution::Gamma::Java_ do before do @engine=Distribution::Gamma::Java_ end it_should_behave_like "Gamma engine" end end end distribution-0.7.3/spec/exponential_spec.rb0000644000004100000410000000444112540356202021111 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") describe Distribution::Exponential do shared_examples_for "exponential engine" do it "should return correct pdf" do if @engine.respond_to? :pdf [0.5,1,1.5].each {|l| 1.upto(5) {|x| @engine.pdf(x,l).should be_within(1e-10).of(l*Math.exp(-l*x)) } } else pending("No #{@engine}.pdf") end end it "should return correct cdf" do if @engine.respond_to? :cdf [0.5,1,1.5].each {|l| 1.upto(5) {|x| @engine.cdf(x,l).should be_within(1e-10).of(1-Math.exp(-l*x)) } } else pending("No #{@engine}.cdf") end end it "should return correct p_value" do if @engine.respond_to? :p_value [0.5,1,1.5].each {|l| 1.upto(5) {|x| pr=@engine.cdf(x,l) @engine.p_value(pr,l).should be_within(1e-10).of(x) } } else pending("No #{@engine}.p_value") end end end describe "singleton" do before do @engine=Distribution::Exponential end it_should_behave_like "exponential engine" end describe Distribution::Exponential::Ruby_ do before do @engine=Distribution::Exponential::Ruby_ end it_should_behave_like "exponential engine" end if Distribution.has_gsl? describe Distribution::Exponential::GSL_ do before do @engine=Distribution::Exponential::GSL_ end it_should_behave_like "exponential engine" end end # if Distribution.has_java? # describe Distribution::Exponential::Java_ do # before do # @engine=Distribution::Exponential::Java_ # end # it_should_behave_like "exponential engine" # # end # end describe "rng" do it "should default to Kernel#rand if no :random is given" do Random.stub(:rand) Random.should_receive(:rand).and_return(0.5) rng = Distribution::Exponential.rng 1.0 rng.call() end it "should use a given rng if one is passed during construction" do random = double("random") random.should_receive(:rand).and_return(0.5) rng = Distribution::Exponential::rng 1.0, :random => random rng.call() end end end distribution-0.7.3/spec/math_extension_spec.rb0000644000004100000410000003352412540356202021614 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") include ExampleWithGSL describe Distribution::MathExtension do it "binomial coefficient should be correctly calculated" do n=50 n.times do |k| Math.binomial_coefficient(n,k).should eq(Math.factorial(n).quo(Math.factorial(k)*Math.factorial(n-k))),"not correct for k=#{k}" end end it "ChebyshevSeries for :sin should return correct values" do #Math::SIN_CS.evaluate() end it "log_1plusx_minusx should return correct values" do # Tests from GSL-1.9 Math::Log.log_1plusx_minusx(1.0e-10).should be_within(1e-10).of(-4.999999999666666667e-21) Math::Log.log_1plusx_minusx(1.0e-8).should be_within(1e-10).of(-4.999999966666666917e-17) Math::Log.log_1plusx_minusx(1.0e-4).should be_within(1e-10).of(-4.999666691664666833e-09) Math::Log.log_1plusx_minusx(0.1).should be_within(1e-10).of(-0.004689820195675139956) Math::Log.log_1plusx_minusx(0.49).should be_within(1e-10).of(-0.09122388004263222704) Math::Log.log_1plusx_minusx(-0.49).should be_within(1e-10).of(-0.18334455326376559639) Math::Log.log_1plusx_minusx(1.0).should be_within(1e-10).of(Math::LN2 - 1.0) Math::Log.log_1plusx_minusx(-0.99).should be_within(1e-10).of(-3.615170185988091368) end it "log_1plusx should return correct values" do # Tests from GSL-1.9 Math::Log.log_1plusx(1.0e-10).should be_within(1e-10).of(9.999999999500000000e-11) Math::Log.log_1plusx(1.0e-8).should be_within(1e-10).of(9.999999950000000333e-09) Math::Log.log_1plusx(1.0e-4).should be_within(1e-10).of(0.00009999500033330833533) Math::Log.log_1plusx(0.1).should be_within(1e-10).of(0.09531017980432486004) Math::Log.log_1plusx(0.49).should be_within(1e-10).of(0.3987761199573677730) Math::Log.log_1plusx(-0.49).should be_within(1e-10).of(-0.6733445532637655964) Math::Log.log_1plusx(1.0).should be_within(1e-10).of(Math::LN2) Math::Log.log_1plusx(-0.99).should be_within(1e-10).of(-4.605170185988091368) end it "log_beta should return correct values" do Math::Beta.log_beta(1.0e-8, 1.0e-8).first.should be_within(1e-10).of(19.113827924512310617) Math::Beta.log_beta(1.0e-8, 0.01).first.should be_within(1e-10).of(18.420681743788563403) Math::Beta.log_beta(1.0e-8, 1.0).first.should be_within(1e-10).of(18.420680743952365472) Math::Beta.log_beta(1.0e-8, 10.0).first.should be_within(1e-10).of(18.420680715662683009) Math::Beta.log_beta(1.0e-8, 1000.0).first.should be_within(1e-10).of(18.420680669107656949) Math::Beta.log_beta(0.1, 0.1).first.should be_within(1e-10).of(2.9813614810376273949) Math::Beta.log_beta(0.1, 1.0).first.should be_within(1e-10).of(2.3025850929940456840) Math::Beta.log_beta(0.1, 100.0).first.should be_within(1e-10).of(1.7926462324527931217) Math::Beta.log_beta(0.1, 1000).first.should be_within(1e-10).of(1.5619821298353164928) Math::Beta.log_beta(1.0, 1.00025).first.should be_within(1e-10).of(-0.0002499687552073570) Math::Beta.log_beta(1.0, 1.01).first.should be_within(1e-10).of(-0.009950330853168082848) Math::Beta.log_beta(1.0, 1000.0).first.should be_within(1e-10).of(-6.907755278982137052) Math::Beta.log_beta(100.0, 100.0).first.should be_within(1e-10).of(-139.66525908670663927) Math::Beta.log_beta(100.0, 1000.0).first.should be_within(1e-10).of(-336.4348576477366051) Math::Beta.log_beta(100.0, 1.0e+8).first.should be_within(1e-10).of(-1482.9339185256447309) end it "regularized_beta should return correct values" do Math.regularized_beta(0.0,1.0, 1.0).should be_within(1e-10).of(0.0) Math.regularized_beta(1.0, 1.0, 1.0).should be_within(1e-10).of(1.0) Math.regularized_beta(1.0, 0.1, 0.1).should be_within(1e-10).of(1.0) Math.regularized_beta(0.5, 1.0, 1.0).should be_within(1e-10).of(0.5) Math.regularized_beta(0.5, 0.1, 1.0).should be_within(1e-10).of(0.9330329915368074160) Math.regularized_beta(0.5, 10.0, 1.0).should be_within(1e-10).of(0.0009765625000000000000) Math.regularized_beta(0.5, 50.0, 1.0).should be_within(1e-10).of(8.881784197001252323e-16) Math.regularized_beta(0.5, 1.0, 0.1).should be_within(1e-10).of(0.06696700846319258402) Math.regularized_beta(0.5, 1.0, 10.0).should be_within(1e-10).of(0.99902343750000000000) Math.regularized_beta(0.5, 1.0, 50.0).should be_within(1e-10).of(0.99999999999999911180) Math.regularized_beta(0.1, 1.0, 1.0).should be_within(1e-10).of(0.10) Math.regularized_beta(0.1, 1.0, 2.0).should be_within(1e-10).of(0.19) Math.regularized_beta(0.9, 1.0, 2.0).should be_within(1e-10).of(0.99) Math.regularized_beta(0.5, 50.0, 60.0).should be_within(1e-10).of(0.8309072939016694143) Math.regularized_beta(0.5, 90.0, 90.0).should be_within(1e-10).of(0.5) Math.regularized_beta(0.5, 500.0, 500.0).should be_within(1e-10).of(0.5) Math.regularized_beta(0.4, 5000.0, 5000.0).should be_within(1e-10).of(4.518543727260666383e-91) Math.regularized_beta(0.6, 5000.0, 5000.0).should be_within(1e-10).of(1.0) Math.regularized_beta(0.6, 5000.0, 2000.0).should be_within(1e-10).of(8.445388773903332659e-89) end it_only_with_gsl "incomplete_beta should return correct values" do a=rand()*10+1 b=rand()*10+1 ib = GSL::Function.alloc { |t| t**(a-1)*(1-t)**(b-1)} w = GSL::Integration::Workspace.alloc(1000) 1.upto(10) {|x| inte=ib.qag([0,x / 10.0],w) Math.incomplete_beta(x/10.0, a ,b).should be_within(1e-10).of(inte[0]) } end it "gammastar should return correct values" do # Tests from GSL-1.9 Math::Gammastar.evaluate(1.0e-08).should be_within(1e-10).of(3989.423555759890865) Math::Gammastar.evaluate(1.0e-05).should be_within(1e-10).of(126.17168469882690233) Math::Gammastar.evaluate(0.001).should be_within(1e-10).of(12.708492464364073506) Math::Gammastar.evaluate(1.5).should be_within(1e-10).of(1.0563442442685598666) Math::Gammastar.evaluate(3.0).should be_within(1e-10).of(1.0280645179187893045) Math::Gammastar.evaluate(9.0).should be_within(1e-10).of(1.0092984264218189715) Math::Gammastar.evaluate(11.0).should be_within(1e-10).of(1.0076024283104962850) Math::Gammastar.evaluate(100.0).should be_within(1e-10).of(1.0008336778720121418) Math::Gammastar.evaluate(1.0e+05).should be_within(1e-10).of(1.0000008333336805529) Math::Gammastar.evaluate(1.0e+20).should be_within(1e-10).of(1.0) end it "erfc_e should return correct values" do # From GSL-1.9. For troubleshooting gammq. Math::erfc_e(-10.0).should be_within(1e-10).of(2.0) Math::erfc_e(-5.0000002).should be_within(1e-10).of(1.9999999999984625433) Math::erfc_e(-5.0).should be_within(1e-10).of(1.9999999999984625402) Math::erfc_e(-1.0).should be_within(1e-10).of(1.8427007929497148693) Math::erfc_e(-0.5).should be_within(1e-10).of(1.5204998778130465377) Math::erfc_e(1.0).should be_within(1e-10).of(0.15729920705028513066) Math::erfc_e(3.0).should be_within(1e-10).of(0.000022090496998585441373) Math::erfc_e(7.0).should be_within(1e-10).of(4.183825607779414399e-23) Math::erfc_e(10.0).should be_within(1e-10).of(2.0884875837625447570e-45) end it "unnormalized_incomplete_gamma with x=0 should return correct values" do Math.unnormalized_incomplete_gamma(-1.5, 0).should be_within(1e-10).of(4.0*Math.sqrt(Math::PI) / 3.0) Math.unnormalized_incomplete_gamma(-0.5, 0).should be_within(1e-10).of(-2*Math.sqrt(Math::PI)) Math.unnormalized_incomplete_gamma(0.5, 0).should be_within(1e-10).of(Math.sqrt(Math::PI)) Math.unnormalized_incomplete_gamma(1.0, 0).should eq 1.0 Math.unnormalized_incomplete_gamma(1.5, 0).should be_within(1e-10).of(Math.sqrt(Math::PI) / 2.0) Math.unnormalized_incomplete_gamma(2.0, 0).should eq 1.0 Math.unnormalized_incomplete_gamma(2.5, 0).should be_within(1e-10).of(0.75*Math.sqrt(Math::PI)) Math.unnormalized_incomplete_gamma(3.0, 0).should be_within(1e-12).of(2.0) Math.unnormalized_incomplete_gamma(3.5, 0).should be_within(1e-10).of(15.0*Math.sqrt(Math::PI) / 8.0) Math.unnormalized_incomplete_gamma(4.0, 0).should be_within(1e-12).of(6.0) end it "incomplete_gamma should return correct values" do # Tests from GSL-1.9 Math.incomplete_gamma(1e-100, 0.001).should be_within(1e-10).of(1.0) Math.incomplete_gamma(0.001, 0.001).should be_within(1e-10).of(0.9936876467088602902) Math.incomplete_gamma(0.001, 1.0).should be_within(1e-10).of(0.9997803916424144436) Math.incomplete_gamma(0.001, 10.0).should be_within(1e-10).of(0.9999999958306921828) Math.incomplete_gamma(1.0, 0.001).should be_within(1e-10).of(0.0009995001666250083319) Math.incomplete_gamma(1.0, 1.01).should be_within(1e-10).of(0.6357810204284766802) Math.incomplete_gamma(1.0, 10.0).should be_within(1e-10).of(0.9999546000702375151) Math.incomplete_gamma(10.0, 10.01).should be_within(1e-10).of(0.5433207586693410570) Math.incomplete_gamma(10.0, 20.0).should be_within(1e-10).of(0.9950045876916924128) Math.incomplete_gamma(1000.0, 1000.1).should be_within(1e-10).of(0.5054666401440661753) Math.incomplete_gamma(1000.0, 2000.0).should be_within(1e-10).of(1.0) # designed to trap the a-x=1 problem # These next two are 1e-7 because they give the same output as GSL, but GSL is apparently not totally accurate here. # It's a problem with log_1plusx_mx (log_1plusx_minusx in my code) Math.incomplete_gamma(100, 99.0).should be_within(1e-7).of(0.4733043303994607) Math.incomplete_gamma(200, 199.0).should be_within(1e-7).of(0.4811585880878718) # Test for x86 cancellation problems Math.incomplete_gamma(5670, 4574).should be_within(1e-10).of(3.063972328743934e-55) end it "gammq should return correct values" do # Tests from GSL-1.9 Math.gammq(0.0, 0.001).should be_within(1e-10).of(0.0) Math.gammq(0.001, 0.001).should be_within(1e-10).of(0.006312353291139709793) Math.gammq(0.001, 1.0).should be_within(1e-10).of(0.00021960835758555639171) Math.gammq(0.001, 2.0).should be_within(1e-10).of(0.00004897691783098147880) Math.gammq(0.001, 5.0).should be_within(1e-10).of(1.1509813397308608541e-06) Math.gammq(1.0, 0.001).should be_within(1e-10).of(0.9990004998333749917) Math.gammq(1.0, 1.01).should be_within(1e-10).of(0.3642189795715233198) Math.gammq(1.0, 10.0).should be_within(1e-10).of(0.00004539992976248485154) Math.gammq(10.0, 10.01).should be_within(1e-10).of(0.4566792413306589430) Math.gammq(10.0, 100.0).should be_within(1e-10).of(1.1253473960842733885e-31) Math.gammq(1000.0, 1000.1).should be_within(1e-10).of(0.4945333598559338247) Math.gammq(1000.0, 2000.0).should be_within(1e-10).of(6.847349459614753180e-136) # designed to trap the a-x=1 problem Math.gammq(100, 99.0).should be_within(1e-10).of(0.5266956696005394) Math.gammq(200, 199.0).should be_within(1e-10).of(0.5188414119121281) # Test for x86 cancellation problems Math.gammq(5670, 4574).should be_within(1e-10).of(1.0000000000000000) # test suggested by Michel Lespinasse [gsl-discuss Sat, 13 Nov 2004] Math.gammq(1.0e+06-1.0, 1.0e+06-2.0).should be_within(1e-10).of(0.50026596175224547004) # tests in asymptotic regime related to Lespinasse test Math.gammq(1.0e+06+2.0, 1.0e+06+1.0).should be_within(1e-10).of(0.50026596135330304336) Math.gammq(1.0e+06, 1.0e+06-2.0).should be_within(1e-10).of(0.50066490399940144811) Math.gammq(1.0e+07, 1.0e+07-2.0).should be_within(1e-10).of(0.50021026104978614908) end it "rising_factorial should return correct values" do x=rand(10)+1 Math.rising_factorial(x,0).should eq 1 Math.rising_factorial(x,1).should eq x Math.rising_factorial(x,2).should eq x**2+x Math.rising_factorial(x,3).should eq x**3+3*x**2+2*x Math.rising_factorial(x,4).should eq x**4+6*x**3+11*x**2+6*x end it "permutations should return correct values" do n=rand(50)+50 10.times { |k| Math.permutations(n,k).should eq(Math.factorial(n) / Math.factorial(n-k)) } Math.permutations(n,n).should eq(Math.factorial(n) / Math.factorial(n-n)) end it "exact regularized incomplete beta should behave properly" do Math.exact_regularized_beta(0.5,5,5).should be_within(1e-6).of(0.5) Math.exact_regularized_beta(0.5,5,6).should be_within(1e-6).of(0.6230469) Math.exact_regularized_beta(0.5,5,7).should be_within(1e-6).of(0.725586) a=5 b=5 Math.exact_regularized_beta(0,a,b).should eq 0 Math.exact_regularized_beta(1,a,b).should eq 1 x=rand() Math.exact_regularized_beta(x,a,b).should be_within(1e-6). of(1-Math.regularized_beta(1-x,b,a)) end it "binomial coefficient(gamma) with n<=48 should be correct " do [1,5,10,25,48].each {|n| k=(n/2).to_i Math.binomial_coefficient_gamma(n,k).round.should eq(Math.binomial_coefficient(n,k)) } end it "binomial coefficient(gamma) with 4833" do ac=8683317618811886495518194401280000000 # 33! Math.factorial(33).should eq ac 34.upto(40).each do |i| ac*=i Math.factorial(i).should eq(ac) end end end end distribution-0.7.3/spec/shorthand_spec.rb0000644000004100000410000000223612540356202020555 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") describe Distribution::Shorthand do include Distribution::Shorthand it "should have basic methods for all distributions" do [:Normal,:ChiSquare, :F, :Hypergeometric, :Binomial, :T].each do |d| klass=Distribution.const_get(d) shortname=klass::SHORTHAND methods=[:pdf, :cdf, :p_value].map {|m| "#{shortname}_#{m}".to_sym} methods.each do |m| Distribution::Shorthand.instance_methods.map {|v| v.to_sym}.should include(m) end end end it "should have exact methods discrete distributions" do [:Hypergeometric, :Binomial].each do |d| klass=Distribution.const_get(d) shortname=klass::SHORTHAND methods=[:epdf, :ecdf].map {|m| "#{shortname}_#{m}".to_sym} methods.each do |m| Distribution::Shorthand.instance_methods.map {|v| v.to_sym}.should include(m) end end end it "returns same values as long form" do x=rand() norm_cdf(x).should eql(Distribution::Normal.cdf(x)) norm_pdf(x).should eql(Distribution::Normal.pdf(x)) norm_p_value(x).should eql(Distribution::Normal.p_value(x)) end end distribution-0.7.3/spec/spec.opts0000644000004100000410000000002012540356202017052 0ustar www-datawww-data--color -f s -b distribution-0.7.3/spec/lognormal_spec.rb0000644000004100000410000000265012540356202020555 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") describe Distribution::LogNormal do shared_examples_for "log-normal engine" do it "should return correct pdf" do if @engine.respond_to? :pdf 1.upto(10) { u=rand() s=rand()*100 x=rand()*50 exp=(1.0/(x*s*Math.sqrt(2*Math::PI)))*Math.exp(-((Math.log(x)-u)**2 / (2*s**2))) @engine.pdf(x,u,s).should be_within(1e-10).of(exp) } else pending("No #{@engine}.pdf") end end it "should return correct cdf" do if @engine.respond_to? :cdf 1.upto(10) { u=rand() s=rand()*100 x=rand()*50 exp=Distribution::Normal.cdf((Math.log(x) - u) / s) @engine.cdf(x,u,s).should be_within(1e-10).of(exp) } else pending("No #{@engine}.cdf") end end end describe "singleton" do before do @engine=Distribution::LogNormal end it_should_behave_like "log-normal engine" end describe Distribution::LogNormal::Ruby_ do before do @engine=Distribution::LogNormal::Ruby_ end it_should_behave_like "log-normal engine" end if Distribution.has_gsl? describe Distribution::LogNormal::GSL_ do before do @engine=Distribution::LogNormal::GSL_ end it_should_behave_like "log-normal engine" end end end distribution-0.7.3/spec/spec_helper.rb0000644000004100000410000000170212540356202020037 0ustar www-datawww-data$:.unshift(File.dirname(__FILE__)+"/../lib") begin require 'simplecov' SimpleCov.start do add_filter "/spec/" add_group "Libraries", "lib" end rescue LoadError end require 'rspec' require 'distribution' RSpec.configure do |config| config.expect_with :rspec do |c| c.syntax = [:should, :expect] end # Use color in STDOUT config.color = true # Use color not only in STDOUT but also in pagers and files config.tty = true # Use the specified formatter config.formatter = :documentation # :progress, :html, :textmate end module ExampleWithGSL def it_only_with_gsl(name,opts={},&block) it(name, opts) do if Distribution.has_gsl? instance_eval(&block) else skip("Requires GSL") end end end def it_only_with_java(name,&block) it(name) do if Distribution.has_java? instance_eval(&block) else skip("Requires Java") end end end end distribution-0.7.3/spec/t_spec.rb0000644000004100000410000000552312540356202017030 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") include ExampleWithGSL describe Distribution::T do shared_examples_for "T engine(with rng)" do it "should return correct rng" do pending() end end shared_examples_for "T engine(cdf with fractional df)" do it "should return correct cdf with fractional df" do @engine.cdf(1,2.5).should be_within(1e-6).of(0.7979695) @engine.cdf(2,3.5).should be_within(1e-6).of(0.9369307) @engine.cdf(3,4.5).should be_within(1e-6).of(0.9828096) end end shared_examples_for "T engine" do it_only_with_gsl "should return correct pdf" do if @engine.respond_to? :pdf [-2,0.1,0.5,1,2].each{|t| [2,5,10].each{|n| @engine.pdf(t,n).should be_within(1e-6).of(GSL::Ran.tdist_pdf(t,n)) @engine.pdf(t,n.to_f).should be_within(1e-6).of(@engine.pdf(t,n)) } } else pending("No #{@engine}.pdf") end end it_only_with_gsl "should return correct cdf" do if @engine.respond_to? :cdf # Testing with R values @engine.cdf(1,2).should be_within(1e-7).of(0.7886751) @engine.cdf(1,2.0).should be_within(1e-7).of(0.7886751) @engine.cdf(1,3.0).should be_within(1e-7).of(0.8044989) [-2,0.1,0.5,1,2].each{|t| [2,5,10].each{|n| @engine.cdf(t,n).should be_within(1e-4).of(GSL::Cdf.tdist_P(t,n)) @engine.cdf(t,n).should be_within(1e-4).of(@engine.cdf(t,n.to_f)) } } else pending("No #{@engine}.cdf") end end it_only_with_gsl "should return correct p_value" do if @engine.respond_to? :p_value [-2,0.1,0.5,1,2].each{|t| [2,5,10].each{|n| area=Distribution::T.cdf(t,n) @engine.p_value(area,n).should be_within(1e-4).of(GSL::Cdf.tdist_Pinv(area,n)) } } else pending("No #{@engine}.p_value") end end end describe "singleton" do before do @engine=Distribution::T end it_should_behave_like "T engine" end describe Distribution::T::Ruby_ do before do @engine=Distribution::T::Ruby_ end it_should_behave_like "T engine" it_should_behave_like "T engine(cdf with fractional df)" end if Distribution.has_gsl? describe Distribution::T::GSL_ do before do @engine=Distribution::T::GSL_ end it_should_behave_like "T engine" it_should_behave_like "T engine(cdf with fractional df)" end end =begin if Distribution.has_statistics2? describe Distribution::T::Statistics2_ do before do @engine=Distribution::T::Statistics2_ end it_should_behave_like "T engine" end end =end if Distribution.has_java? describe Distribution::T::Java_ do before do @engine=Distribution::T::Java_ end it_should_behave_like "T engine" end end end distribution-0.7.3/spec/f_spec.rb0000644000004100000410000000553312540356202017013 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__) + '/spec_helper.rb') include ExampleWithGSL describe Distribution::F do shared_examples_for 'F engine (with rng)' do it 'should return correct rng' do pending end end shared_examples_for 'F engine (with pdf)' do it_only_with_gsl 'should return correct pdf' do if @engine.respond_to? :pdf [0.1, 0.5, 1, 2, 10, 20, 30].each do |x| [2, 5, 10].product([2, 5, 10]).each do |n, m| expected_value = GSL::Ran.fdist_pdf(x, n, m) @engine.pdf(x, n, m).should be_within(1e-4).of(expected_value) end end else pending("No #{@engine}.pdf") end end end shared_examples_for 'F engine' do it_only_with_gsl 'should return correct cdf' do if @engine.respond_to? :cdf [0.1, 0.5, 1, 2, 10, 20, 30].each do |f| [2, 5, 10].each do |n2| [2, 5, 10].each do |n1| @engine.cdf(f, n1, n2).should be_within(1e-4).of(GSL::Cdf.fdist_P(f, n1, n2)) end end end else pending("No #{@engine}.cdf") end end it_only_with_gsl 'should return correct p_value', focus: true do if @engine.respond_to? :p_value expected_value = GSL::Cdf.fdist_Pinv(0.975, 5, 4.189092917592713) @engine.p_value(0.975, 5, 4.189092917592713).should be_within(1e-4).of(expected_value) [0.1, 0.5, 1, 2, 10, 20, 30].each do |f| [2, 5, 10].each do |n2| [2, 5, 10].each do |n1| area = @engine.cdf(f, n1, n2) expected_value = GSL::Cdf.fdist_Pinv(area, n1, n2) @engine.p_value(area, n1, n2).should be_within(1e-4).of(expected_value) end end end else pending("No #{@engine}.p_value") end end end describe 'singleton' do before do @engine = Distribution::F end it_should_behave_like 'F engine' it_should_behave_like 'F engine (with pdf)' end describe Distribution::F::Ruby_ do before do @engine = Distribution::F::Ruby_ end it_should_behave_like 'F engine' it_should_behave_like 'F engine (with pdf)' end if Distribution.has_gsl? describe Distribution::F::GSL_ do before do @engine = Distribution::F::GSL_ end it_should_behave_like 'F engine' it_should_behave_like 'F engine (with pdf)' end end if Distribution.has_statistics2? describe Distribution::F::Statistics2_ do before do @engine = Distribution::F::Statistics2_ end it_should_behave_like 'F engine' end end if Distribution.has_java? describe Distribution::F::Java_ do before do @engine = Distribution::F::Java_ end it_should_behave_like 'F engine' it_should_behave_like 'F engine (with pdf)' end end end distribution-0.7.3/spec/binomial_spec.rb0000644000004100000410000000675712540356202020371 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") include ExampleWithGSL describe Distribution::Binomial do shared_examples_for "binomial engine" do it "should return correct pdf" do if @engine.respond_to? :pdf [10,100,1000].each do |n| [1.quo(4),1.quo(2),3.quo(4)].each do |pr| [0, 1,n/2,n-1].each do |x| exp=Math.binomial_coefficient(n,x)*pr**x*(1-pr)**(n-x) obs=@engine.pdf(x,n,pr) obs.should be_within(1e-5).of(exp), "For pdf(#{x},#{n},#{pr}) expected #{exp}, obtained #{obs}" end end end else skip("No #{@engine}.pdf") end end it_only_with_gsl "should return correct cdf for n<=100" do if @engine.respond_to? :pdf [10,100].each do |n| [0.25,0.5,0.75].each do |pr| [1,n/2,n-1].each do |x| exp=GSL::Cdf.binomial_P(x,pr,n) obs=@engine.cdf(x,n,pr) exp.should be_within(1e-5).of(obs), "For cdf(#{x},#{n},#{pr}) expected #{exp}, obtained #{obs}" end end end else skip("No #{@engine}.cdf") end end end describe "singleton" do before do @engine=Distribution::Binomial end it_should_behave_like "binomial engine" it {@engine.should respond_to(:exact_pdf) } it { pending("No exact_p_value") @engine.should respond_to(:exact_p_value) } it "exact_cdf should return same values as cdf for n=50" do pr=rand()*0.8+0.1 n=rand(10)+10 [1,(n/2).to_i,n-1].each do |k| @engine.exact_cdf(k,n,pr).should be_within(1e-10).of(@engine.cdf(k,n,pr)) end end it "exact_pdf should not return a Float if not float is used as parameter" do @engine.exact_pdf(1,1,1).should_not be_a(Float) @engine.exact_pdf(16, 80, 1.quo(2)).should_not be_a(Float) end end describe Distribution::Binomial::Ruby_ do before do @engine=Distribution::Binomial::Ruby_ end it_should_behave_like "binomial engine" it "should return correct cdf for n>100" do [500,1000].each do |n| [0.5,0.6].each do |pr| [n/2].each do |x| cdf=@engine.exact_cdf(x,n,pr) p_value=@engine.p_value(cdf,n,pr) p_value.should eq(x), "For p_value(#{cdf},#{n},#{pr}) expected #{x}, obtained #{p_value}" end end end end it "should return correct p_value for n<=100" do pending("Can't calculate with precision x using p") [10,100].each do |n| [0.25,0.5,0.75].each do |pr| [n/2].each do |x| cdf=@engine.cdf(x,n,pr) p_value=@engine.p_value(cdf,n,pr) p_value.should eq(x), "For p_value(#{cdf},#{n},#{pr}) expected #{x}, obtained #{p_value}" end end end end end if Distribution.has_gsl? describe Distribution::Binomial::GSL_ do before do @engine=Distribution::Binomial::GSL_ end it_should_behave_like "binomial engine" end end #if Distribution.has_statistics2? # describe Distribution::Binomial::Statistics2_ do # # before do # @engine=Distribution::Binomial::Statistics2_ # end #it_should_behave_like "binomial engine" # end #end if Distribution.has_java? describe Distribution::Binomial::Java_ do before do @engine=Distribution::Binomial::Java_ end it_should_behave_like "binomial engine" end end end distribution-0.7.3/spec/logistic_spec.rb0000644000004100000410000000272012540356202020376 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") describe Distribution::Logistic do shared_examples_for "logistic engine" do it "should return correct pdf" do if @engine.respond_to? :pdf 1.upto(10) { u=rand() s=rand()+1 x=rand()*100-50 exp=Math.exp(-(x-u) / s) / (s*(1+Math.exp(-(x-u) / s)**2)) @engine.pdf(x,u,s).should eq(exp) } else pending("No #{@engine}.pdf") end end it "should return correct cdf" do if @engine.respond_to? :cdf 1.upto(100) { u=rand() s=rand()*100 x=rand()*100-50 exp=1/(1+Math.exp(-(x-u) / s)) @engine.cdf(x,u,s).should eq(exp) } else pending("No #{@engine}.cdf") end end it "should return correct p_value" do if @engine.respond_to? :p_value 1.upto(9) {|i| u=rand() s=rand()*100 x=@engine.p_value(i/10.0,u,s) @engine.cdf(x,u,s).should be_within(1e-10).of(i/10.0) } else pending("No #{@engine}.cdf") end end end describe "singleton" do before do @engine=Distribution::Logistic end it_should_behave_like "logistic engine" end describe Distribution::Logistic::Ruby_ do before do @engine=Distribution::Logistic::Ruby_ end it_should_behave_like "logistic engine" end end distribution-0.7.3/spec/poisson_spec.rb0000644000004100000410000000414412540356202020255 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") include ExampleWithGSL describe Distribution::Poisson do shared_examples_for "poisson engine" do it "should return correct pdf" do if @engine.respond_to? :pdf [0.5,1,1.5].each {|l| 1.upto(5) {|k| @engine.pdf(k,l).should be_within(1e-10).of( (l**k*Math.exp(-l)).quo(Math.factorial(k)) ) } } else pending("No #{@engine}.pdf") end end it_only_with_gsl "should return correct cdf" do if @engine.respond_to? :cdf [0.5,1,1.5,4,10].each {|l| 1.upto(5) {|k| @engine.cdf(k,l).should be_within(1e-10).of(GSL::Cdf.poisson_P(k,l)) } } else pending("No #{@engine}.cdf") end end it "should return correct p_value" do pending("No exact p_value") if @engine.respond_to? :p_value [0.1,1,5,10].each {|l| 1.upto(20) {|k| pr=@engine.cdf(k,l) @engine.p_value(pr,l).should eq(k) } } else skip("No #{@engine}.p_value") end end end describe "singleton" do before do @engine=Distribution::Poisson end it_should_behave_like "poisson engine" end describe Distribution::Poisson::Ruby_ do before do @engine=Distribution::Poisson::Ruby_ end it_should_behave_like "poisson engine" end if Distribution.has_gsl? describe Distribution::Poisson::GSL_ do before do @engine=Distribution::Poisson::GSL_ end it_should_behave_like "poisson engine" end end if Distribution.has_java? describe Distribution::Poisson::Java_ do before do @engine=Distribution::Poisson::Java_ end it_should_behave_like "poisson engine" it "should return correct cdf" do [0.5,1,1.5,4,10].each {|l| 1.upto(5) {|k| @engine.cdf(k,l).should be_within(1e-10).of(Distribution::Poisson::Ruby_.cdf(k,l)) } } end end end end distribution-0.7.3/spec/distribution_spec.rb0000644000004100000410000000107412540356202021301 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") describe Distribution do it "should respond to has_gsl?" do lambda {Distribution.has_gsl?}.should_not raise_exception if Distribution.has_gsl? expect(defined?(GSL)).to be else defined?(GSL).should be_nil end end it "should respond to has_statistics2?" do lambda {Distribution.has_statistics2?}.should_not raise_exception if Distribution.has_statistics2? defined?(Statistics2).should be else defined?(Statistics2).should be_nil end end end distribution-0.7.3/spec/hypergeometric_spec.rb0000644000004100000410000000622412540356202021612 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") include ExampleWithGSL #require 'ruby-prof' # Need to test: # * that Fixnum fast_choose returns same as choose # * that pdf and exact_pdf return the same value in Ruby_ # * that cdf in Ruby_ returns the same value as cdf in GSL_ describe Distribution::Hypergeometric do describe Distribution::Hypergeometric::GSL_ do before do @ruby=Distribution::Hypergeometric::Ruby_ @engine=Distribution::Hypergeometric::GSL_ end it_only_with_gsl "cdf should return values near to exact Ruby calculations" do #RubyProf.start if @engine.respond_to? :cdf #[2].each do |k| [0,1,2,4,8,16].each do |k| @engine.cdf(k, 80, 100, 10000).should be_within(1e-10).of(@ruby.cdf(k, 80, 100, 10000)) end #result = RubyProf.stop # Print a flat profile to text #printer = RubyProf::FlatPrinter.new(result) #printer.print(STDOUT) else pending("No #{@engine}.pdf") end end end describe Distribution::Hypergeometric::Ruby_ do before do @engine=Distribution::Hypergeometric::Ruby_ end it_only_with_gsl "pdf_fast should return same as pdf" do pending("Aprox. factorial doesn't work right") if @engine.respond_to? :pdf [0,1,2,4,8,16].each do |k| @engine.pdf_aprox(k, 80, 100, 1000).should be_within(1e-8).of(GSL::Ran::hypergeometric_pdf(k, 80, 920, 100)) end else pending("No #{@engine}.pdf") end end it_only_with_gsl "should return correct pdf" do #RubyProf.start if @engine.respond_to? :pdf #[2].each do |k| [0,1,2,4,8,16].each do |k| #puts "k:#{k}->#{@engine.pdf(k, 80, 100, 10000).to_f}" @engine.pdf(k, 80, 100, 10000).to_f.should be_within(1e-8).of(GSL::Ran::hypergeometric_pdf(k, 80, 9920, 100)) end #result = RubyProf.stop # Print a flat profile to text #printer = RubyProf::FlatPrinter.new(result) #printer.print(STDOUT) else pending("No #{@engine}.pdf") end end it "should return correct cdf" do total=rand(5)+3000 n=rand(10)+15 m=rand(10)+5 ac=0 0.upto(m) do |i| ac+=@engine.pdf(i,m,n,total) @engine.cdf(i,m,n,total).should eq(ac) end end it "should return correct p_value" do #0.upto(10) do |i| # puts "#{i}:#{@engine.pdf(i,5,7,10)}" #end total=rand(5)+3000 n=rand(10)+15 m=rand(10)+5 ac=0 0.upto(m) do |k| ac+=@engine.pdf(k,m,n,total) @engine.p_value(ac, m, n, total).should eq(k) end end end describe Distribution::Hypergeometric do before do @engine=Distribution::Hypergeometric end it {@engine.should respond_to(:exact_pdf) } it {@engine.should respond_to(:exact_cdf) } it {@engine.should respond_to(:exact_p_value) } it "exact pdf should return a Rational" do @engine.exact_pdf(1,1,1,1).should_not be_a(Float) @engine.exact_pdf(16, 80, 100, 10000).should_not be_a(Float) end end enddistribution-0.7.3/spec/bivariatenormal_spec.rb0000644000004100000410000000362612540356202021746 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") include ExampleWithGSL describe Distribution::BivariateNormal do shared_examples_for "all pdf normal capables engines" do it_only_with_gsl "should return correct pdf" do if @engine.respond_to? :pdf [0.2,0.4,0.6,0.8,0.9, 0.99,0.999,0.999999].each {|rho| @engine.pdf(0,0, rho , 1,1).should be_within(1e-8).of(GSL::Ran::bivariate_gaussian_pdf(0, 0, 1,1,rho)) } else pending("No #{@engine}.pdf") end end end shared_examples_for "all cdf normal capables engines" do it "should return correct cdf" do if @engine.respond_to? :cdf @engine.cdf(2,0.5,0.5).should be_within(1e-3).of(0.686) @engine.cdf(2,0.0,0.5).should be_within(1e-3).of(0.498) @engine.cdf(1.5,0.5,0.5).should be_within(1e-3).of(0.671) v=rand @engine.cdf(10,0,v).should be_within(1e-3).of(Distribution::Normal.cdf(0)) else pending("No #{@engine}.cdf") end end end describe "singleton" do before do @engine=Distribution::BivariateNormal end it_should_behave_like "all pdf normal capables engines" it_should_behave_like "all cdf normal capables engines" end describe Distribution::Normal::Ruby_ do before do @engine=Distribution::BivariateNormal::Ruby_ end it_should_behave_like "all pdf normal capables engines" it_should_behave_like "all cdf normal capables engines" it "Ganz method should return similar method to Hull one" do [-3,-2,-1,0,1,1.5].each {|x| @engine.cdf_hull(x,x,0.5).should be_within(0.001).of(@engine.cdf_genz(x,x,0.5)) } end end describe Distribution::Normal::GSL_ do before do @engine=Distribution::BivariateNormal::GSL_ end it_should_behave_like "all pdf normal capables engines" end end distribution-0.7.3/spec/chisquare_spec.rb0000644000004100000410000000443012540356202020545 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") include ExampleWithGSL describe Distribution::ChiSquare do shared_examples_for "Chi-square engine(with pdf)" do it_only_with_gsl "should return correct pdf" do if @engine.respond_to? :pdf 1.upto(10) do |k| v=1+rand(5) chi=GSL::Ran.chisq_pdf(v,k) @engine.pdf(v,k).should be_within(10e-10).of(chi) end else skip("No #{@engine}.pdf") end end end shared_examples_for "Chi-square engine" do it_only_with_gsl "should return correct cdf" do if @engine.respond_to? :cdf 1.upto(10) do |k| v=1+rand(5) chi=GSL::Cdf::chisq_P(v,k) @engine.cdf(v,k).should be_within(10e-10).of(chi) end else skip("No #{@engine}.cdf") end end it "should return correct p_value" do if @engine.respond_to? :p_value 1.upto(10) do |k| v=1+rand(5) pr=@engine.cdf(v,k) @engine.p_value(pr,k).should be_within(10e-4).of(v) end else skip("No #{@engine}.p_value") end end end describe "singleton" do before do @engine=Distribution::ChiSquare end it_should_behave_like "Chi-square engine" it_should_behave_like "Chi-square engine(with pdf)" end describe Distribution::ChiSquare::Ruby_ do before do @engine=Distribution::ChiSquare::Ruby_ end it_should_behave_like "Chi-square engine" it_should_behave_like "Chi-square engine(with pdf)" end if Distribution.has_gsl? describe Distribution::ChiSquare::GSL_ do before do @engine=Distribution::ChiSquare::GSL_ end it_should_behave_like "Chi-square engine" it_should_behave_like "Chi-square engine(with pdf)" end end if Distribution.has_statistics2? describe Distribution::ChiSquare::Statistics2_ do before do @engine=Distribution::ChiSquare::Statistics2_ end it_should_behave_like "Chi-square engine" end end if Distribution.has_java? describe Distribution::ChiSquare::Java_ do before do @engine=Distribution::ChiSquare::Java_ end it_should_behave_like "Chi-square engine" it_should_behave_like "Chi-square engine(with pdf)" end end end distribution-0.7.3/spec/weibull_spec.rb0000644000004100000410000000105212540356202020221 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") include ExampleWithGSL describe Distribution::Weibull do #shared_examples for "Weibull engine" do it "should return correct pdf" do Distribution::Weibull::pdf(2, 1, 1).should be_within(1e-3).of(0.13533) end it "should return correct cdf" do Distribution::Weibull::cdf(2, 1, 1).should be_within(1e-3).of(0.86466) end it "should return correct p-value" do Distribution::Weibull::p_value(0.86466, 1, 1).should be_within(1e-3).of(2.0) end #end enddistribution-0.7.3/spec/normal_spec.rb0000644000004100000410000000546312540356202020060 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb") describe Distribution::Normal do shared_examples_for "gaussian engine(with rng)" do it "should return correct rng" do samples=100 sum=0 ss=0 exp_mean=rand(10)-5 exp_sd=1 rng=@engine.rng(exp_mean,exp_sd) samples.times do v=rng.call sum+=v ss+=(v-exp_mean)**2 end mean=sum.to_f/samples sd=Math::sqrt(ss.to_f/samples) mean.should be_within(0.5).of(exp_mean) sd.should be_within(0.3).of(exp_sd) end end shared_examples_for "gaussian engine(with pdf)" do it "should return correct pdf" do if @engine.respond_to? :pdf 10.times do |i| x=(i-5)/2.0 pdf=(1.0 / Distribution::SQ2PI)*Math::exp(-(x**2/2.0)) @engine.pdf(x).should be_within(1e-10).of(pdf) end else pending("No #{@engine}.pdf") end end end shared_examples_for "gaussian engine" do it "should return correct cdf" do if @engine.respond_to? :cdf @engine.cdf(1.96).should be_within(1e-10).of(0.97500210485178) @engine.cdf(0).should be_within(1e-10).of(0.5) else pending("No #{@engine}.cdf") end end it "should return correct p_value" do if @engine.respond_to? :p_value @engine.p_value(0.5).should be_within(1e-3).of(0) 10.times do |i| x=(i-5) / 2.0 cdf=@engine.cdf(x) @engine.p_value(cdf).should be_within(1e-6).of(x) end else pending("No #{@engine}.p_value") end end end describe "singleton" do before do @engine=Distribution::Normal end it_should_behave_like "gaussian engine" it_should_behave_like "gaussian engine(with rng)" it_should_behave_like "gaussian engine(with pdf)" end describe Distribution::Normal::Ruby_ do before do @engine=Distribution::Normal::Ruby_ end it_should_behave_like "gaussian engine" it_should_behave_like "gaussian engine(with rng)" it_should_behave_like "gaussian engine(with pdf)" end if Distribution.has_gsl? describe Distribution::Normal::GSL_ do before do @engine=Distribution::Normal::GSL_ end it_should_behave_like "gaussian engine" it_should_behave_like "gaussian engine(with rng)" it_should_behave_like "gaussian engine(with pdf)" end end if Distribution.has_statistics2? describe Distribution::Normal::Statistics2_ do before do @engine=Distribution::Normal::Statistics2_ end it_should_behave_like "gaussian engine" end end if Distribution.has_java? describe Distribution::Normal::Java_ do before do @engine=Distribution::Normal::Java_ end it_should_behave_like "gaussian engine" end end end distribution-0.7.3/.travis.yml0000644000004100000410000000036512540356202016404 0ustar www-datawww-datalanguage: ruby rvm: - 1.9.3 - 2.0 - 2.1 - 2.2 # - jruby-19mode # JRuby in 1.9 mode -> Problems with bigint # - rbx-19mode script: bundle exec rake before_install: - sudo apt-get update -qq - sudo apt-get install -y libgsl0-dev distribution-0.7.3/benchmark/0000755000004100000410000000000012540356202016221 5ustar www-datawww-datadistribution-0.7.3/benchmark/power.rb0000644000004100000410000000102212540356202017675 0ustar www-datawww-datarequire 'bench_press' require 'bigdecimal' extend BenchPress name 'Float vs Rational power' author 'Claudio Bustos' date '2011-02-02' summary " On ruby, the maximum size of a float is #{Float::MAX}. With Rational, we can raise to integer numbers and surpass Float maximum. What is the speed reduction using Rational?" reps 1000 #number of repetitions int=10 rat=10.quo(1) bd=BigDecimal("10") measure "Using float pow" do int**307 end measure "Using rational" do rat**307 end measure "Using big decimal pow" do bd**307 end distribution-0.7.3/benchmark/binomial_coefficient.rb0000644000004100000410000000225712540356202022704 0ustar www-datawww-data$:.unshift(File.expand_path(File.dirname(__FILE__)+"/../lib")) require 'distribution' require 'bench_press' extend BenchPress samples=10.times.map {|i| 2**(i+1)} name 'binomial coefficient: multiplicative, factorial and optimized factorial methods' author 'Claudio Bustos' date '2011-01-27' summary "Exact calculation of Binomial Coefficient could be obtained using multiplicative, pure factorial or optimized factorial algorithm (failing + factorial). Which one is faster? Lower k is the best for all k=n/2 is the worst case. The factorial method uses the fastest Swing Prime Algorithm." reps 10 #number of repetitions x=100 n=100 k=50 measure "Multiplicative" do samples.each do |n| [5,n/2].each do |k| k=[k,n-k].min (1..k).inject(1) {|ac, i| (ac*(n-k+i).quo(i))} end end end measure "Pure Factorial" do samples.each do |n| [5,n/2].each do |k| k=[k,n-k].min Math.factorial(n).quo(Math.factorial(k) * Math.factorial(n - k)) end end end measure "Failing factorial + factorial" do samples.each do |n| [5,n/2].each do |k| k=[k,n-k].min (((n-k+1)..n).inject(1) {|ac,v| ac * v}).quo(Math.factorial(k)) end end end distribution-0.7.3/benchmark/odd.rb0000644000004100000410000000044412540356202017316 0ustar www-datawww-data require 'bench_press' extend BenchPress name 'n&1==1 vs n%2==1 to detect odd numbers' author 'Claudio Bustos' date '2011-01-28' summary " Which is faster, n%1==1 or n%2==1 " reps 10_000 #number of repetitions n=100000 measure "Using &" do n%1==1 end measure "Using %" do n%2==1 end distribution-0.7.3/benchmark/binomial_coefficient/0000755000004100000410000000000012540356202022351 5ustar www-datawww-datadistribution-0.7.3/benchmark/binomial_coefficient/binomial_coefficient.ds0000644000004100000410000000652312540356202027037 0ustar www-datawww-datao:Statsample::Dataset : @nameI"Dataset 1:ET: @fields[ I"n;FI"k;FI"mixed_factorial;FI"multiplicative;F: @vectors{ I"n;Fu:Statsample::Vector${ I" data:EF[=i i iiii7i7i7i7i7iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii'i'i'i'i'i'i'i'i'i'i'i'I"missing_values;F[I" labels;F{I" type;F: scaleI" name;FI" Vector 1;FI"k;Fu; { I" data:EF[=iiiii iii iiiii iii7iii iii7iiiiii iii7iiiiiii iii7iiiiii iii iii7iiiiii iI"missing_values;F[I" labels;F{I" type;F: scaleI" name;FI" Vector 2;FI"mixed_factorial;Fu; +{ I" data:EF[=f0.0005848407745361328f0.0008199214935302734f0.0005037784576416016f0.0008032321929931641f0.0010831356048583984f0.00049591064453125f0.0007839202880859375f0.001169443130493164f0.0018410682678222656f0.007485628128051758f0.0005395412445068359f0.0007987022399902344f0.0011131763458251953f0.0021491050720214844f0.00490260124206543f0.053803443908691406f0.0005381107330322266f0.0007991790771484375f0.0011074542999267578f0.0018732547760009766f0.004754781723022461f0.040105342864990234f0.11306977272033691f0.2937960624694824f0.0005099773406982422f0.0007784366607666016f0.0010867118835449219f0.0018830299377441406f0.0047130584716796875f0.039388179779052734f0.11153721809387207f0.2952287197113037f0.619046688079834f0.0005393028259277344f0.0008382797241210938f0.0011820793151855469f0.0020835399627685547f0.005173683166503906f0.05453968048095703f0.12773418426513672f0.2986032962799072f0.660742998123169f1.3285834789276123f4.752197980880737f0.0005733966827392578f0.0007886886596679688f0.0014104843139648438f0.0016720294952392578f0.005021572113037109f0.05472850799560547f0.1143183708190918f0.29619503021240234f0.6801633834838867f1.381115198135376f5.082608222961426f14.778673648834229I"missing_values;F[I" labels;F{I" type;F: scaleI" name;FI" Vector 3;FI"multiplicative;Fu; &{ I" data:EF[=f0.00047326087951660156f0.00119781494140625f0.00046706199645996094f0.0007853507995605469f0.0011129379272460938f0.0004639625549316406f0.0007953643798828125f0.0010991096496582031f0.0018818378448486328f0.018336057662963867f0.0005133152008056641f0.0008594989776611328f0.0011301040649414062f0.0021452903747558594f0.006609916687011719f0.029898643493652344f0.00046563148498535156f0.0008807182312011719f0.0011165142059326172f0.002197265625f0.024567842483520508f0.04833674430847168f0.09071612358093262f0.2599635124206543f0.00045490264892578125f0.0007786750793457031f0.0010988712310791016f0.002362489700317383f0.02189493179321289f0.05181241035461426f0.0947723388671875f0.2730567455291748f0.5700416564941406f0.0004899501800537109f0.0008633136749267578f0.0012662410736083984f0.017019987106323242f0.012119531631469727f0.03869891166687012f0.10341310501098633f0.29678893089294434f0.7340238094329834f1.8076701164245605f5.4109532833099365f0.00045609474182128906f0.0008265972137451172f0.0011692047119140625f0.002863168716430664f0.02634263038635254f0.03903698921203613f0.1197059154510498f0.3108999729156494f0.7560126781463623f1.8730740547180176f6.595805406570435f15.579787731170654I"missing_values;F[I" labels;F{I" type;F: scaleI" name;FI" Vector 4;F:@i0: @casesi=distribution-0.7.3/benchmark/binomial_coefficient/experiment.rb0000644000004100000410000000275512540356202025067 0ustar www-datawww-data# This test create a database to adjust the best algorithm # to use on correlation matrix $:.unshift(File.expand_path(File.dirname(__FILE__)+"/../../lib")) require 'distribution' require 'statsample' require 'benchmark' if !File.exists?("binomial_coefficient.ds") or File.mtime(__FILE__) > File.mtime("binomial_coefficient.ds") reps=100 #number of repetitions ns={ 5=> [1,3], 10=> [1,3,5], 50=> [1,3,5,10,25], 100=> [1,3,5,10,25,50], 500=> [1,3,5,10,25,50,100,250], 1000=> [1,3,5,10,25,50,100,250,500], 5000=> [1,3,5,10,25,50,100,250,500,1000,2500], 10000=>[1,3,5,10,25,50,100,250,500,1000,2500,5000] } rs=Statsample::Dataset.new(%w{n k mixed_factorial multiplicative}) ns.each do |n,ks| ks.each do |k| time_factorial= Benchmark.realtime do reps.times { (((n-k+1)..n).inject(1) {|ac,v| ac * v}).quo(Math.factorial(k)) } end time_multiplicative= Benchmark.realtime do reps.times { (1..k).inject(1) {|ac, i| (ac*(n-k+i).quo(i))} } end puts "n:#{n}, k:#{k} -> factorial:%0.3f | multiplicative: %0.3f " % [time_factorial, time_multiplicative] rs.add_case({'n'=>n,'k'=>k,'mixed_factorial'=>time_factorial, 'multiplicative'=>time_multiplicative}) end end else rs=Statsample.load("binomial_coefficient.ds") end rs.fields.each {|f| rs[f].type=:scale} rs.update_valid_data rs.save("binomial_coefficient.ds") Statsample::Excel.write(rs,"binomial_coefficient.xls")distribution-0.7.3/benchmark/binomial_coefficient/binomial_coefficient.xls0000644000004100000410000002100012540356202027222 0ustar www-datawww-dataࡱ;    Ba==@ 8"1Arial1 Arial GENERAL                    Worksheet13nkmixed_factorialmultiplicative |  Ba==@ 8"1Arial1 Arial GENERAL                    Worksheet13nkmixed_factorialmultiplicative |   d_%U}  9         *C???J?S?*@?>?*RJ?I?*Q??I?J?)S?R? * *^? ^? f @~? ƒ?  A? @?  ,J? *L?  =R? R?*a?a?ft?{? ??A?>?0J?L?%R?KR?*^?b?fys?P(???$?,9??>?@?=?I?I?Q?R?*^?Zc?fNs?k?*?(??C? !"#$%&'()*+,-./012345678  ? y?!!;?!=?""N"A?"@?#"N#xK?#JL?$"N$^S?$T?%"N*%a?%m?&"Nf&1u?& ҈?'"N'?'XУ?("N(Y?(Hy?)"N)Q?)?*"N*$?*}?+"N+A?+7?,"N',0@@,Ф@-B-B?-=?.B.I?.K?/B/W?/(S?0B*0e[?0tg?1Bf1t?1?2B2`?2?3B3C?3 ?4B4?4?5B5?5A1?6B6@ ?6?7B'7@T@7b@8B"N8P-@8(/@> Root EntryWorkbookZ2Z2 distribution-0.7.3/benchmark/factorial_method.rb0000644000004100000410000000117012540356202022051 0ustar www-datawww-data$:.unshift(File.dirname(__FILE__)+"/../lib") require 'distribution' require 'bench_press' extend BenchPress name 'aprox vs exact factorization method' author 'Claudio Bustos' date '2011-01-27' summary " Factorization requires a lot of processing, so approximation method could be required. But for greats value, bigdecimal are required and things start to get harder. * Approximation (fast_factorial): Luschny f.3 * Exact (factorial): Luschny Swing Prime " reps 10 #number of repetitions x=200 measure "Math.factorial(#{x})" do Math.factorial(x) end measure "Math.fast_factorial(#{x})" do Math.fast_factorial(x) end distribution-0.7.3/benchmark/factorial_hash.rb0000644000004100000410000000105212540356202021513 0ustar www-datawww-data$:.unshift(File.expand_path(File.dirname(__FILE__)+"/../lib")) require 'bench_press' require 'distribution' extend BenchPress name 'calculate factorial vs looking on a Hash' author 'Claudio Bustos' date '2011-01-31' summary " Is better create a lookup table for factorial or just calculate it? Distribution::MathExtension::SwingFactorial has a lookup table for factorials n<20 " reps 1000 #number of repetitions measure "Lookup" do Math.factorial(19) end measure "calculate" do Distribution::MathExtension::SwingFactorial.naive_factorial(19) end distribution-0.7.3/lib/0000755000004100000410000000000012540356202015035 5ustar www-datawww-datadistribution-0.7.3/lib/distribution.rb0000644000004100000410000001157312540356202020110 0ustar www-datawww-data# = 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_' 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 distribution-0.7.3/lib/distribution/0000755000004100000410000000000012540356202017554 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/weibull.rb0000644000004100000410000000035312540356202021545 0ustar www-datawww-datarequire 'distribution/weibull/ruby' require 'distribution/weibull/gsl' module Distribution module Weibull SHORTHAND = 'weibull' extend Distributable create_distribution_methods end enddistribution-0.7.3/lib/distribution/beta.rb0000644000004100000410000000175412540356202021023 0ustar www-datawww-datarequire 'distribution/beta/ruby' require 'distribution/beta/gsl' # no statistics2 functions for beta. require 'distribution/beta/java' module Distribution # From Wikipedia: # In probability theory and statistics, the beta distribution # is a family of continuous probability distributions defined # on the interval (0, 1) parameterized by two positive shape # parameters, typically denoted by alpha and beta. # This module calculate cdf and inverse cdf for Beta Distribution. # module Beta extend Distributable SHORTHAND = 'beta' create_distribution_methods ## # :singleton-method: pdf(x,a,b) # Returns PDF of of Beta distribution with parameters a and b ## # :singleton-method: cdf(x,a,b) # Returns the integral of Beta distribution with parameters a and b ## # :singleton-method: p_value(qn,a,b) # Return the quantile of the corresponding integral +qn+ # on a beta distribution's cdf with parameters a and b end end distribution-0.7.3/lib/distribution/t/0000755000004100000410000000000012540356202020017 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/t/gsl.rb0000644000004100000410000000121112540356202021124 0ustar www-datawww-datamodule Distribution module T module GSL_ class << self def pdf(x,k) GSL::Ran.tdist_pdf(x,k) end # Return the P-value of the corresponding integral with # k degrees of freedom # # Distribution::F.p_value(0.95,1,2) def p_value(pr,k) GSL::Cdf.tdist_Pinv(pr,k) end # F cumulative distribution function (cdf). # # Returns the integral of F-distribution # with k1 and k2 degrees of freedom # over [0, x]. # Distribution::F.cdf(20,3,2) # def cdf(x, k) GSL::Cdf.tdist_P(x.to_f, k) end end end end enddistribution-0.7.3/lib/distribution/t/ruby.rb0000644000004100000410000000540012540356202021324 0ustar www-datawww-datamodule Distribution module T module Ruby_ class << self def pdf(t,v) ((Math.gamma((v+1) / 2.0)) / (Math.sqrt(v*Math::PI)*Math.gamma(v/2.0))) * ((1+(t**2 / v.to_f))**(-(v+1) / 2.0)) end # Returns the integral of t-distribution with n degrees of freedom over (-Infty, x]. def cdf(t, n) p_t(n, t) end # t-distribution ([1]) # (-\infty, x] def p_t(df, t) if df.to_i!=df x=(t+Math.sqrt(t**2+df)) / (2*Math.sqrt(t**2+df)) return Math.regularized_beta(x,df/2.0,df/2.0) end df=df.to_i c2 = df.to_f / (df + t * t); s = Math.sqrt(1.0 - c2) s = -s if t < 0.0 p = 0.0; i = df % 2 + 2 while i <= df p += s s *= (i - 1) * c2 / i i += 2 end if df.is_a? Float or df & 1 != 0 0.5+(p*Math.sqrt(c2)+Math.atan(t/Math.sqrt(df))) / Math::PI else (1.0 + p) / 2.0 end end # inverse of t-distribution ([2]) # (-\infty, -q/2] + [q/2, \infty) def ptsub(q, n) q = q.to_f if(n == 1 && 0.001 < q && q < 0.01) eps = 1.0e-4 elsif (n == 2 && q < 0.0001) eps = 1.0e-4 elsif (n == 1 && q < 0.001) eps = 1.0e-2 else eps = 1.0e-5 end s = 10000.0 w = 0.0 loop do w += s if(s <= eps) then return w end if((qe = 2.0 - p_t(n, w)*2.0 - q) == 0.0) then return w end if(qe < 0.0) w -= s s /= 10.0 #/ end end end def pt(q, n) q = q.to_f if(q < 1.0e-5 || q > 1.0 || n < 1) $stderr.printf("Error : Illegal parameter in pt()!\n") return 0.0 end if(n <= 5) then return ptsub(q, n) end if(q <= 5.0e-3 && n <= 13) then return ptsub(q, n) end f1 = 4.0 * (f = n.to_f) f5 = (f4 = (f3 = (f2 = f * f) * f) * f) * f f2 *= 96.0 f3 *= 384.0 f4 *= 92160.0 f5 *= 368640.0 u = Normal.p_value(1.0 - q / 2.0) w0 = (u2 = u * u) * u w1 = w0 * u2 w2 = w1 * u2 w3 = w2 * u2 w4 = w3 * u2 w = (w0 + u) / f1 w += (5.0 * w1 + 16.0 * w0 + 3.0 * u) / f2 w += (3.0 * w2 + 19.0 * w1 + 17.0 * w0 - 15.0 * u) / f3 w += (79.0 * w3 + 776.0 * w2 + 1482.0 * w1 - 1920.0 * w0 - 9450.0 * u) / f4 w += (27.0 * w4 + 339.0 * w3 + 930.0 * w2 - 1782.0 * w1 - 765.0 * w0 + 17955.0 * u) / f5 u + w end # Returns the P-value of tdist(). def p_value(y,n) if y > 0.5 pt(2.0 - y*2.0, n) else - pt(y*2.0, n) end end end end end end distribution-0.7.3/lib/distribution/t/statistics2.rb0000644000004100000410000000123412540356202022620 0ustar www-datawww-datarequire 'rbconfig' module Distribution module T module Statistics2_ class << self # Return the P-value of the corresponding integral with # k degrees of freedom def p_value(pr,k) Statistics2.ptdist(k, pr) end # There are some problem on i686 with t on statistics2 if true or !RbConfig::CONFIG['arch']=~/i686/ # T cumulative distribution function (cdf). # # Returns the integral of t-distribution # with n degrees of freedom over (-Infty, x]. # def cdf(x,k) Statistics2.tdist(k,x) end end end end end enddistribution-0.7.3/lib/distribution/t/java.rb0000644000004100000410000000015212540356202021263 0ustar www-datawww-datamodule Distribution module T # TODO module Java_ class << self end end end enddistribution-0.7.3/lib/distribution/binomial.rb0000644000004100000410000000130112540356202021666 0ustar www-datawww-datarequire 'distribution/binomial/ruby' require 'distribution/binomial/gsl' require 'distribution/binomial/java' module Distribution # Calculate statisticals for Binomial Distribution. module Binomial SHORTHAND = 'bino' extend Distributable create_distribution_methods ## # :singleton-method: pdf(x,k) # Returns the integral of T distribution # with +k+ degrees of freedom over [0, +x+] ## # :singleton-method: p_value(qn, k) # Return the P-value of the corresponding integral +qn+ with # +k+ degrees of freedom ## # :singleton-method: cdf(x,k) # Returns the integral of T distribution # with +k+ degrees of freedom over [0, +x+] end end distribution-0.7.3/lib/distribution/bivariatenormal/0000755000004100000410000000000012540356202022733 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/bivariatenormal/gsl.rb0000644000004100000410000000033312540356202024044 0ustar www-datawww-datamodule Distribution module BivariateNormal module GSL_ class < 0.95 # * Hull:: Port from a C++ code # * Jantaravareerat:: Iterative (slow and buggy) # module BivariateNormal module Ruby_ class << self SIDE=0.1 # :nodoc: LIMIT=5 # :nodoc: # Return the partial derivative of cdf over x, with y and rho constant # Reference: # * Tallis, 1962, p.346, cited by Olsson, 1979 def partial_derivative_cdf_x(x,y,rho) Distribution::Normal.pdf(x) * Distribution::Normal.cdf((y-rho*x).quo( Math::sqrt( 1 - rho**2 ))) end alias :pd_cdf_x :partial_derivative_cdf_x # Probability density function for a given x, y and rho value. # # Source: http://en.wikipedia.org/wiki/Multivariate_normal_distribution def pdf(x,y, rho, s1=1.0, s2=1.0) 1.quo(2 * Math::PI * s1 * s2 * Math::sqrt( 1 - rho**2 )) * (Math::exp(-(1.quo(2*(1-rho**2))) * ((x**2.quo(s1)) + (y**2.quo(s2)) - (2*rho*x*y).quo(s1*s2)))) end def f(x,y,aprime,bprime,rho) r=aprime*(2*x-aprime)+bprime*(2*y-bprime)+2*rho*(x-aprime)*(y-bprime) Math::exp(r) end # CDF for a given x, y and rho value. # Uses Genz algorithm (cdf_genz method). # def cdf(a,b,rho) cdf_genz(a,b,rho) end def sgn(x) if(x>=0) 1 else -1 end end # Normal cumulative distribution function (cdf) for a given x, y and rho. # Based on Hull (1993, cited by Arne, 2003) # # References: # * Arne, B.(2003). Financial Numerical Recipes in C ++. Available on http://finance.bi.no/~bernt/gcc_prog/recipes/recipes/node23.html def cdf_hull(a,b,rho) #puts "a:#{a} - b:#{b} - rho:#{rho}" if (a<=0 and b<=0 and rho<=0) # puts "ruta 1" aprime=a.quo(Math::sqrt(2.0*(1.0-rho**2))) bprime=b.quo(Math::sqrt(2.0*(1.0-rho**2))) aa=[0.3253030, 0.4211071, 0.1334425, 0.006374323] bb=[0.1337764, 0.6243247, 1.3425378, 2.2626645] sum=0 4.times do |i| 4.times do |j| sum+=aa[i]*aa[j] * f(bb[i], bb[j], aprime, bprime,rho) end end sum=sum*(Math::sqrt(1.0-rho**2).quo(Math::PI)) return sum elsif(a*b*rho<=0.0) #puts "ruta 2" if(a<=0 and b>=0 and rho>=0) return Distribution::Normal.cdf(a) - cdf(a,-b,-rho) elsif (a>=0.0 and b<=0.0 and rho>=0) return Distribution::Normal.cdf(b) - cdf(-a,b,-rho) elsif (a>=0.0 and b>=0.0 and rho<=0) return Distribution::Normal.cdf(a) + Distribution::Normal.cdf(b) - 1.0 + cdf(-a,-b,rho) end elsif (a*b*rho>=0.0) #puts "ruta 3" denum=Math::sqrt(a**2 - 2*rho*a*b + b**2) rho1=((rho*a-b)*sgn(a)).quo(denum) rho2=((rho*b-a)*sgn(b)).quo(denum) delta=(1.0-sgn(a)*sgn(b)).quo(4) #puts "#{rho1} - #{rho2}" return cdf(a, 0.0, rho1) + cdf(b, 0.0, rho2) - delta end raise "Should'nt be here! #{a} - #{b} #{rho}" end # CDF. Iterative method by Jantaravareerat (n/d) # # Reference: # * Jantaravareerat, M. & Thomopoulos, N. (n/d). Tables for standard bivariate normal distribution def cdf_jantaravareerat(x,y,rho,s1=1,s2=1) # Special cases return 1 if x>LIMIT and y>LIMIT return 0 if x<-LIMIT or y<-LIMIT return Distribution::Normal.cdf(y) if x>LIMIT return Distribution::Normal.cdf(x) if y>LIMIT #puts "x:#{x} - y:#{y}" x=-LIMIT if x<-LIMIT x=LIMIT if x>LIMIT y=-LIMIT if y<-LIMIT y=LIMIT if y>LIMIT x_squares=((LIMIT+x) / SIDE).to_i y_squares=((LIMIT+y) / SIDE).to_i sum=0 x_squares.times do |i| y_squares.times do |j| z1=-LIMIT+(i+1)*SIDE z2=-LIMIT+(j+1)*SIDE #puts " #{z1}-#{z2}" 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) sum+= (SIDE**2)*h # area end end sum end # Normal cumulative distribution function (cdf) for a given x, y and rho. # Ported from Fortran code by Alan Genz # # Original documentation # DOUBLE PRECISION FUNCTION BVND( DH, DK, R ) # A function for computing bivariate normal probabilities. # # Alan Genz # Department of Mathematics # Washington State University # Pullman, WA 99164-3113 # Email : alangenz_AT_wsu.edu # # This function is based on the method described by # Drezner, Z and G.O. Wesolowsky, (1989), # On the computation of the bivariate normal integral, # Journal of Statist. Comput. Simul. 35, pp. 101-107, # with major modifications for double precision, and for |R| close to 1. # # Original location: # * http://www.math.wsu.edu/faculty/genz/software/fort77/tvpack.f def cdf_genz(x,y,rho) dh=-x dk=-y r=rho twopi = 6.283185307179586 w=11.times.collect {[nil]*4}; x=11.times.collect {[nil]*4} data=[ 0.1713244923791705E+00, -0.9324695142031522E+00, 0.3607615730481384E+00, -0.6612093864662647E+00, 0.4679139345726904E+00, -0.2386191860831970E+00] (1..3).each {|i| w[i][1]=data[(i-1)*2] x[i][1]=data[(i-1)*2+1] } data=[ 0.4717533638651177E-01,-0.9815606342467191E+00, 0.1069393259953183E+00,-0.9041172563704750E+00, 0.1600783285433464E+00,-0.7699026741943050E+00, 0.2031674267230659E+00,-0.5873179542866171E+00, 0.2334925365383547E+00,-0.3678314989981802E+00, 0.2491470458134029E+00,-0.1252334085114692E+00] (1..6).each {|i| w[i][2]=data[(i-1)*2] x[i][2]=data[(i-1)*2+1] } data=[ 0.1761400713915212E-01,-0.9931285991850949E+00, 0.4060142980038694E-01,-0.9639719272779138E+00, 0.6267204833410906E-01,-0.9122344282513259E+00, 0.8327674157670475E-01,-0.8391169718222188E+00, 0.1019301198172404E+00,-0.7463319064601508E+00, 0.1181945319615184E+00,-0.6360536807265150E+00, 0.1316886384491766E+00,-0.5108670019508271E+00, 0.1420961093183821E+00,-0.3737060887154196E+00, 0.1491729864726037E+00,-0.2277858511416451E+00, 0.1527533871307259E+00,-0.7652652113349733E-01] (1..10).each {|i| w[i][3]=data[(i-1)*2] x[i][3]=data[(i-1)*2+1] } if ( r.abs < 0.3 ) ng = 1 lg = 3 elsif ( r.abs < 0.75 ) ng = 2 lg = 6 else ng = 3 lg = 10 end h = dh k = dk hk = h*k bvn = 0 if ( r.abs < 0.925 ) if ( r.abs > 0 ) hs = ( h*h + k*k ).quo(2) asr = Math::asin(r) (1..lg).each do |i| [-1,1].each do |is| sn = Math::sin(asr*(is* x[i][ng]+1).quo(2) ) bvn = bvn + w[i][ng] * Math::exp( ( sn*hk-hs ).quo( 1-sn*sn ) ) end # do end # do bvn = bvn*asr.quo( 2*twopi ) end # if bvn = bvn + Distribution::Normal.cdf(-h) * Distribution::Normal.cdf(-k) else # r.abs if ( r < 0 ) k = -k hk = -hk end if ( r.abs < 1 ) as = ( 1 - r )*( 1 + r ) a = Math::sqrt(as) bs = ( h - k )**2 c = ( 4 - hk ).quo(8) d = ( 12 - hk ).quo(16) asr = -( bs.quo(as) + hk ).quo(2) if ( asr > -100 ) bvn = a*Math::exp(asr) * ( 1 - c*( bs - as )*( 1 - d*bs.quo(5) ).quo(3) + c*d*as*as.quo(5) ) end if ( -hk < 100 ) b = Math::sqrt(bs) bvn = bvn - Math::exp( -hk.quo(2) ) * Math::sqrt(twopi)*Distribution::Normal.cdf(-b.quo(a))*b * ( 1 - c*bs*( 1 - d*bs.quo(5) ).quo(3) ) end a = a.quo(2) (1..lg).each do |i| [-1,1].each do |is| xs = (a*( is*x[i][ng] + 1 ) )**2 rs = Math::sqrt( 1 - xs ) asr = -( bs/xs + hk ).quo(2) if ( asr > -100 ) bvn = bvn + a*w[i][ng] * Math::exp( asr ) * ( Math::exp( -hk*( 1 - rs ).quo(2*( 1 + rs ) ) ) .quo(rs) - ( 1 + c*xs*( 1 + d*xs ) ) ) end end end bvn = -bvn/twopi end if ( r > 0 ) bvn = bvn + Distribution::Normal.cdf(-[h,k].max) else bvn = -bvn if ( k > h ) bvn = bvn + Distribution::Normal.cdf(k) - Distribution::Normal.cdf(h) end end end bvn end private :f, :sgn end end end end distribution-0.7.3/lib/distribution/bivariatenormal/statistics2.rb0000644000004100000410000000000012540356202025522 0ustar www-datawww-datadistribution-0.7.3/lib/distribution/bivariatenormal/java.rb0000644000004100000410000000017012540356202024177 0ustar www-datawww-datamodule Distribution module BivariateNormal # TODO module Java_ class << self end end end enddistribution-0.7.3/lib/distribution/poisson.rb0000644000004100000410000000222212540356202021571 0ustar www-datawww-datarequire 'distribution/poisson/ruby' require 'distribution/poisson/gsl' require 'distribution/poisson/java' module Distribution # From Wikipedia # In probability theory and statistics, the Poisson distribution is # a discrete probability distribution that expresses the probability of # a number of events occurring in a fixed period of time if these # events occur with a known average rate and independently of the time # since the last event. module Poisson SHORTHAND='pois' extend Distributable create_distribution_methods ## # :singleton-method: pdf(k , l) # PDF for Poisson distribution, # [+k+] is the number of occurrences of an event # [+l+] is a positive real number, equal to the expected number of occurrences that occur during the given interval. ## # :singleton-method: cdf(k , l) # CDF for Poisson distribution # [+k+] is the number of occurrences of an event # [+l+] is a positive real number, equal to the expected number of occurrences that occur during the given interval. # TODO: Not implemented yet # :singleton-method: p_value(pr , l) end end distribution-0.7.3/lib/distribution/math_extension.rb0000644000004100000410000002437712540356202023143 0ustar www-datawww-datarequire 'bigdecimal' require 'bigdecimal/math' require 'prime' # The next few requires eventually probably need to go in their own gem. They're all functions and constants used by # GSL-adapted pure Ruby math functions. require 'distribution/math_extension/chebyshev_series' require 'distribution/math_extension/erfc' require 'distribution/math_extension/exponential_integral' require 'distribution/math_extension/gammastar' require 'distribution/math_extension/gsl_utilities' require 'distribution/math_extension/incomplete_gamma' require 'distribution/math_extension/incomplete_beta' require 'distribution/math_extension/log_utilities' module Distribution # Useful additions to Math module MathExtension # Factorization based on Prime Swing algorithm, by Luschny (the king of factorial numbers analysis :P ) # == Reference # * The Homepage of Factorial Algorithms. (C) Peter Luschny, 2000-2010 # == URL: http://www.luschny.de/math/factorial/csharp/FactorialPrimeSwing.cs.html class SwingFactorial SmallOddSwing = [1, 1, 1, 3, 3, 15, 5, 35, 35, 315, 63, 693, 231, 3003, 429, 6435, 6435, 109_395, 12_155, 230_945, 46_189, 969_969, 88_179, 2_028_117, 676_039, 16_900_975, 1_300_075, 35_102_025, 5_014_575, 145_422_675, 9_694_845, 300_540_195, 300_540_195] SmallFactorial = [1, 1, 2, 6, 24, 120, 720, 5040, 40_320, 362_880, 3_628_800, 39_916_800, 479_001_600, 6_227_020_800, 87_178_291_200, 1_307_674_368_000, 20_922_789_888_000, 355_687_428_096_000, 6_402_373_705_728_000, 121_645_100_408_832_000, 2_432_902_008_176_640_000] attr_reader :result def bitcount(n) bc = n - ((n >> 1) & 0x55555555) bc = (bc & 0x33333333) + ((bc >> 2) & 0x33333333) bc = (bc + (bc >> 4)) & 0x0f0f0f0f bc += bc >> 8 bc += bc >> 16 bc &= 0x3f bc end def initialize(n) if n < 20 @result = SmallFactorial[n] # naive_factorial(n) else @prime_list = [] exp2 = n - bitcount(n) @result = recfactorial(n) << exp2 end end def recfactorial(n) return 1 if n < 2 (recfactorial(n / 2)**2) * swing(n) end def swing(n) return SmallOddSwing[n] if n < 33 sqrtN = Math.sqrt(n).floor count = 0 Prime.each(n / 3) do |prime| next if prime < 3 if (prime <= sqrtN) q = n _p = 1 while (q = (q / prime).truncate) > 0 if q.odd? _p *= prime end end if _p > 1 @prime_list[count] = _p count += 1 end else if (n / prime).truncate.odd? @prime_list[count] = prime count += 1 end end end prod = get_primorial((n / 2).truncate + 1, n) prod * @prime_list[0, count].inject(1) { |ac, v| ac * v } end def get_primorial(low, up) prod = 1 Prime.each(up) do |prime| next if prime < low prod *= prime end prod end def naive_factorial(n) @result = (self.class).naive_factorial(n) end def self.naive_factorial(n) (2..n).inject(1) { |f, nn| f * nn } end end # Module to calculate approximated factorial # Based (again) on Luschny formula, with 16 digits of precision # == Reference # * http://www.luschny.de/math/factorial/approx/SimpleCases.html module ApproxFactorial class << self def stieltjes_ln_factorial(z) a0 = 1.quo(12); a1 = 1.quo(30); a2 = 53.quo(210); a3 = 195.quo(371) a4 = 22_999.quo(22_737); a5 = 29_944_523.quo(19_733_142) a6 = 109_535_241_009.quo(48_264_275_462) zz = z + 1 (1.quo(2)) * Math.log(2 * Math::PI) + (zz - 1.quo(2)) * Math.log(zz) - zz + a0.quo(zz + a1.quo(zz + a2.quo(zz + a3.quo(zz + a4.quo(zz + a5.quo(zz + a6.quo(zz))))))) end def stieltjes_ln_factorial_big(z) a0 = 1 / 12.0; a1 = 1 / 30.0; a2 = 53 / 210.0; a3 = 195 / 371.0 a4 = 22_999 / 22_737.0; a5 = 29_944_523 / 19_733_142.0 a6 = 109_535_241_009 / 48_264_275_462.0 zz = z + 1 BigDecimal('0.5') * BigMath.log(BigDecimal('2') * BigMath::PI(20), 20) + BigDecimal((zz - 0.5).to_s) * BigMath.log(BigDecimal(zz.to_s), 20) - BigDecimal(zz.to_s) + BigDecimal(( a0 / (zz + a1 / (zz + a2 / (zz + a3 / (zz + a4 / (zz + a5 / (zz + a6 / zz)))))) ).to_s) end # Valid upto 11 digits def stieltjes_factorial(x) y = x _p = 1 while y < 8 _p *= y; y += 1 end lr = stieltjes_ln_factorial(y) r = Math.exp(lr) if r.infinite? r = BigMath.exp(BigDecimal(lr.to_s), 20) r = (r * x) / (_p * y) if x < 8 r = r.to_i else r = (r * x) / (_p * y) if x < 8 end r end end end # Exact factorial. # Use lookup on a Hash table on n<20 # and Prime Swing algorithm for higher values. def factorial(n) SwingFactorial.new(n).result end # Approximate factorial, up to 16 digits # Based of Luschy algorithm def fast_factorial(n) ApproxFactorial.stieltjes_factorial(n) end # Beta function. # Source: # * http://mathworld.wolfram.com/BetaFunction.html def beta(x, y) (gamma(x) * gamma(y)).quo(gamma(x + y)) end # Get pure-Ruby logbeta def logbeta(x, y) Beta.log_beta(x, y).first end # Log beta function conforming to style of lgamma (returns sign in second array index) def lbeta(x, y) Beta.log_beta(x, y) end # I_x(a,b): Regularized incomplete beta function # Fast version. For a exact calculation, based on factorial # use exact_regularized_beta_function def regularized_beta(x, a, b) return 1 if x == 1 IncompleteBeta.evaluate(a, b, x) end # I_x(a,b): Regularized incomplete beta function # TODO: Find a faster version. # Source: # * http://dlmf.nist.gov/8.17 def exact_regularized_beta(x, a, b) return 1 if x == 1 m = a.to_i n = (b + a - 1).to_i (m..n).inject(0) do|sum, j| sum + (binomial_coefficient(n, j) * x**j * (1 - x)**(n - j)) end end # Incomplete beta function: B(x;a,b) # +a+ and +b+ are parameters and +x+ is # integration upper limit. def incomplete_beta(x, a, b) IncompleteBeta.evaluate(a, b, x) * beta(a, b) # Math::IncompleteBeta.axpy(1.0, 0.0, a,b,x) end # Rising factorial def rising_factorial(x, n) factorial(x + n - 1).quo(factorial(x - 1)) end # Ln of gamma def loggamma(x) Math.lgamma(x).first end def incomplete_gamma(a, x = 0, with_error = false) IncompleteGamma.p(a, x, with_error) end alias_method :gammp, :incomplete_gamma def gammq(a, x, with_error = false) IncompleteGamma.q(a, x, with_error) end def unnormalized_incomplete_gamma(a, x, with_error = false) IncompleteGamma.unnormalized(a, x, with_error) end # Not the same as erfc. This is the GSL version, which may have slightly different results. def erfc_e(x, with_error = false) Erfc.evaluate(x, with_error) end # Sequences without repetition. n^k' # Also called 'failing factorial' def permutations(n, k) return 1 if k == 0 return n if k == 1 return factorial(n) if k == n (((n - k + 1)..n).inject(1) { |ac, v| ac * v }) # factorial(x).quo(factorial(x-n)) end # Binomial coeffients, or: # ( n ) # ( k ) # # Gives the number of *different* k size subsets of a set size n # # Uses: # # (n) n^k' (n)..(n-k+1) # ( ) = ---- = ------------ # (k) k! k! # def binomial_coefficient(n, k) return 1 if k == 0 || k == n k = [k, n - k].min permutations(n, k).quo(factorial(k)) # The factorial way is # factorial(n).quo(factorial(k)*(factorial(n-k))) # The multiplicative way is # (1..k).inject(1) {|ac, i| (ac*(n-k+i).quo(i))} end # Binomial coefficient using multiplicative algorithm # On benchmarks, is faster that raising factorial method # when k is little. Use only when you're sure of that. def binomial_coefficient_multiplicative(n, k) return 1 if k == 0 || k == n k = [k, n - k].min (1..k).inject(1) { |ac, i| (ac * (n - k + i).quo(i)) } end # Approximate binomial coefficient, using gamma function. # The fastest method, until we fall on BigDecimal! def binomial_coefficient_gamma(n, k) return 1 if k == 0 || k == n k = [k, n - k].min # First, we try direct gamma calculation for max precission val = gamma(n + 1).quo(gamma(k + 1) * gamma(n - k + 1)) # Ups. Outside float point range. We try with logs if val.nan? # puts "nan" lg = loggamma(n + 1) - (loggamma(k + 1) + loggamma(n - k + 1)) val = Math.exp(lg) # Crash again! We require BigDecimals if val.infinite? # puts "infinite" val = BigMath.exp(BigDecimal(lg.to_s), 16) end end val end alias_method :combinations, :binomial_coefficient end end module Math include Distribution::MathExtension module_function :factorial, :beta, :loggamma, :erfc_e, :unnormalized_incomplete_gamma, :incomplete_gamma, :gammp, :gammq, :binomial_coefficient, :binomial_coefficient_gamma, :exact_regularized_beta, :incomplete_beta, :regularized_beta, :permutations, :rising_factorial, :fast_factorial, :combinations, :logbeta, :lbeta end # Necessary on Ruby 1.9 module CMath # :nodoc: include Distribution::MathExtension module_function :factorial, :beta, :loggamma, :unnormalized_incomplete_gamma, :incomplete_gamma, :gammp, :gammq, :erfc_e, :binomial_coefficient, :binomial_coefficient_gamma, :incomplete_beta, :exact_regularized_beta, :regularized_beta, :permutations, :rising_factorial, :fast_factorial, :combinations, :logbeta, :lbeta end distribution-0.7.3/lib/distribution/gamma.rb0000644000004100000410000000175512540356202021173 0ustar www-datawww-datarequire 'distribution/gamma/ruby' require 'distribution/gamma/gsl' # no statistics2 functions for gamma. require 'distribution/gamma/java' module Distribution # From Wikipedia: # The gamma distribution is a two-parameter family of # continuous probability distributions. It has a scale parameter a # and a shape parameter b. # # Calculate pdf, cdf and inverse cdf for Gamma Distribution. # module Gamma extend Distributable SHORTHAND='gamma' create_distribution_methods ## # :singleton-method: pdf(x,a,b) # Returns PDF of of Gamma distribution with +a+ as scale # parameter and +b+ as shape parameter ## # :singleton-method: cdf(x,a,b) # Returns the integral of Gamma distribution with +a+ as scale # parameter and +b+ as shape parameter ## # :singleton-method: p_value(qn,a,b) # Return the upper limit for the integral of a # gamma distribution which returns +qn+ # with scale +a+ and shape +b+ end end distribution-0.7.3/lib/distribution/lognormal/0000755000004100000410000000000012540356202021546 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/lognormal/gsl.rb0000644000004100000410000000060512540356202022661 0ustar www-datawww-datamodule Distribution module LogNormal module GSL_ class << self def pdf(x,u,s) GSL::Ran::lognormal_pdf(x.to_f, u.to_f, s.to_f) end def p_value(pr,u,s) GSL::Cdf::lognormal_Pinv(pr.to_f, u.to_f, s.to_f) end def cdf(x,u,s) GSL::Cdf::lognormal_P(x.to_f, u.to_f, s.to_f) end end end end end distribution-0.7.3/lib/distribution/lognormal/ruby.rb0000644000004100000410000000063612540356202023061 0ustar www-datawww-datamodule Distribution module LogNormal module Ruby_ class << self def pdf(x,u,s) raise "x should be > 0 " if x < 0 (1.0/(x*s*Math.sqrt(2*Math::PI)))*Math.exp(-((Math.log(x)-u)**2 / (2*s**2))) end #def p_value(pr,u,s) #end def cdf(x,u,s) Distribution::Normal.cdf((Math.log(x)-u) / s) end end end end end distribution-0.7.3/lib/distribution/version.rb0000644000004100000410000000005412540356202021565 0ustar www-datawww-datamodule Distribution VERSION = '0.7.3' end distribution-0.7.3/lib/distribution/bivariatenormal.rb0000644000004100000410000000142212540356202023257 0ustar www-datawww-datarequire 'distribution/bivariatenormal/ruby' require 'distribution/bivariatenormal/gsl' require 'distribution/bivariatenormal/java' module Distribution # Calculate pdf and cdf for bivariate normal distribution. # # Pdf if easy to calculate, but CDF is not trivial. Several papers # describe methods to calculate the integral. module BivariateNormal SHORTHAND='bnor' extend Distributable create_distribution_methods ## # :singleton-method: pdf(k,n,prob) # Probability density function for exactly +k+ successes in +n+ trials # with success probability +prob+ # ## # :singleton-method: cdf(k,n,prob) # Cumulative density function for +k+ or less successes in +n+ trials # with success probability +prob+ end end distribution-0.7.3/lib/distribution/binomial/0000755000004100000410000000000012540356202021346 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/binomial/gsl.rb0000644000004100000410000000041512540356202022460 0ustar www-datawww-datamodule Distribution module Binomial module GSL_ class << self def pdf(k, n, prob) GSL::Ran.binomial_pdf(k, prob, n) end def cdf(k, n, prob) GSL::Cdf.binomial_P(k, prob, n) end end end end end distribution-0.7.3/lib/distribution/binomial/ruby.rb0000644000004100000410000000154412540356202022660 0ustar www-datawww-datamodule Distribution module Binomial module Ruby_ class << self def pdf(k, n, pr) fail 'k>n' if k > n Math.binomial_coefficient(n, k) * (pr**k) * (1 - pr)**(n - k) end # TODO: Use exact_regularized_beta for # small values and regularized_beta for bigger ones. def cdf(k, n, pr) # (0..x.floor).inject(0) {|ac,i| ac+pdf(i,n,pr)} Math.regularized_beta(1 - pr, n - k, k + 1) end def exact_cdf(k, n, pr) out = (0..k).inject(0) { |ac, i| ac + pdf(i, n, pr) } out = 1 if out > 1.0 out end def p_value(prob, n, pr) ac = 0 (0..n).each do |i| ac += pdf(i, n, pr) return i if prob <= ac end end alias_method :exact_pdf, :pdf end end end end distribution-0.7.3/lib/distribution/binomial/java.rb0000644000004100000410000000016212540356202022613 0ustar www-datawww-datamodule Distribution module Binomial # TODO module Java_ class << self end end end end distribution-0.7.3/lib/distribution/exponential/0000755000004100000410000000000012540356202022102 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/exponential/gsl.rb0000644000004100000410000000062112540356202023213 0ustar www-datawww-datamodule Distribution module Exponential module GSL_ class << self def pdf(x,l) return 0 if x<0 GSL::Ran.exponential_pdf(x,1/l.to_f) end def cdf(x,l) return 0 if x<0 GSL::Cdf.exponential_P(x,1/l.to_f) end def p_value(pr,l) GSL::Cdf.exponential_Pinv(pr,1/l.to_f) end end end end enddistribution-0.7.3/lib/distribution/exponential/ruby.rb0000644000004100000410000000073012540356202023410 0ustar www-datawww-datamodule Distribution module Exponential module Ruby_ class << self def rng(l, opts = {}) rng = opts[:random] || Random lambda {p_value(rng.rand,l)} end def pdf(x,l) return 0 if x<0 l*Math.exp(-l*x) end def cdf(x,l) return 0 if x<0 1-Math.exp(-l*x) end def p_value(pr,l) (-Math.log(1-pr)).quo(l) end end end end end distribution-0.7.3/lib/distribution/normal/0000755000004100000410000000000012540356202021044 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/normal/gsl.rb0000644000004100000410000000102712540356202022156 0ustar www-datawww-datamodule Distribution module Normal module GSL_ class << self def rng(mean=0,sigma=1,seed=nil) seed||=rand(10e8) rng=GSL::Rng.alloc(GSL::Rng::MT19937,seed) lambda { mean+rng.gaussian(sigma)} end def cdf(x) # :nodoc: GSL::Cdf::ugaussian_P(x) end def pdf(x) # :nodoc: GSL::Ran::gaussian_pdf(x) end def p_value(qn) GSL::Cdf::ugaussian_Pinv(qn) end def gsl end end end end end distribution-0.7.3/lib/distribution/normal/ruby.rb0000644000004100000410000000523512540356202022357 0ustar www-datawww-datamodule Distribution module Normal module Ruby_ class << self # random number within a gaussian distribution X ~ N(0,1) def rngu rng(0,1,nil) end # Return a proc which return a random number within a # gaussian distribution X ~ N(+mean+,+sigma+^2) # +seed+ feed the # == Reference: # * http://www.taygeta.com/random/gaussian.html def rng(mean=0,sigma=1,seed=nil) returned,y1,y2=0,0,0 lambda { if returned==0 begin x1 = 2.0 * rand - 1.0 x2 = 2.0 * rand - 1.0 w = x1 * x1 + x2 * x2 end while ( w >= 1.0 ) w = Math::sqrt( (-2.0 * Math::log( w ) ) / w ) y1 = x1 * w y2 = x2 * w returned=1 y1*sigma + mean else returned=0 y2 * sigma + mean end } end # Return the inverse CDF or P-value of the corresponding integral def p_value(qn) b = [1.570796288, 0.03706987906, -0.8364353589e-3, -0.2250947176e-3, 0.6841218299e-5, 0.5824238515e-5, -0.104527497e-5, 0.8360937017e-7, -0.3231081277e-8, 0.3657763036e-10, 0.6936233982e-12] if(qn < 0.0 || 1.0 < qn) $stderr.printf("Error : qn <= 0 or qn >= 1 in pnorm()!\n") return 0.0; end qn == 0.5 and return 0.0 w1 = qn qn > 0.5 and w1 = 1.0 - w1 w3 = -Math.log(4.0 * w1 * (1.0 - w1)) w1 = b[0] 1.upto 10 do |i| w1 += b[i] * w3**i; end qn > 0.5 and return Math.sqrt(w1 * w3) -Math.sqrt(w1 * w3) end # Normal cumulative distribution function (cdf). # # Returns the integral of normal distribution # over (-Infty, z]. # def cdf(z) return 0.0 if z < -12 return 1.0 if z > 12 return 0.5 if z == 0.0 if z > 0.0 e = true else e = false z = -z end z = z.to_f z2 = z * z t = q = z * Math.exp(-0.5 * z2) / SQ2PI 3.step(199, 2) do |i| prev = q t *= z2 / i q += t if q <= prev return(e ? 0.5 + q : 0.5 - q) end end e ? 1.0 : 0.0 end # Normal probability density function (pdf) # With x=0 and sigma=1 def pdf(x) (1.0 / SQ2PI)*Math::exp(-(x**2/2.0)) end end end end end distribution-0.7.3/lib/distribution/normal/statistics2.rb0000644000004100000410000000037012540356202023645 0ustar www-datawww-datamodule Distribution module Normal module Statistics2_ class << self def cdf(x) Statistics2.normaldist(x) end def p_value(pr) Statistics2.pnormaldist(pr) end end end end end distribution-0.7.3/lib/distribution/normal/java.rb0000644000004100000410000000163712540356202022321 0ustar www-datawww-datamodule Distribution module Normal # TODO module Java_ class << self #== # Generate random variables from the provided distribution def rng(mean=0,sigma=1,seed=nil) dist = NormalDistributionImpl.new(mean, sigma) lambda { dist.sample } end #== # Get the inverse cumulative density function (p-value) for qn def p_value(qn) dist = NormalDistributionImpl.new dist.inverseCumulativeProbability(qn) end #== # Return the cumulative density function at x def cdf(x) dist = NormalDistributionImpl.new dist.cumulativeProbability(x) end #== # Return the probability density function at x def pdf(x) dist = NormalDistributionImpl.new dist.density(x) end end end end enddistribution-0.7.3/lib/distribution/gamma/0000755000004100000410000000000012540356202020636 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/gamma/gsl.rb0000644000004100000410000000121612540356202021750 0ustar www-datawww-datamodule Distribution module Gamma module GSL_ class << self def pdf(x,a,b) GSL::Ran::gamma_pdf(x.to_f, a.to_f, b.to_f) end # Return the P-value of the corresponding integral with # k degrees of freedom def p_value(pr,a,b) GSL::Cdf::gamma_Pinv(pr.to_f, a.to_f, b.to_f) end # Chi-square cumulative distribution function (cdf). # # Returns the integral of Chi-squared distribution # with k degrees of freedom over [0, x] # def cdf(x,a,b) GSL::Cdf::gamma_P(x.to_f, a.to_f, b.to_f) end end end end end distribution-0.7.3/lib/distribution/gamma/ruby.rb0000644000004100000410000000277612540356202022160 0ustar www-datawww-data# Added by John O. Woods, SciRuby project. module Distribution module Gamma module Ruby_ class << self include Math # Gamma distribution probability density function # # If you're looking at Wikipedia's Gamma distribution page, the arguments for this pdf function correspond # as follows: # # * +x+: same # * +a+: alpha or k # + +b+: theta or 1/beta # # This is confusing! But we're trying to most closely mirror the GSL function for the gamma distribution # (see references). # # Adapted the function itself from GSL-1.9 in rng/gamma.c: gsl_ran_gamma_pdf # # ==References # * http://www.gnu.org/software/gsl/manual/html_node/The-Gamma-Distribution.html # * http://en.wikipedia.org/wiki/Gamma_distribution def pdf(x,a,b) return 0 if x < 0 if x == 0 return 1.quo(b) if a == 1 return 0 elsif a == 1 Math.exp(-x.quo(b)).quo(b) else Math.exp((a-1)*Math.log(x.quo(b)) - x.quo(b) - Math.lgamma(a).first).quo(b) end end # Gamma cumulative distribution function def cdf(x,a,b) return 0.0 if x <= 0.0 y = x.quo(b) return (1-Math::IncompleteGamma.q(a, y)) if y > a return (Math::IncompleteGamma.p(a, y)) end #def p_value(pr,a,b) # cdf(1.0-pr,a,b) #end end end end end distribution-0.7.3/lib/distribution/gamma/java.rb0000644000004100000410000000015612540356202022106 0ustar www-datawww-datamodule Distribution module Gamma # TODO module Java_ class << self end end end enddistribution-0.7.3/lib/distribution/t.rb0000644000004100000410000000151212540356202020343 0ustar www-datawww-datarequire 'distribution/t/ruby' require 'distribution/t/gsl' # Removed statistics2 support for t, because # can't calculate correctly cdf for rational d.f # require 'distribution/t/statistics2' require 'distribution/t/java' module Distribution # Calculate statisticals for T Distribution. module T SHORTHAND='tdist' extend Distributable create_distribution_methods ## # :singleton-method: pdf(x,k) # Returns the integral of T distribution # with +k+ degrees of freedom over [0, +x+] ## # :singleton-method: p_value(qn, k) # Return the P-value of the corresponding integral +qn+ with # +k+ degrees of freedom ## # :singleton-method: cdf(x,k) # Returns the integral of T distribution # with +k+ degrees of freedom over [0, +x+] end end distribution-0.7.3/lib/distribution/hypergeometric/0000755000004100000410000000000012540356202022602 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/hypergeometric/gsl.rb0000644000004100000410000000062312540356202023715 0ustar www-datawww-datamodule Distribution module Hypergeometric module GSL_ class << self def pdf(k, m, n, total) # :nodoc: GSL::Ran::hypergeometric_pdf(k, m, total-m, n) end # The GSL::Cdf function for hypergeometric # def cdf(k, m, n, total) # :nodoc: GSL::Cdf::hypergeometric_P(k, m, total-m, n) end end end end end distribution-0.7.3/lib/distribution/hypergeometric/ruby.rb0000644000004100000410000000362512540356202024116 0ustar www-datawww-data# Added by John O. Woods, SciRuby project. # Optimized by Claudio Bustos module Distribution module Hypergeometric module Ruby_ class << self def bc(n,k) Math.binomial_coefficient(n,k) end # Hypergeometric probability density function # # Probability p(+k+, +m+, +n+, +total+) of drawing sets of size +m+ and +n+ with an intersection of size +k+ # from a total pool of size +total+, without replacement. # # ==References # * http://www.gnu.org/software/gsl/manual/html_node/The-Hypergeometric-Distribution.html # * http://en.wikipedia.org/wiki/Hypergeometric_distribution def pdf(k, m, n, total) min_m_n=mmin_m_n or k=pr end end # Cumulative distribution function. # The probability of obtain, from a sample of # size +n+, +k+ or less elements # in a population size +total+ with +m+ interesting elements. # # Slow, but secure def cdf(k, m, n, total) raise(ArgumentError, "k>m") if k>m raise(ArgumentError, "k>n") if k>n # Store the den den=bc(total,n) (0..k).collect { |ki| pdf_with_den(ki,m,n,total,den) }.inject { |sum,v| sum+v} end alias :exact_pdf :pdf alias :exact_p_value :p_value alias :exact_cdf :cdf end end end enddistribution-0.7.3/lib/distribution/hypergeometric/java.rb0000644000004100000410000000016712540356202024054 0ustar www-datawww-datamodule Distribution module Hypergeometric # TODO module Java_ class << self end end end enddistribution-0.7.3/lib/distribution/f/0000755000004100000410000000000012540356202020001 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/f/gsl.rb0000644000004100000410000000125612540356202021117 0ustar www-datawww-datamodule Distribution module F module GSL_ class << self def pdf(x,k1,k2) GSL::Ran.fdist_pdf(x.to_f,k1,k2) end # Return the P-value of the corresponding integral with # k degrees of freedom # # Distribution::F.p_value(0.95,1,2) def p_value(pr,k1,k2) GSL::Cdf.fdist_Pinv(pr.to_f,k1,k2) end # F cumulative distribution function (cdf). # # Returns the integral of F-distribution # with k1 and k2 degrees of freedom # over [0, x]. # Distribution::F.cdf(20,3,2) # def cdf(x, k1, k2) GSL::Cdf.fdist_P(x.to_f.to_f,k1,k2) end end end end end distribution-0.7.3/lib/distribution/f/ruby.rb0000644000004100000410000000717612540356202021322 0ustar www-datawww-datamodule Distribution module F # Continuous random number distributions are defined by a probability density function, p(x), such that the probability of x occurring in the infinitesimal range x to x+dx is p dx. # The cumulative distribution function for the lower tail P(x) is defined by the integral, # P(x) = \int_{-\infty}^{x} dx' p(x') # and gives the probability of a variate taking a value less than x. # The cumulative distribution function for the upper tail Q(x) is defined by the integral, # Q(x) = \int_{x}^{+\infty} dx' p(x') # and gives the probability of a variate taking a value greater than x. # The upper and lower cumulative distribution functions are related by P(x) + Q(x) = 1 and satisfy 0 <= P(x) <= 1, 0 <= Q(x). module Ruby_ extend Distribution::MathExtension # functions needed: # - pdf # - cdf (lower cumulative function, P(x)) # - Q(x), upper cumulative function # - mean # - mode # - kurtosis # - skewness # - entropy # - "fit" (maximum likelihood?) # - expected value (given a function) # - lower-tail quantile -> P # - upper tail quantile -> Q class << self # F Distribution (Ruby) -- Probability Density Function def pdf(x, n, m) x = x.to_f numerator = ((n * x)**n * (m**m)) / (n * x + m)**(n + m) denominator = x * Math.beta(n / 2.0, m / 2.0) Math.sqrt(numerator) / denominator end # Cumulative Distribution Function. def cdf(x, n, m) x = x.to_f xx = (x * n).to_f / (x * n + m).to_f regularized_beta(xx, n / 2.0, m / 2.0) end # Upper cumulative function. # # If cdf(x, n, m) = p, then q(x, n, m) = 1 - p def q(x, n, m) 1.0 - cdf(x, n, m) end # Return the F value corresponding to `probability` with degrees of # freedom `n` and `m`. # # If x = quantile(p, n, m), then cdf(x, n, m) = p. # # Taken from: # https://github.com/JuliaLang/Rmath-julia/blob/master/src/qf.c def p_value(probability, n, m) return Float::NAN if n <= 0.0 || m <= 0.0 if n == Float::INFINITY || n == -Float::INFINITY || m == Float::INFINITY || m == -Float::INFINITY return 1.0 end if n <= m && m > 4e5 return Distribution::ChiSquare.p_value(probability, n) / n.to_f elsif n > 4e5 # thus n > m return m.to_f / Distribution::ChiSquare.p_value(1.0 - probability, m) else # O problema está aqui. tmp = Distribution::Beta.p_value(1.0 - probability, m.to_f / 2, n.to_f / 2) value = (1.0 / tmp - 1.0) * (m.to_f / n.to_f) return value.nan? ? Float::NAN : value end end # Complementary quantile function. # # def cquantile(prob, n, m) # quantile(1.0 - probability, n, m) # end # Return the corresponding F value for a p-value `y` with `n` and `m` # degrees of freedom. # # @param y [Float] Value corresponding to the desired p-value. Between 0 and 1. # @param n [Float] Degree of freedom of the first random variable. # @param m [Float] Degree of freedom of the second random variable. # @return [Float] Value of the F distribution that gives a p-value of `y`. def mean end def mode end def skewness end def kurtosis end def entropy end end end end end distribution-0.7.3/lib/distribution/f/statistics2.rb0000644000004100000410000000123112540356202022577 0ustar www-datawww-datamodule Distribution module F module Statistics2_ class << self # Return the P-value of the corresponding integral with # k degrees of freedom # # Distribution::F.p_value(0.95,1,2) # Statistics2 have some problem with extreme values def p_value(pr,k1,k2) Statistics2.pfdist(k1,k2, pr) end # F cumulative distribution function (cdf). # # Returns the integral of F-distribution # with k1 and k2 degrees of freedom # over [0, x]. # Distribution::F.cdf(20,3,2) # def cdf(x, k1, k2) Statistics2.fdist(k1, k2,x) end end end end end distribution-0.7.3/lib/distribution/f/java.rb0000644000004100000410000000015212540356202021245 0ustar www-datawww-datamodule Distribution module F # TODO module Java_ class << self end end end enddistribution-0.7.3/lib/distribution/hypergeometric.rb0000644000004100000410000000241712540356202023133 0ustar www-datawww-datarequire 'distribution/hypergeometric/ruby' require 'distribution/hypergeometric/gsl' require 'distribution/hypergeometric/java' module Distribution # From Wikipedia: # In probability theory and statistics, the hypergeometric distribution is a discrete probability distribution that # describes the number of successes in a sequence of n draws from a finite population without replacement, just as # the binomial distribution describes the number of successes for draws with replacement. module Hypergeometric SHORTHAND='hypg' extend Distributable create_distribution_methods ## # :singleton-method: pdf(k,m,n,total) # This function computes the probability p(k) of obtaining k # from a hypergeometric distribution with parameters # m, n t. # * m: number of elements with desired attribute on population # * n: sample size # * t: population size ## # :singleton-method: cdf(k,m,n,total) # These functions compute the cumulative distribution function P(k) # for the hypergeometric distribution with parameters m, n and t. # * m: number of elements with desired attribute on population # * n: sample size # * t: population size ## # :singleton-method: p_value(k,m,n,total) end end distribution-0.7.3/lib/distribution/normal.rb0000644000004100000410000000174212540356202021375 0ustar www-datawww-datarequire 'distribution/normal/ruby' require 'distribution/normal/gsl' require 'distribution/normal/statistics2' require 'distribution/normal/java' module Distribution # From Wikipedia: # Continuous probability distribution that is often used as # a first approximation to describe real-valued random variables # that tend to cluster around a single mean value. # The graph of the associated probability density function is “bell”-shaped module Normal SHORTHAND='norm' extend Distributable create_distribution_methods ## # :singleton-method: pdf(x) # Returns PDF of Normal distribution ## # :singleton-method: p_value(qn) # Return the P-value of the corresponding integral +qn+ ## # :singleton-method: cdf(x) # Returns the integral of Normal distribution over [0, +x+] ## # :singleton-method: rng # Returns a lambda which returns a random number from # X ~ N(0,1) end end distribution-0.7.3/lib/distribution/chisquare.rb0000644000004100000410000000142512540356202022067 0ustar www-datawww-datarequire 'distribution/chisquare/ruby' require 'distribution/chisquare/gsl' require 'distribution/chisquare/statistics2' require 'distribution/chisquare/java' module Distribution # Calculate cdf and inverse cdf for Chi Square Distribution. # module ChiSquare extend Distributable SHORTHAND='chisq' create_distribution_methods ## # :singleton-method: pdf(x) # Returns PDF of of Chi-squared distribution # with +k+ degrees of freedom ## # :singleton-method: cdf(x,k) # Returns the integral of Chi-squared distribution # with +k+ degrees of freedom over [0, +x+] ## # :singleton-method: p_value(qn, k) # Return the P-value of the corresponding integral +qn+ with # +k+ degrees of freedom end end distribution-0.7.3/lib/distribution/exponential.rb0000644000004100000410000000235712540356202022436 0ustar www-datawww-datarequire 'distribution/exponential/ruby' require 'distribution/exponential/gsl' #require 'distribution/exponential/java' module Distribution # From Wikipedia: # In probability theory and statistics, the exponential distribution # (a.k.a. negative exponential distribution) is a family of continuous # probability distributions. It describes the time between events in a # Poisson process, i.e. a process in which events occur continuously # and independently at a constant average rate. # # Parameter +l+ is the rate parameter, the number of occurrences/unit time. module Exponential SHORTHAND='expo' extend Distributable create_distribution_methods ## # :singleton-method: rng(l) # Returns a lambda, which generates exponential variates # with +l+ as rate parameter ## # :singleton-method: pdf(x,l) # PDF of exponential distribution, with parameters +x+ and +l+. # +l+ is rate parameter ## # :singleton-method: cdf(x,l) # CDF of exponential distribution, with parameters +x+ and +l+. # +l+ is rate parameter ## # :singleton-method: p_value(pr,l) # Inverse CDF of exponential distribution, with parameters +pr+ and +l+. # +l+ is rate parameter end end distribution-0.7.3/lib/distribution/chisquare/0000755000004100000410000000000012540356202021540 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/chisquare/gsl.rb0000644000004100000410000000120312540356202022646 0ustar www-datawww-datamodule Distribution module ChiSquare module GSL_ class << self def rng(k,seed=nil) end def pdf(x,k) GSL::Ran::chisq_pdf(x.to_f,k.to_i) end # Return the P-value of the corresponding integral with # k degrees of freedom def p_value(pr,k) GSL::Cdf::chisq_Pinv(pr.to_f,k.to_i) end # Chi-square cumulative distribution function (cdf). # # Returns the integral of Chi-squared distribution # with k degrees of freedom over [0, x] # def cdf(x, k) GSL::Cdf::chisq_P(x.to_f,k.to_i) end end end end end distribution-0.7.3/lib/distribution/chisquare/ruby.rb0000644000004100000410000000412312540356202023046 0ustar www-datawww-datamodule Distribution module ChiSquare module Ruby_ class << self include Math def pdf(x,n) if n == 1 1.0/Math.sqrt(2 * Math::PI * x) * Math::E**(-x/2.0) elsif n == 2 0.5 * Math::E**(-x/2.0) else n = n.to_f n2 = n/2 x = x.to_f 1.0 / 2**n2 / gamma(n2) * x**(n2 - 1.0) * Math.exp(-x/2.0) end end # CDF Inverse over [x, \infty) # Pr([x, \infty)) = y -> x def pchi2(n, y) if n == 1 w = Distribution::Normal.p_value(1 - y/2) # = p1.0-Distribution::Normal.cdf(y/2) w * w elsif n == 2 # v = (1.0 / y - 1.0) / 33.0 # newton_a(y, v) {|x| [q_chi2(n, x), -chi2dens(n, x)] } -2.0 * Math.log(y) else eps = 1.0e-5 v = 0.0 s = 10.0 loop do v += s if s <= eps then break end if (qe = q_chi2(n, v) - y) == 0.0 then break end if qe < 0.0 v -= s s /= 10.0 end end v end end def p_value(pr,k) pchi2(k, 1.0-pr) end def cdf(x,k) 1.0-q_chi2(k,x) end # chi-square distribution ([1]) # Integral over [x, \infty) def q_chi2(df, chi2) chi2 = chi2.to_f if (df & 1) != 0 chi = Math.sqrt(chi2) if (df == 1) then return 2 * (1.0-Distribution::Normal.cdf(chi)); end s = t = chi * Math.exp(-0.5 * chi2) / SQ2PI k = 3 while k < df t *= chi2 / k; s += t; k += 2 end 2 * (1.0-(Distribution::Normal.cdf(chi)) + s) else s = t = Math.exp(-0.5 * chi2) k = 2 while k < df t *= chi2 / k; s += t; k += 2 end s end end end end end end distribution-0.7.3/lib/distribution/chisquare/statistics2.rb0000644000004100000410000000101312540356202024334 0ustar www-datawww-datamodule Distribution module ChiSquare module Statistics2_ class << self # Return the P-value of the corresponding integral with # k degrees of freedom def p_value(pr,k) Statistics2.pchi2X_(k.to_i, pr) end # Chi-square cumulative distribution function (cdf). # # Returns the integral of Chi-squared distribution # with k degrees of freedom over [0, x] # def cdf(x, k) Statistics2.chi2dist(k.to_i,x) end end end end end distribution-0.7.3/lib/distribution/chisquare/java.rb0000644000004100000410000000016212540356202023005 0ustar www-datawww-datamodule Distribution module ChiSquare # TODO module Java_ class << self end end end enddistribution-0.7.3/lib/distribution/logistic.rb0000644000004100000410000000240512540356202021717 0ustar www-datawww-datarequire 'distribution/logistic/ruby' #require 'distribution/logistic/gsl' #require 'distribution/logistic/java' module Distribution # From Wikipedia: # In probability theory and statistics, the logistic distribution is a continuous probability distribution. Its cumulative distribution function is the logistic function, which appears in logistic regression and feedforward neural networks. It resembles the normal distribution in shape but has heavier tails (higher kurtosis). module Logistic SHORTHAND='logis' extend Distributable create_distribution_methods ## # :singleton-method: rng(u,s) # Returns a proc, which returns a different logistic # variate each time is called # * u: mean # * s: variance related parameter ## # :singleton-method: pdf(x , u,s) # Returns the pdf for logistic distribution (f(x,u,s)) # * u: mean # * s: variance related parameter ## # :singleton-method: cdf(x,u,s) # Returns the cdf for logistic distribution (F(x,u,s)) # * u: mean # * s: variance related parameter ## # :singleton-method: p_value(pr , u,s) # Returns the inverse cdf for logistic distribution # (F^-1(pr,u,s)) # * u: mean # * s: variance related parameter end end distribution-0.7.3/lib/distribution/math_extension/0000755000004100000410000000000012540356202022601 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/math_extension/gammastar.rb0000644000004100000410000000453212540356202025106 0ustar www-datawww-data# Added by John O. Woods, SciRuby project. # Derived from GSL-1.9 source files in the specfunc/ dir. module Distribution module MathExtension # Derived from GSL-1.9. module Gammastar C0 = 1.quo(12) C1 = -1.quo(360) C2 = 1.quo(1260) C3 = -1.quo(1680) C4 = 1.quo(1188) C5 = -691.quo(360360) C6 = 1.quo(156) C7 = -3617.quo(122400) class << self def series x, with_error = false # Use the Stirling series for the correction to Log(Gamma(x)), # which is better behaved and easier to compute than the # regular Stirling series for Gamma(x). y = 1.quo(x*x) ser = C0 + y*(C1 + y*(C2 + y*(C3 + y*(C4 + y*(C5 + y*(C6 + y*C7)))))) result = Math.exp(ser/x) with_error ? [result, 2.0 * Float::EPSILON * result * [1, ser/x].max] : result end def evaluate x, with_error = false raise(ArgumentError, "x must be positive") if x <= 0 if x < 0.5 STDERR.puts("Warning: Don't know error on lg_x, error for this function will be incorrect") if with_error lg = Math.lgamma(x).first lg_err = Float::EPSILON # Guess lx = Math.log(x) c = 0.5 * (LN2 + LNPI) lnr_val = lg - (x-0.5)*lx + x - c lnr_err = lg_err + 2.0*Float::EPSILON * ((x+0.5)*lx.abs + c) with_error ? exp_err(lnr_val, lnr_err) : Math.exp(lnr_val) elsif x < 2.0 t = 4.0/3.0*(x-0.5) - 1.0 ChebyshevSeries.evaluate(:gstar_a, t, with_error) elsif x < 10.0 t = 0.25*(x-2.0) - 1.0 c = ChebyshevSeries.evaluate(:gstar_b, t, with_error) c, c_err = c if with_error result = c / (x*x) + 1.0 + 1.0/(12.0*x) with_error ? [result, c_err / (x*x) + 2.0*Float::EPSILON*result.abs] : result elsif x < 1.0/Math::ROOT4_FLOAT_EPSILON series x, with_error elsif x < 1.0 / Float::EPSILON # Stirling xi = 1.0 / x result = 1.0 + xi/12.0*(1.0 + xi/24.0*(1.0 - xi*(139.0/180.0 + 571.0/8640.0*xi))) result_err = 2.0 * Float::EPSILON * result.abs with_error ? [result,result_err] : result else with_error ? [1.0,1.0/x] : 1.0 end end end end end end distribution-0.7.3/lib/distribution/math_extension/log_utilities.rb0000644000004100000410000000524612540356202026011 0ustar www-datawww-data# Added by John O. Woods, SciRuby project. # Derived from GSL-1.9 source files in the specfunc/ dir. module Distribution module MathExtension # Various logarithm shortcuts, adapted from GSL-1.9. module Log C1 = -1.quo(2) C2 = 1.quo(3) C3 = -1.quo(4) C4 = 1.quo(5) C5 = -1.quo(6) C6 = 1.quo(7) C7 = -1.quo(8) C8 = 1.quo(9) C9 = -1.quo(10) class << self # gsl_log1p from GSL-1.9 sys/log1p.c # log for very small x def log1p x # in C, this is volatile double y. # Not sure how to reproduce that in Ruby. y = 1+x Math.log(y) - ((y-1)-x).quo(y) # cancel errors with IEEE arithmetic end # \log(1+x) for x > -1 # gsl_sf_log_1plusx_e def log_1plusx(x, with_error = false) raise(ArgumentError, "Range error: x must be > -1") if x <= -1 if x.abs < Math::ROOT6_FLOAT_EPSILON result = x * (1.0 + x * (C1 + x*(C2 + x*(C3 + x*(C4 + x*begin C5 + x*(C6 + x*(C7 + x*(C8 + x*C9))) # formerly t = this end))))) return with_error ? [result, Float::EPSILON * result.abs] : result elsif x.abs < 0.5 c = ChebyshevSeries.evaluate(:lopx, (8*x + 1).quo(2*x+4), with_error) return with_error ? [x * c.first, x * c.last] : x*c else result = Math.log(1+x) return with_error ? [result, Float::EPSILON*result.abs] : result end end # \log(1+x)-x for x > -1 # gsl_sf_log_1plusx_mx_e def log_1plusx_minusx x, with_error = false raise(ArgumentError, "Range error: x must be > -1") if x <= -1 if x.abs < Math::ROOT5_FLOAT_EPSILON result = x*x * (C1 + x*(C2 + x*(C3 + x*(C4 + x*begin C5 + x*(C6 + x*(C7 + x*(C8 + x*C9))) # formerly t = this end)))) return with_error ? [result, Float::EPSILON * result.abs] : result elsif x.abs < 0.5 c = ChebyshevSeries.evaluate(:lopxmx, (8*x + 1).quo(2*x+4), with_error) return with_error ? [x*x * c.first, x*x * c.last] : x*x*c else lterm = Math.log(1.0+x) error = Float::EPSILON * (lterm.abs + x.abs) if with_error result = lterm - x return with_error ? [result, error] : result end end protected # Abstracted from other log helper functions in GSL-1.9. def x_less_than_root_epsilon x, with_error result = square_x ? x*x : x with_error ? [result, Float::EPSILON * result.abs] : result end end end end end distribution-0.7.3/lib/distribution/math_extension/chebyshev_series.rb0000644000004100000410000004723712540356202026475 0ustar www-datawww-data# Added by John O. Woods, SciRuby project. # Derived from GSL-1.9 source files in the specfunc/ and cheb/ dirs. module Distribution module MathExtension # Adapted from GSL-1.9. class ChebyshevSeries DATA = {:lopx => [ 2.16647910664395270521272590407, -0.28565398551049742084877469679, 0.01517767255690553732382488171, -0.00200215904941415466274422081, 0.00019211375164056698287947962, -0.00002553258886105542567601400, 2.9004512660400621301999384544e-06, -3.8873813517057343800270917900e-07, 4.7743678729400456026672697926e-08, -6.4501969776090319441714445454e-09, 8.2751976628812389601561347296e-10, -1.1260499376492049411710290413e-10, 1.4844576692270934446023686322e-11, -2.0328515972462118942821556033e-12, 2.7291231220549214896095654769e-13, -3.7581977830387938294437434651e-14, 5.1107345870861673561462339876e-15, -7.0722150011433276578323272272e-16, 9.7089758328248469219003866867e-17, -1.3492637457521938883731579510e-17, 1.8657327910677296608121390705e-18 ], :lopxmx => [ -1.12100231323744103373737274541, 0.19553462773379386241549597019, -0.01467470453808083971825344956, 0.00166678250474365477643629067, -0.00018543356147700369785746902, 0.00002280154021771635036301071, -2.8031253116633521699214134172e-06, 3.5936568872522162983669541401e-07, -4.6241857041062060284381167925e-08, 6.0822637459403991012451054971e-09, -8.0339824424815790302621320732e-10, 1.0751718277499375044851551587e-10, -1.4445310914224613448759230882e-11, 1.9573912180610336168921438426e-12, -2.6614436796793061741564104510e-13, 3.6402634315269586532158344584e-14, -4.9937495922755006545809120531e-15, 6.8802890218846809524646902703e-16, -9.5034129794804273611403251480e-17, 1.3170135013050997157326965813e-17], :gstar_a => [ 2.16786447866463034423060819465, -0.05533249018745584258035832802, 0.01800392431460719960888319748, -0.00580919269468937714480019814, 0.00186523689488400339978881560, -0.00059746524113955531852595159, 0.00019125169907783353925426722, -0.00006124996546944685735909697, 0.00001963889633130842586440945, -6.3067741254637180272515795142e-06, 2.0288698405861392526872789863e-06, -6.5384896660838465981983750582e-07, 2.1108698058908865476480734911e-07, -6.8260714912274941677892994580e-08, 2.2108560875880560555583978510e-08, -7.1710331930255456643627187187e-09, 2.3290892983985406754602564745e-09, -7.5740371598505586754890405359e-10, 2.4658267222594334398525312084e-10, -8.0362243171659883803428749516e-11, 2.6215616826341594653521346229e-11, -8.5596155025948750540420068109e-12, 2.7970831499487963614315315444e-12, -9.1471771211886202805502562414e-13, 2.9934720198063397094916415927e-13, -9.8026575909753445931073620469e-14, 3.2116773667767153777571410671e-14, -1.0518035333878147029650507254e-14, 3.4144405720185253938994854173e-15, -1.0115153943081187052322643819e-15 ], :gstar_b => [ 0.0057502277273114339831606096782, 0.0004496689534965685038254147807, -0.0001672763153188717308905047405, 0.0000615137014913154794776670946, -0.0000223726551711525016380862195, 8.0507405356647954540694800545e-06, -2.8671077107583395569766746448e-06, 1.0106727053742747568362254106e-06, -3.5265558477595061262310873482e-07, 1.2179216046419401193247254591e-07, -4.1619640180795366971160162267e-08, 1.4066283500795206892487241294e-08, -4.6982570380537099016106141654e-09, 1.5491248664620612686423108936e-09, -5.0340936319394885789686867772e-10, 1.6084448673736032249959475006e-10, -5.0349733196835456497619787559e-11, 1.5357154939762136997591808461e-11, -4.5233809655775649997667176224e-12, 1.2664429179254447281068538964e-12, -3.2648287937449326771785041692e-13, 7.1528272726086133795579071407e-14, -9.4831735252566034505739531258e-15, -2.3124001991413207293120906691e-15, 2.8406613277170391482590129474e-15, -1.7245370321618816421281770927e-15, 8.6507923128671112154695006592e-16, -3.9506563665427555895391869919e-16, 1.6779342132074761078792361165e-16, -6.0483153034414765129837716260e-17 ], :e11 => [ -16.11346165557149402600, 7.79407277874268027690, -1.95540581886314195070, 0.37337293866277945612, -0.05692503191092901938, 0.00721107776966009185, -0.00078104901449841593, 0.00007388093356262168, -0.00000620286187580820, 0.00000046816002303176, -0.00000003209288853329, 0.00000000201519974874, -0.00000000011673686816, 0.00000000000627627066, -0.00000000000031481541, 0.00000000000001479904, -0.00000000000000065457, 0.00000000000000002733, -0.00000000000000000108], :e12 => [ -0.03739021479220279500, 0.04272398606220957700, -0.13031820798497005440, 0.01441912402469889073, -0.00134617078051068022, 0.00010731029253063780, -0.00000742999951611943, 0.00000045377325690753, -0.00000002476417211390, 0.00000000122076581374, -0.00000000005485141480, 0.00000000000226362142, -0.00000000000008635897, 0.00000000000000306291, -0.00000000000000010148, 0.00000000000000000315 ], :ae11 => [ 0.121503239716065790, -0.065088778513550150, 0.004897651357459670, -0.000649237843027216, 0.000093840434587471, 0.000000420236380882, -0.000008113374735904, 0.000002804247688663, 0.000000056487164441, -0.000000344809174450, 0.000000058209273578, 0.000000038711426349, -0.000000012453235014, -0.000000005118504888, 0.000000002148771527, 0.000000000868459898, -0.000000000343650105, -0.000000000179796603, 0.000000000047442060, 0.000000000040423282, -0.000000000003543928, -0.000000000008853444, -0.000000000000960151, 0.000000000001692921, 0.000000000000607990, -0.000000000000224338, -0.000000000000200327, -0.000000000000006246, 0.000000000000045571, 0.000000000000016383, -0.000000000000005561, -0.000000000000006074, -0.000000000000000862, 0.000000000000001223, 0.000000000000000716, -0.000000000000000024, -0.000000000000000201, -0.000000000000000082, 0.000000000000000017], :ae12 => [ 0.582417495134726740, -0.158348850905782750, -0.006764275590323141, 0.005125843950185725, 0.000435232492169391, -0.000143613366305483, -0.000041801320556301, -0.000002713395758640, 0.000001151381913647, 0.000000420650022012, 0.000000066581901391, 0.000000000662143777, -0.000000002844104870, -0.000000000940724197, -0.000000000177476602, -0.000000000015830222, 0.000000000002905732, 0.000000000001769356, 0.000000000000492735, 0.000000000000093709, 0.000000000000010707, -0.000000000000000537, -0.000000000000000716, -0.000000000000000244, -0.000000000000000058], :ae13 => [ -0.605773246640603460, -0.112535243483660900, 0.013432266247902779, -0.001926845187381145, 0.000309118337720603, -0.000053564132129618, 0.000009827812880247, -0.000001885368984916, 0.000000374943193568, -0.000000076823455870, 0.000000016143270567, -0.000000003466802211, 0.000000000758754209, -0.000000000168864333, 0.000000000038145706, -0.000000000008733026, 0.000000000002023672, -0.000000000000474132, 0.000000000000112211, -0.000000000000026804, 0.000000000000006457, -0.000000000000001568, 0.000000000000000383, -0.000000000000000094, 0.000000000000000023], :ae14 => [ -0.18929180007530170, -0.08648117855259871, 0.00722410154374659, -0.00080975594575573, 0.00010999134432661, -0.00001717332998937, 0.00000298562751447, -0.00000056596491457, 0.00000011526808397, -0.00000002495030440, 0.00000000569232420, -0.00000000135995766, 0.00000000033846628, -0.00000000008737853, 0.00000000002331588, -0.00000000000641148, 0.00000000000181224, -0.00000000000052538, 0.00000000000015592, -0.00000000000004729, 0.00000000000001463, -0.00000000000000461, 0.00000000000000148, -0.00000000000000048, 0.00000000000000016, -0.00000000000000005], :erfc_xlt1 => [ 1.06073416421769980345174155056, -0.42582445804381043569204735291, 0.04955262679620434040357683080, 0.00449293488768382749558001242, -0.00129194104658496953494224761, -0.00001836389292149396270416979, 0.00002211114704099526291538556, -5.23337485234257134673693179020e-7, -2.78184788833537885382530989578e-7, 1.41158092748813114560316684249e-8, 2.72571296330561699984539141865e-9, -2.06343904872070629406401492476e-10, -2.14273991996785367924201401812e-11, 2.22990255539358204580285098119e-12, 1.36250074650698280575807934155e-13, -1.95144010922293091898995913038e-14, -6.85627169231704599442806370690e-16, 1.44506492869699938239521607493e-16, 2.45935306460536488037576200030e-18, -9.29599561220523396007359328540e-19 ], :erfc_x15 => [ 0.44045832024338111077637466616, -0.143958836762168335790826895326, 0.044786499817939267247056666937, -0.013343124200271211203618353102, 0.003824682739750469767692372556, -0.001058699227195126547306482530, 0.000283859419210073742736310108, -0.000073906170662206760483959432, 0.000018725312521489179015872934, -4.62530981164919445131297264430e-6, 1.11558657244432857487884006422e-6, -2.63098662650834130067808832725e-7, 6.07462122724551777372119408710e-8, -1.37460865539865444777251011793e-8, 3.05157051905475145520096717210e-9, -6.65174789720310713757307724790e-10, 1.42483346273207784489792999706e-10, -3.00141127395323902092018744545e-11, 6.22171792645348091472914001250e-12, -1.26994639225668496876152836555e-12, 2.55385883033257575402681845385e-13, -5.06258237507038698392265499770e-14, 9.89705409478327321641264227110e-15, -1.90685978789192181051961024995e-15, 3.50826648032737849245113757340e-16 ], :erfc_x510 => [ 1.11684990123545698684297865808, 0.003736240359381998520654927536, -0.000916623948045470238763619870, 0.000199094325044940833965078819, -0.000040276384918650072591781859, 7.76515264697061049477127605790e-6, -1.44464794206689070402099225301e-6, 2.61311930343463958393485241947e-7, -4.61833026634844152345304095560e-8, 8.00253111512943601598732144340e-9, -1.36291114862793031395712122089e-9, 2.28570483090160869607683087722e-10, -3.78022521563251805044056974560e-11, 6.17253683874528285729910462130e-12, -9.96019290955316888445830597430e-13, 1.58953143706980770269506726000e-13, -2.51045971047162509999527428316e-14, 3.92607828989125810013581287560e-15, -6.07970619384160374392535453420e-16, 9.12600607264794717315507477670e-17 ], :sin => [ -0.3295190160663511504173, 0.0025374284671667991990, 0.0006261928782647355874, -4.6495547521854042157541e-06, -5.6917531549379706526677e-07, 3.7283335140973803627866e-09, 3.0267376484747473727186e-10, -1.7400875016436622322022e-12, -1.0554678305790849834462e-13, 5.3701981409132410797062e-16, 2.5984137983099020336115e-17, -1.1821555255364833468288e-19], } PARAMS = { :lopx => [20, -1, 1, 10], :lopxmx => [19, -1, 1, 9], :gstar_a => [29, -1, 1, 17], :gstar_b => [29, -1, 1, 18], :e11 => [18, -1, 1, 13], :e12 => [15, -1, 1, 10], :ae11 => [38, -1, 1, 20], :ae12 => [24, -1, 1, 15], :ae13 => [24, -1, 1, 15], :ae14 => [25, -1, 1, 13], :erfc_xlt1 => [19, -1, 1, 12], :erfc_x15 => [24, -1, 1, 16], :erfc_x510 => [19, -1, 1, 12], :sin => [11, -1, 1, 11] } def initialize(coefficients, expansion_order, lower_interval_point, upper_interval_point, single_precision_order) @c = coefficients.is_a?(Symbol) ? DATA[coefficients] : coefficients @order = expansion_order @lower_interval_point = lower_interval_point @upper_interval_point = upper_interval_point @single_precision_order = single_precision_order end #double * c; /* coefficients */ #int order; /* order of expansion */ #double a; /* lower interval point */ #double b; /* upper interval point */ #int order_sp; /* effective single precision order */ attr_reader :lower_interval_point, :upper_interval_point, :single_precision_order, :order, :c def a; @lower_interval_point; end def b; @upper_interval_point; end def order_sp; @single_precision_order; end def coefficients(idx); @c[idx]; end class << self # cheb_eval_e in specfunc/cheb_eval.c (gsl-1.9) def evaluate series, x, with_error = false cs = Math.const_get "#{series.to_s.upcase}_CS" raise(ArgumentError, "Unrecognized series #{series.to_s}") if cs.nil? d = 0.0 dd = 0.0 y = (2*x - cs.a - cs.b).quo(cs.b - cs.a) y2 = 2*y e = 0.0 cs.order.downto(1) do |j| temp = d d = y2*d - dd + cs.c[j] e += (y2*temp).abs + dd.abs + cs.c[j].abs dd = temp end begin temp = d d = y*d - dd + 0.5 * cs.c[0] e += (y*temp).abs + dd.abs + 0.5*cs.c[0].abs end with_error ? [d, Float::EPSILON*e + (cs.c[cs.order])] : d end end end ChebyshevSeries::DATA.keys.each do |series| Math.const_set "#{series.to_s.upcase}_CS", ChebyshevSeries.new(series, *(ChebyshevSeries::PARAMS[series])) end end enddistribution-0.7.3/lib/distribution/math_extension/gsl_utilities.rb0000644000004100000410000000250412540356202026007 0ustar www-datawww-data# Added by John O. Woods, SciRuby project. # Derived from GSL-1.9 source files, mostly in the specfunc/ dir. module Distribution module MathExtension LNPI = 1.14472988584940017414342735135 LN2 = 0.69314718055994530941723212146 SQRT2 = 1.41421356237309504880168872421 SQRTPI = 1.77245385090551602729816748334 ROOT3_FLOAT_MIN = Float::MIN ** (1/3.0) ROOT3_FLOAT_EPSILON = Float::EPSILON ** (1/3.0) ROOT4_FLOAT_MIN = Float::MIN ** (1/4.0) ROOT4_FLOAT_EPSILON = Float::EPSILON ** (1/4.0) ROOT5_FLOAT_MIN = Float::MIN ** (1/5.0) ROOT5_FLOAT_EPSILON = Float::EPSILON ** (1/5.0) ROOT6_FLOAT_MIN = Float::MIN ** (1/6.0) ROOT6_FLOAT_EPSILON = Float::EPSILON ** (1/6.0) LOG_FLOAT_MIN = Math.log(Float::MIN) EULER = 0.57721566490153286060651209008 # e^x taking into account the error thus far (I think) # gsl_sf_exp_err_e def exp_err(x, dx) adx = dx.abs raise("Overflow Error in exp_err: x + adx > LOG_FLOAT_MAX") if x + adx > LOG_FLOAT_MAX raise("Underflow Error in exp_err: x - adx < LOG_FLOAT_MIN") if x - adx < LOG_FLOAT_MIN [Math.exp(x), Math.exp(x) * [Float::EPSILON, Math.exp(adx) - 1.0/Math.exp(adx)] + 2.0 * Float::EPSILON * Math.exp(x).abs] end end enddistribution-0.7.3/lib/distribution/math_extension/exponential_integral.rb0000644000004100000410000000557212540356202027352 0ustar www-datawww-datamodule Distribution module MathExtension # From GSL-1.9. module ExponentialIntegral class << self def first_order x, scale = 0, with_error = false xmaxt = -Math::LOG_FLOAT_MIN xmax = xmaxt - Math.log(xmaxt) result = nil error = with_error ? nil : 0.0 if x < -xmax && !scale raise("Overflow Error") elsif x <= -10.0 s = 1.0 / x * ( scale ? 1.0 : Math.exp(-x)) result_c = ChebyshevSeries.eval(20.0/x+1.0, :ae11, with_error) result_c, result_c_err = result_c if with_error result = s * (1.0 + result_c) error ||= (s * result_c_err) + 2.0*Float::EPSILON * (x.abs + 1.0) * result.abs elsif x <= -4.0 s = 1.0 / x * (scale ? 1.0 : Math.exp(-x)) result_c = ChebyshevSeries.eval((40.0/x+7.0)/3.0, :ae12, with_error) result_c, result_c_err = result_c if with_error result = s * (1.0 + result_c) error ||= (s * result_c_err) + 2.0*Float::EPSILON * result.abs elsif x <= -1.0 ln_term = - Math.log(x.abs) scale_factor = scale ? Math.exp(x) : 1.0 result_c = ChebyshevSeries.eval((2.0*x+5.0)/3.0, :e11, with_error) result_c, result_c_err = result_c if with_error result = scale_factor * (ln_term + result_c) error ||= scale_factor * (result_c_err + Float::EPSILON * ln_term.abs) + 2.0*Float::EPSILON*result.abs elsif x == 0.0 raise(ArgumentError, "Domain Error") elsif x <= 1.0 ln_term = - Math.log(x.abs) scale_factor = scale ? Math.exp(x) : 1.0 result_c = ChebyshevSeries.eval(x, :e12, with_error) result_c, result_c_err = result_c if with_error result = scale_factor * (ln_term - 0.6875 + x + result_c) error ||= scale_factor * (result_c_err + Float::EPSILON * ln_term.abs) + 2.0*Float::EPSILON*result.abs elsif x <= 4.0 s = 1.0 / x * (scale ? 1.0 : Math.exp(-x)) result_c = ChebyshevSeries.eval((8.0/x-5.0)/3.0, :ae13, with_error) result_c, result_c_err = result_c if with_error result = s * (1.0 + result_c) error ||= (s * result_c_err) + 2.0*Float::EPSILON * result.abs elsif x <= xmax || scale s = 1.0 / x * (scale ? 1.0 : Math.exp(-x)) result_c = ChebyshevSeries.eval(8.0/x-1.0, :ae14, with_error) result_c, result_c_err = result_c if with_error result = s * (1.0 + result_c) error ||= s * (Float::EPSILON + result_c_err) + 2.0*(x+1.0)*Float::EPSILON * result.abs raise("Underflow Error") if result == 0.0 else raise("Underflow Error") end with_error ? [result, error] : result end end end end end distribution-0.7.3/lib/distribution/math_extension/incomplete_gamma.rb0000644000004100000410000004010712540356202026431 0ustar www-datawww-data# Added by John O. Woods, SciRuby project. # Derived from GSL-1.9 source files in the specfunc/ dir. # require "statsample" module Distribution module MathExtension module IncompleteGamma NMAX = 5000 SMALL = Float::EPSILON ** 3 PG21 = -2.404113806319188570799476 # PolyGamma[2,1] class << self # Helper function for plot #def range_to_array r # r << (r.last - r.first)/100.0 if r.size == 2 # set dr as Dr/100.0 # arr = [] # pos = r[0] # while pos <= r[1] # arr << pos # pos += r[2] # end # arr #end # #def plot a, x_range, fun = :p # x_range = range_to_array(x_range) if x_range.is_a?(Array) # y_range = x_range.collect { |x| self.send(fun, a, x) } # graph = Statsample::Graph::Scatterplot.new x_range.to_scale, y_range.to_scale # f = File.new("test.svg", "w") # f.puts(graph.to_svg) # f.close # `google-chrome test.svg` #end # The dominant part, D(a,x) := x^a e^(-x) / Gamma(a+1) # gamma_inc_D in GSL-1.9. def d(a, x, with_error = false) error = nil if a < 10.0 ln_a = Math.lgamma(a+1.0).first lnr = a * Math.log(x) - x - ln_a result = Math.exp(lnr) error = 2.0 * Float::EPSILON * (lnr.abs + 1.0) + result.abs if with_error with_error ? [result,error] : result else ln_term = ln_term_error = nil if x < 0.5*a u = x/a.to_f ln_u = Math.log(u) ln_term = ln_u - u + 1.0 ln_term_error = (ln_u.abs + u.abs + 1.0) * Float::EPSILON if with_error else mu = (x-a)/a.to_f ln_term = Log::log_1plusx_minusx(mu, with_error) ln_term, ln_term_error = ln_term if with_error end gstar = Gammastar.evaluate(a, with_error) gstar,gstar_error = gstar if with_error term1 = Math.exp(a*ln_term) / Math.sqrt(2.0*Math::PI*a) result = term1/gstar error = 2.0*Float::EPSILON*((a*ln_term).abs+1.0) * result.abs + gstar_error/gstar.abs * result.abs if with_error with_error ? [result,error] : result end end # gamma_inc_P_series def p_series(a,x,with_error=false) d = d(a,x,with_error) d, d_err = d if with_error sum = 1.0 term = 1.0 n = 1 1.upto(NMAX-1) do |n| term *= x / (a+n).to_f sum += term break if (term/sum).abs < Float::EPSILON end result = d * sum if n == NMAX STDERR.puts("Error: n reached NMAX in p series") else return with_error ? [result,d_err * sum.abs + (1.0+n)*Float::EPSILON * result.abs] : result end end # This function does not exist in GSL, but is nonetheless GSL code. It's for calculating two specific ranges of p. def q_asymptotic_uniform_complement a,x,with_error=false q = q_asymptotic_uniform(a, x, with_error) q,q_err = q if with_error result = 1.0 - q return with_error ? [result, q_err + 2.0*Float::EPSILON*result.abs] : result end def q_continued_fraction_complement a,x,with_error=false q = q_continued_fraction(a,x,with_error) return with_error ? [1.0 - q.first, q.last + 2.0*Float::EPSILON*(1.0-q.first).abs] : 1.0 - q end def q_large_x_complement a,x,with_error=false q = q_large_x(a,x,with_error) return with_error ? [1.0 - q.first, q.last + 2.0*Float::EPSILON*(1.0-q.first).abs] : 1.0 - q end # The incomplete gamma function. # gsl_sf_gamma_inc_P_e def p a,x,with_error=false raise(ArgumentError, "Range Error: a must be positive, x must be non-negative") if a <= 0.0 || x < 0.0 if x == 0.0 return with_error ? [0.0, 0.0] : 0.0 elsif x < 20.0 || x < 0.5*a return p_series(a, x, with_error) elsif a > 1e6 && (x-a)*(x-a) < a return q_asymptotic_uniform_complement a, x, with_error elsif a <= x if a > 0.2*x return q_continued_fraction_complement(a, x, with_error) else return q_large_x_complement(a, x, with_error) end elsif (x-a)*(x-a) < a return q_asymptotic_uniform_complement a, x, with_error else return p_series(a, x, with_error) end end # gamma_inc_Q_e def q a,x,with_error=false raise(ArgumentError, "Range Error: a and x must be non-negative") if (a < 0.0 || x < 0.0) if x == 0.0 return with_error ? [1.0, 0.0] : 1.0 elsif a == 0.0 return with_error ? [0.0, 0.0] : 0.0 elsif x <= 0.5*a # If series is quick, do that. p = p_series(a,x, with_error) p,p_err = p if with_error result = 1.0 - p return with_error ? [result, p_err + 2.0*Float::EPSILON*result.abs] : result elsif a >= 1.0e+06 && (x-a)*(x-a) < a # difficult asymptotic regime, only way to do this region return q_asymptotic_uniform(a, x, with_error) elsif a < 0.2 && x < 5.0 return q_series(a,x, with_error) elsif a <= x return x <= 1.0e+06 ? q_continued_fraction(a, x, with_error) : q_large_x(a, x, with_error) else if x > a-Math.sqrt(a) return q_continued_fraction(a, x, with_error) else p = p_series(a, x, with_error) p, p_err = p if with_error result = 1.0 - p return with_error ? [result, p_err + 2.0*Float::EPSILON*result.abs] : result end end end # gamma_inc_Q_CF def q_continued_fraction a, x, with_error=false d = d(a, x, with_error) f = f_continued_fraction(a, x, with_error) if with_error [d.first*(a/x).to_f*f.first, d.last * ((a/x).to_f*f.first).abs + (d.first*a/x*f.last).abs] else d * (a/x).to_f * f end end # gamma_inc_Q_large_x in GSL-1.9 def q_large_x a,x,with_error=false d = d(a,x,with_error) d,d_err = d if with_error sum = 1.0 term = 1.0 last = 1.0 n = 1 1.upto(NMAX-1).each do |n| term *= (a-n)/x break if (term/last).abs > 1.0 break if (term/sum).abs < Float::EPSILON sum += term last = term end result = d*(a/x)*sum error = d_err * (a/x).abs * sum if with_error if n == NMAX STDERR.puts("Error: n reached NMAX in q_large_x") else return with_error ? [result,error] : result end end # Uniform asymptotic for x near a, a and x large # gamma_inc_Q_asymp_unif def q_asymptotic_uniform(a, x, with_error = false) rta = Math.sqrt(a) eps = (x-a).quo(a) ln_term = Log::log_1plusx_minusx(eps, with_error) ln_term, ln_term_err = ln_term if with_error eta = (eps >= 0 ? 1 : -1) * Math.sqrt(-2*ln_term) erfc = Math.erfc_e(eta*rta/SQRT2, with_error) erfc, erfc_err = erfc if with_error c0 = c1 = nil if eps.abs < ROOT5_FLOAT_EPSILON c0 = -1.quo(3) + eps*(1.quo(12) - eps*(23.quo(540) - eps*(353.quo(12960) - eps*589.quo(30240)))) c1 = -1.quo(540) - eps.quo(288) else rt_term = Math.sqrt(-2 * ln_term.quo(eps*eps)) lam = x.quo(a) c0 = (1 - 1/rt_term)/eps c1 = -(eta**3 * (lam*lam + 10*lam + 1) - 12*eps**3).quo(12 * eta**3 * eps**3) end r = Math.exp(-0.5*a*eta*eta) / (SQRT2*SQRTPI*rta) * (c0 + c1.quo(a)) result = 0.5 * erfc + r with_error ? [result, Float::EPSILON + (r*0.5*a*eta*eta).abs + 0.5*erfc_err + 2.0*Float::EPSILON + result.abs] : result end # gamma_inc_F_CF def f_continued_fraction a, x, with_error = false hn = 1.0 # convergent cn = 1.0 / SMALL dn = 1.0 n = 2 2.upto(NMAX-1).each do |n| an = n.odd? ? 0.5*(n-1)/x : (0.5*n-a)/x dn = 1.0 + an * dn dn = SMALL if dn.abs < SMALL cn = 1.0 + an / cn cn = SMALL if cn.abs < SMALL dn = 1.0 / dn delta = cn * dn hn *= delta break if (delta-1.0).abs < Float::EPSILON end if n == NMAX STDERR.puts("Error: n reached NMAX in f continued fraction") else with_error ? [hn,2.0*Float::EPSILON * hn.abs + Float::EPSILON*(2.0+0.5*n) * hn.abs] : hn end end def q_series(a,x,with_error=false) term1 = nil sum = nil term2 = nil begin lnx = Math.log(x) el = EULER + lnx c1 = -el c2 = Math::PI * Math::PI / 12.0 - 0.5*el*el c3 = el*(Math::PI*Math::PI/12.0 - el*el/6.0) + PG21/6.0 c4 = -0.04166666666666666667 * (-1.758243446661483480 + lnx) * (-0.764428657272716373 + lnx) * ( 0.723980571623507657 + lnx) * ( 4.107554191916823640 + lnx) c5 = -0.0083333333333333333 * (-2.06563396085715900 + lnx) * (-1.28459889470864700 + lnx) * (-0.27583535756454143 + lnx) * ( 1.33677371336239618 + lnx) * ( 5.17537282427561550 + lnx) c6 = -0.0013888888888888889 * (-2.30814336454783200 + lnx) * (-1.65846557706987300 + lnx) * (-0.88768082560020400 + lnx) * ( 0.17043847751371778 + lnx) * ( 1.92135970115863890 + lnx) * ( 6.22578557795474900 + lnx) c7 = -0.00019841269841269841 (-2.5078657901291800 + lnx) * (-1.9478900888958200 + lnx) * (-1.3194837322612730 + lnx) * (-0.5281322700249279 + lnx) * ( 0.5913834939078759 + lnx) * ( 2.4876819633378140 + lnx) * ( 7.2648160783762400 + lnx) c8 = -0.00002480158730158730 * (-2.677341544966400 + lnx) * (-2.182810448271700 + lnx) * (-1.649350342277400 + lnx) * (-1.014099048290790 + lnx) * (-0.191366955370652 + lnx) * ( 0.995403817918724 + lnx) * ( 3.041323283529310 + lnx) * ( 8.295966556941250 + lnx) * c9 = -2.75573192239859e-6 * (-2.8243487670469080 + lnx) * (-2.3798494322701120 + lnx) * (-1.9143674728689960 + lnx) * (-1.3814529102920370 + lnx) * (-0.7294312810261694 + lnx) * ( 0.1299079285269565 + lnx) * ( 1.3873333251885240 + lnx) * ( 3.5857258865210760 + lnx) * ( 9.3214237073814600 + lnx) * c10 = -2.75573192239859e-7 * (-2.9540329644556910 + lnx) * (-2.5491366926991850 + lnx) * (-2.1348279229279880 + lnx) * (-1.6741881076349450 + lnx) * (-1.1325949616098420 + lnx) * (-0.4590034650618494 + lnx) * ( 0.4399352987435699 + lnx) * ( 1.7702236517651670 + lnx) * ( 4.1231539047474080 + lnx) * ( 10.342627908148680 + lnx) term1 = a*(c1+a*(c2+a*(c3+a*(c4+a*(c5+a*(c6+a*(c7+a*(c8+a*(c9+a*c10))))))))) end n = 1 begin t = 1.0 sum = 1.0 1.upto(NMAX-1).each do |n| t *= -x/(n+1.0) sum += (a+1.0) / (a+n+1.0) * t break if (t/sum).abs < Float::EPSILON end end if n == NMAX STDERR.puts("Error: n reached NMAX in q_series") else term2 = (1.0 - term1) * a/(a+1.0) * x * sum result = term1+term2 with_error ? [result, Float::EPSILON*term1.abs + 2.0*term2.abs + 2.0*Float::EPSILON*result.abs] : result end end # gamma_inc_series def series a,x,with_error = false q = q_series(a,x,with_error) g = Math.gamma(a) STDERR.puts("Warning: Don't know error for Math.gamma. Error will be incorrect") if with_error # When we get the error from Gamma, switch the comment on the next to lines # with_error ? [q.first*g.first, (q.first*g.last).abs + (q.last*g.first).abs + 2.0*Float::EPSILON*(q.first*g.first).abs] : q*g with_error ? [q.first*g, (q.first*Float::EPSILON).abs + (q.last*g.first).abs + 2.0*Float::EPSILON(q.first*g).abs] : q*g end # gamma_inc_a_gt_0 def a_greater_than_0 a, x, with_error = false q = q(a,x,with_error) q,q_err = q if with_error g = Math.gamma(a) STDERR.puts("Warning: Don't know error for Math.gamma. Error will be incorrect") if with_error g_err = Float::EPSILON result = g*q error = (g*q_err).abs + (g_err*q).abs if with_error with_error ? [result,error] : result end # gamma_inc_CF def continued_fraction a,x, with_error=false f = f_continued_fraction(a,x,with_error) f,f_error = f if with_error pre = Math.exp((a-1.0)*Math.log(x) - x) STDERR.puts("Warning: Don't know error for Math.exp. Error will be incorrect") if with_error pre_error = Float::EPSILON result = f*pre if with_error error = (f_error*pre).abs + (f*pre_error) + (2.0+a.abs)*Float::EPSILON*result.abs [result,error] else result end end # Unnormalized incomplete gamma function. # gsl_sf_gamma_inc_e def unnormalized a,x,with_error = false raise(ArgumentError, "x cannot be negative") if x < 0.0 if x == 0.0 result = Math.gamma(a.to_f) STDERR.puts("Warning: Don't know error for Math.gamma. Error will be incorrect") if with_error return with_error ? [result, Float::EPSILON] : result elsif a == 0.0 return ExponentialIntegral.first_order(x.to_f, with_error) elsif a > 0.0 return a_greater_than_0(a.to_f, x.to_f, with_error) elsif x > 0.25 # continued fraction seems to fail for x too small return continued_fraction(a.to_f, x.to_f, with_error) elsif a.abs < 0.5 return series(a.to_f,x.to_f,with_error) else fa = a.floor.to_f da = a - fa g_da = da > 0.0 ? a_greater_than_0(da, x.to_f, with_error) : ExponentialIntegral.first_order(x.to_f, with_error) g_da, g_da_err = g_da if with_error alpha = da gax = g_da # Gamma(alpha-1,x) = 1/(alpha-1) (Gamma(a,x) - x^(alpha-1) e^-x) begin shift = Math.exp(-x + (alpha-1.0)*Math.log(x)) gax = (gax-shift) / (alpha-1.0) alpha -= 1.0 end while alpha > a result = gax return with_error ? [result, 2.0*(1.0 + a.abs) * Float::EPSILON*gax.abs] : result end end end end end enddistribution-0.7.3/lib/distribution/math_extension/incomplete_beta.rb0000644000004100000410000001671712540356202026274 0ustar www-datawww-data# Added by John O. Woods, SciRuby project. # Derived from GSL-1.9 source files in the specfunc/ dir. module Distribution module MathExtension module Beta class << self # Based on gsl_sf_lnbeta_e and gsl_sf_lnbeta_sgn_e # Returns result and sign in an array. If with_error is specified, also returns the error. def log_beta(x,y, with_error=false) sign = nil raise(ArgumentError, "x and y must be nonzero") if x == 0.0 || y == 0.0 raise(ArgumentError, "not defined for negative integers") if [x,y].any? { |v| (v.is_a?(Fixnum) && v < 0) } # See if we can handle the positive case with min/max < 0.2 if x > 0 && y > 0 min, max = [x,y].minmax ratio = min.quo(max) if ratio < 0.2 gsx = Gammastar.evaluate(x, with_error) gsy = Gammastar.evaluate(y, with_error) gsxy = Gammastar.evaluate(x+y, with_error) lnopr = Log::log_1plusx(ratio, with_error) gsx, gsx_err, gsy, gsy_err, gsxy, gsxy_err, lnopr, lnopr_err = [gsx,gsy,gsxy,lnopr].flatten if with_error lnpre = Math.log((gsx*gsy).quo(gsxy) * Math::SQRT2 * Math::SQRTPI) lnpre_err = gsx_err.quo(gsx) + gsy_err(gsy) + gsxy_err.quo(gsxy) if with_error t1 = min * Math.log(ratio) t2 = 0.5 * Math.log(min) t3 = (x+y-0.5)*lnopr lnpow = t1 - t2 - t3 lnpow_err = Float::EPSILON * (t1.abs + t2.abs + t3.abs) + (x+y-0.5).abs * lnopr_err if with_error result = lnpre + lnpow error = lnpre_err + lnpow_err + 2.0*Float::EPSILON*result.abs if with_error return with_error ? [result, 1.0, error] : [result, 1.0] end end # General case: fallback lgx, sgx = Math.lgamma(x) lgy, sgy = Math.lgamma(y) lgxy, sgxy = Math.lgamma(x+y) sgn = sgx * sgy * sgxy raise("Domain error: sign is -") if sgn == -1 result = lgx + lgy - lgxy if with_error lgx_err, lgy_err, lgxy_err = begin STDERR.puts("Warning: Error is unknown for Math::lgamma, guessing.") [Math::EPSILON, Math::EPSILON, Math::EPSILON] end error = lgx_err + lgy_err + lgxy_err + Float::EPSILON*(lgx.abs+lgy.abs+lgxy.abs) + 2.0*(Float::EPSILON)*result.abs return [result, sgn, error] else return [result, sgn] end end end end # Calculate regularized incomplete beta function module IncompleteBeta MAX_ITER = 512 CUTOFF = 2.0 * Float::MIN class << self # Evaluate aa * beta_inc(a,b,x) + yy # # No error mode available. # # From GSL-1.9: cdf/beta_inc.c, beta_inc_AXPY def axpy(aa,yy,a,b,x) return aa*0 + yy if x == 0.0 return aa*1 + yy if x == 1.0 ln_beta = Math.logbeta(a, b) ln_pre = -ln_beta + a * Math.log(x) + b * Math::Log.log1p(-x) prefactor = Math.exp(ln_pre) if x < (a+1).quo(a+b+2) # Apply continued fraction directly epsabs = yy.quo((aa * prefactor).quo(a)).abs * Float::EPSILON cf = continued_fraction(a, b, x, epsabs) return aa * (prefactor * cf).quo(a) + yy else # Apply continued fraction after hypergeometric transformation epsabs = (aa + yy).quo( (aa*prefactor).quo(b) ) * Float::EPSILON cf = continued_fraction(b, a, 1-x, epsabs) term = (prefactor * cf).quo(b) return aa == -yy ? -aa*term : aa*(1-term)+yy end end # Evaluate the incomplete beta function # gsl_sf_beta_inc_e def evaluate(a,b,x,with_error=false) raise(ArgumentError, "Domain error: a(#{a}), b(#{b}) must be positive; x(#{x}) must be between 0 and 1, inclusive") if a <= 0 || b <= 0 || x < 0 || x > 1 if x == 0 return with_error ? [0.0,0.0] : 0.0 elsif x == 1 return with_error ? [1.0,0.0] : 1.0 else ln_beta = Beta.log_beta(a,b, with_error) ln_1mx = Log.log_1plusx(-x, with_error) ln_x = Math.log(x) ln_beta, ln_beta_err, ln_1mx, ln_1mx_err, ln_x_err = begin #STDERR.puts("Warning: Error is unknown for Math::log, guessing.") [ln_beta,ln_1mx,Float::EPSILON].flatten end ln_pre = -ln_beta + a*ln_x + b*ln_1mx ln_pre_err = ln_beta_err + (a*ln_x_err).abs + (b*ln_1mx_err).abs if with_error prefactor, prefactor_err = begin if with_error exp_err(ln_pre, ln_pre_err) else [Math.exp(ln_pre), nil] end end if x < (a+1).quo(a+b+2) # Apply continued fraction directly cf = continued_fraction(a,b,x, nil, with_error) cf,cf_err = cf if with_error result = (prefactor * cf).quo(a) return with_error ? [result, ((prefactor_err*cf).abs + (prefactor*cf_err).abs).quo(a)] : result else # Apply continued fraction after hypergeometric transformation cf = continued_fraction(b, a, 1-x, nil) cf,cf_err = cf if with_error term = (prefactor * cf).quo(b) result = 1 - term return with_error ? [result, (prefactor_err*cf).quo(b) + (prefactor*cf_err).quo(b) + 2.0*Float::EPSILON*(1+term.abs)] : result end end end def continued_fraction_cutoff(epsabs) return CUTOFF if epsabs.nil? 0.0/0 # NaN end # Continued fraction calculation of incomplete beta # beta_cont_frac from GSL-1.9 # # If epsabs is set, will execute the version of the GSL function in the cdf folder. Otherwise, does the # basic one in specfunc. def continued_fraction(a,b,x,epsabs=nil,with_error=false) num_term = 1 den_term = 1 - (a+b)*x.quo(a+1) k = 0 den_term = continued_fraction_cutoff(epsabs) if den_term.abs < CUTOFF den_term = 1.quo(den_term) cf = den_term 1.upto(MAX_ITER) do |k| coeff = k *(b-k)*x.quo(((a-1)+2*k)*(a+2*k)) # coefficient for step 1 delta_frac = nil 2.times do den_term = 1 + coeff*den_term num_term = 1 + coeff.quo(num_term) den_term = continued_fraction_cutoff(epsabs) if den_term.abs < CUTOFF num_term = continued_fraction_cutoff(epsabs) if num_term.abs < CUTOFF den_term = 1.quo(den_term) delta_frac = den_term * num_term cf *= delta_frac coeff = -(a+k)*(a+b+k)*x.quo((a+2*k)*(a+2*k+1)) # coefficient for step 2 end break if (delta_frac-1).abs < 2.0*Float::EPSILON break if !epsabs.nil? && (cf * (delta_frac-1).abs < epsabs) end if k > MAX_ITER raise("Exceeded maximum number of iterations") if epsabs.nil? return with_error ? [0.0/0, 0] : 0.0/0 # NaN if epsabs is set end with_error ? [cf, k * 4 * Float::EPSILON * cf.abs] : cf end end end end enddistribution-0.7.3/lib/distribution/math_extension/erfc.rb0000644000004100000410000000451312540356202024050 0ustar www-datawww-data# Added by John O. Woods, SciRuby project. # Derived from GSL-1.9 source files in the specfunc/ dir. module Distribution module MathExtension # Error function from GSL-1.9, with epsilon information. Access it using Math.erfc_e module Erfc P = [ 2.97886562639399288862, 7.409740605964741794425, 6.1602098531096305440906, 5.019049726784267463450058, 1.275366644729965952479585264, 0.5641895835477550741253201704 ] Q = [ 3.3690752069827527677, 9.608965327192787870698, 17.08144074746600431571095, 12.0489519278551290360340491, 9.396034016235054150430579648, 2.260528520767326969591866945, 1.0 ] class << self # Estimates erfc(x) valid for 8 < x < 100 # erfc8_sum from GSL-1.9 def erfc8_sum(x) num = P[5] 4.downto(0) { |i| num = x*num + P[i] } den = Q[6] 5.downto(0) { |i| den = x*den + Q[i] } num / den end def erfc8(x) erfc8_sum(x) * Math.exp(-x*x) end # gsl_sf_erfc_e def evaluate(x, with_error = false) ax = x.abs e = nil if ax <= 1.0 t = 2*ax-1 e = ChebyshevSeries.evaluate(:erfc_xlt1, t, with_error) elsif ax <= 5.0 ex2 = Math.exp(-x*x) t = (ax-3).quo(2) e = ChebyshevSeries.evaluate(:erfc_x15, t, with_error) if with_error e[0] *= ex2 e[1] = ex2 * (e[1] + 2*x.abs*Float::EPSILON) else e *= ex2 end elsif ax < 10.0 exterm = Math.exp(-x*x) / ax t = (2*ax-15).quo(5) e = ChebyshevSeries.evaluate(:erfc_x510, t, with_error) if with_error e[0] *= exterm e[1] = exterm * (e[1] + 2*x.abs*Float::EPSILON + Float::EPSILON) else e *= exterm end else e8 = erfc8(ax) e = with_error ? [e8, (x*x + 1) * Float::EPSILON * e8.abs] : e8 end result = x < 0 ? 2 - (with_error ? e.first : e) : (with_error ? e.first : e) with_error ? [result, e.last + 2*Float::EPSILON*result.abs] : result end end end end enddistribution-0.7.3/lib/distribution/logistic/0000755000004100000410000000000012540356202021371 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/logistic/ruby.rb0000644000004100000410000000065212540356202022702 0ustar www-datawww-datamodule Distribution module Logistic module Ruby_ class << self def rng(u,s) lambda {p_value(rand(),u,s)} end def pdf(x,u,s ) (Math.exp(-(x-u) / s)) / (s*(1+Math.exp(-(x-u) / s)**2)) end def cdf(x,u,s ) 1/(1+Math.exp(-(x-u) / s)) end def p_value(pr,u,s ) u+s*Math.log(pr/(1-pr)) end end end end end distribution-0.7.3/lib/distribution/weibull/0000755000004100000410000000000012540356202021217 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/weibull/gsl.rb0000644000004100000410000000063712540356202022337 0ustar www-datawww-datamodule Distribution module Weibull module GSL_ class << self def pdf(x, k, lam) GSL::Ran.weibull_pdf(x, lam, k) end def cdf(x, k, lam) GSL::Cdf.weibull_P(x, lam, k) end def p_value(y, k, lam) GSL::Cdf.weibull_Pinv(y, lam, k) end end end end end distribution-0.7.3/lib/distribution/weibull/ruby.rb0000644000004100000410000000135312540356202022527 0ustar www-datawww-datamodule Distribution module Weibull module Ruby_ class << self def pdf(x, k, lam) return 0.0 if x < 0.0 return ((k.to_f/lam.to_f)*(x.to_f/lam.to_f)**(k-1.0))*Math.exp(-(x.to_f/lam.to_f)**k) end #Returns the integral of the Weibull distribution from [-Inf to x] def cdf(x, k, lam) return 0.0 if x < 0.0 return 1.0-Math.exp(-(x.to_f/lam.to_f)**k) end # Returns the P-value of weibull def p_value(y, k, lam) return 1.0 if y > 1.0 return 0.0 if y < 0.0 return -lam*(Math.log(1.0-y))**(1.0/k) end end end end enddistribution-0.7.3/lib/distribution/f.rb0000644000004100000410000000136212540356202020330 0ustar www-datawww-datarequire 'distribution/f/ruby' require 'distribution/f/gsl' require 'distribution/f/statistics2' require 'distribution/f/java' module Distribution # Calculate cdf and inverse cdf for F Distribution. # module F SHORTHAND='fdist' extend Distributable create_distribution_methods ## # :singleton-method: pdf(x,k1,k2) # Returns the PDF of F distribution # with +k1+ and +k2+ degrees of freedom over [0, +x+] ## # :singleton-method: p_value(qn, k1, k2) # Return the P-value of the corresponding integral +qn+ with # +k1+ and +k2+ degrees of freedom ## # :singleton-method: cdf(x,k1,k2) # Returns the integral of F distribution # with +k1+ and +k2+ degrees of freedom over [0, +x+] end end distribution-0.7.3/lib/distribution/beta/0000755000004100000410000000000012540356202020467 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/beta/gsl.rb0000644000004100000410000000120212540356202021574 0ustar www-datawww-datamodule Distribution module Beta module GSL_ class << self def pdf(x, a, b) GSL::Ran.beta_pdf(x.to_f, a.to_f, b.to_f) end # Return the P-value of the corresponding integral with # k degrees of freedom def p_value(pr, a, b) GSL::Cdf.beta_Pinv(pr.to_f, a.to_f, b.to_f) end # Beta cumulative distribution function (cdf). # # Returns the integral of Beta distribution # with parameters +a+ and +b+ over [0, x] # def cdf(x, a, b) GSL::Cdf.beta_P(x.to_f, a.to_f, b.to_f) end end end end end distribution-0.7.3/lib/distribution/beta/ruby.rb0000644000004100000410000000402312540356202021774 0ustar www-datawww-data# Added by John O. Woods, SciRuby project. module Distribution module Beta module Ruby_ class << self include Math # Beta distribution probability density function # # Adapted from GSL-1.9 (apparently by Knuth originally), found in randist/beta.c # # Form: p(x) dx = (Gamma(a + b)/(Gamma(a) Gamma(b))) x^(a-1) (1-x)^(b-1) dx # # == References # * http://www.gnu.org/s/gsl/manual/html_node/The-Gamma-Distribution.html def pdf(x, a, b) return 0 if x < 0 || x > 1 gab = Math.lgamma(a + b).first ga = Math.lgamma(a).first gb = Math.lgamma(b).first if x == 0.0 || x == 1.0 Math.exp(gab - ga - gb) * x**(a - 1) * (1 - x)**(b - 1) else Math.exp(gab - ga - gb + Math.log(x) * (a - 1) + Math::Log.log1p(-x) * (b - 1)) end end # Gamma cumulative distribution function # Translated from GSL-1.9: cdf/beta.c gsl_cdf_beta_P def cdf(x, a, b) return 0.0 if x <= 0.0 return 1.0 if x >= 1.0 Math::IncompleteBeta.axpy(1.0, 0.0, a, b, x) end # Inverse of the beta distribution function def p_value(p, a, b, rmin = 0, rmax = 1) fail 'a <= 0' if a <= 0 fail 'b <= 0' if b <= 0 fail 'rmin == rmax' if rmin == rmax fail 'p <= 0' if p <= 0 fail 'p > 1' if p > 1 precision = 8.88e-016 max_iterations = 256 ga = 0 gb = 2 i = 1 while ((gb - ga) > precision) && (i < max_iterations) guess = (ga + gb) / 2.0 result = cdf(guess, a, b) if (result == p) || (result == 0) gb = ga elsif result > p gb = guess else ga = guess end fail 'No value' if i == max_iterations i += 1 end rmin + guess * (rmax - rmin) end end end end end distribution-0.7.3/lib/distribution/beta/java.rb0000644000004100000410000000015612540356202021737 0ustar www-datawww-datamodule Distribution module Beta # TODO module Java_ class << self end end end end distribution-0.7.3/lib/distribution/poisson/0000755000004100000410000000000012540356202021246 5ustar www-datawww-datadistribution-0.7.3/lib/distribution/poisson/gsl.rb0000644000004100000410000000046412540356202022364 0ustar www-datawww-datamodule Distribution module Poisson module GSL_ class << self def pdf(k,l) return 0 if k<0 GSL::Ran.poisson_pdf(k,l.to_f) end def cdf(k,l) return 0 if k<0 GSL::Cdf.poisson_P(k, l.to_f) end end end end enddistribution-0.7.3/lib/distribution/poisson/ruby.rb0000644000004100000410000000071612540356202022560 0ustar www-datawww-datamodule Distribution module Poisson module Ruby_ class << self def pdf(k,l ) (l**k*Math.exp(-l)).quo(Math.factorial(k)) end def cdf(k,l) Math.exp(-l)*(0..k).inject(0) {|ac,i| ac+ (l**i).quo(Math.factorial(i))} end def p_value(prob,l) ac=0 (0..100).each do |i| ac+=pdf(i,l) return i if prob<=ac end end end end end enddistribution-0.7.3/lib/distribution/poisson/java.rb0000644000004100000410000000121412540356202022512 0ustar www-datawww-datamodule Distribution module Poisson module Java_ class << self #== # Create the PoissonDistributionImpl object for use in calculations # with mean of l def create_distribution(l) PoissonDistributionImpl.new(l) end #== # def pdf(k,l) dist = create_distribution(l) dist.probability(k) end def cdf(k,l) dist = create_distribution(l) dist.cumulativeProbability(k) end # def p_value(pr,l) # dist = create_distribution(l) # dist.inverseCumulativeProbability(pr) # end end end end enddistribution-0.7.3/lib/distribution/normalmultivariate.rb0000644000004100000410000000431312540356202024021 0ustar www-datawww-datamodule Distribution # Calculate cdf and inverse cdf for Multivariate Distribution. module NormalMultivariate class << self # Returns multivariate cdf distribution # * a is the array of lower values # * b is the array of higher values # * s is an symmetric positive definite covariance matrix def cdf(aa,bb,sigma, epsilon=0.0001, alpha=2.5, max_iterations=100) # :nodoc: raise "Doesn't work yet" a=[nil]+aa b=[nil]+bb m=aa.size sigma=sigma.to_gsl if sigma.respond_to? :to_gsl cc=GSL::Linalg::Cholesky.decomp(sigma) c=cc.lower intsum=0 varsum=0 n=0 d=Array.new(m+1,nil) e=Array.new(m+1,nil) f=Array.new(m+1,nil) (1..m).each {|i| d[i]=0.0 if a[i].nil? e[i]=1.0 if b[i].nil? } d[1]=uPhi(a[1].quo( c[0,0])) unless d[1]==0 e[1]=uPhi(b[1].quo( c[0,0])) unless e[1]==1 f[1]=e[1]-d[1] error=1000 begin w=(m+1).times.collect {|i| rand*epsilon} y=[] (2..m).each do |i| y[i-1]=iPhi(d[i-1] + w[i-1] * (e[i-1] - d[i-1])) sumc=0 (1..(i-1)).each do |j| sumc+=c[i-1, j-1]*y[j] end if a[i]!=nil d[i]=uPhi((a[i]-sumc).quo(c[i-1,i-1])) end # puts "sumc:#{sumc}" if b[i]!=nil #puts "e[#{i}] :#{c[i-1,i-1]}" e[i]=uPhi((b[i]-sumc).quo(c[i-1, i-1])) end f[i]=(e[i]-d[i])*f[i-1] end intsum+=intsum+f[m] varsum=varsum+f[m]**2 n+=1 error=alpha*Math::sqrt((varsum.quo(n) - (intsum.quo(n))**2).quo(n)) end while(error>epsilon and n=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rspec requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '3.2' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '3.2' description: Distribution email: - clbustos@gmail.com executables: - distribution extensions: [] extra_rdoc_files: [] files: - ".gitignore" - ".travis.yml" - Gemfile - History.txt - LICENCE.md - README.md - Rakefile - benchmark/binomial_coefficient.rb - benchmark/binomial_coefficient/binomial_coefficient.ds - benchmark/binomial_coefficient/binomial_coefficient.xls - benchmark/binomial_coefficient/experiment.rb - benchmark/factorial_hash.rb - benchmark/factorial_method.rb - benchmark/odd.rb - benchmark/power.rb - bin/distribution - data/template/distribution.erb - data/template/distribution/gsl.erb - data/template/distribution/ruby.erb - data/template/spec.erb - distribution.gemspec - lib/distribution.rb - lib/distribution/beta.rb - lib/distribution/beta/gsl.rb - lib/distribution/beta/java.rb - lib/distribution/beta/ruby.rb - lib/distribution/binomial.rb - lib/distribution/binomial/gsl.rb - lib/distribution/binomial/java.rb - lib/distribution/binomial/ruby.rb - lib/distribution/bivariatenormal.rb - lib/distribution/bivariatenormal/gsl.rb - lib/distribution/bivariatenormal/java.rb - lib/distribution/bivariatenormal/ruby.rb - lib/distribution/bivariatenormal/statistics2.rb - lib/distribution/chisquare.rb - lib/distribution/chisquare/gsl.rb - lib/distribution/chisquare/java.rb - lib/distribution/chisquare/ruby.rb - lib/distribution/chisquare/statistics2.rb - lib/distribution/exponential.rb - lib/distribution/exponential/gsl.rb - lib/distribution/exponential/ruby.rb - lib/distribution/f.rb - lib/distribution/f/gsl.rb - lib/distribution/f/java.rb - lib/distribution/f/ruby.rb - lib/distribution/f/statistics2.rb - lib/distribution/gamma.rb - lib/distribution/gamma/gsl.rb - lib/distribution/gamma/java.rb - lib/distribution/gamma/ruby.rb - lib/distribution/hypergeometric.rb - lib/distribution/hypergeometric/gsl.rb - lib/distribution/hypergeometric/java.rb - lib/distribution/hypergeometric/ruby.rb - lib/distribution/logistic.rb - lib/distribution/logistic/ruby.rb - lib/distribution/lognormal.rb - lib/distribution/lognormal/gsl.rb - lib/distribution/lognormal/ruby.rb - lib/distribution/math_extension.rb - lib/distribution/math_extension/chebyshev_series.rb - lib/distribution/math_extension/erfc.rb - lib/distribution/math_extension/exponential_integral.rb - lib/distribution/math_extension/gammastar.rb - lib/distribution/math_extension/gsl_utilities.rb - lib/distribution/math_extension/incomplete_beta.rb - lib/distribution/math_extension/incomplete_gamma.rb - lib/distribution/math_extension/log_utilities.rb - lib/distribution/normal.rb - lib/distribution/normal/gsl.rb - lib/distribution/normal/java.rb - lib/distribution/normal/ruby.rb - lib/distribution/normal/statistics2.rb - lib/distribution/normalmultivariate.rb - lib/distribution/poisson.rb - lib/distribution/poisson/gsl.rb - lib/distribution/poisson/java.rb - lib/distribution/poisson/ruby.rb - lib/distribution/t.rb - lib/distribution/t/gsl.rb - lib/distribution/t/java.rb - lib/distribution/t/ruby.rb - lib/distribution/t/statistics2.rb - lib/distribution/version.rb - lib/distribution/weibull.rb - lib/distribution/weibull/gsl.rb - lib/distribution/weibull/ruby.rb - spec/beta_spec.rb - spec/binomial_spec.rb - spec/bivariatenormal_spec.rb - spec/chisquare_spec.rb - spec/distribution_spec.rb - spec/exponential_spec.rb - spec/f_spec.rb - spec/gamma_spec.rb - spec/hypergeometric_spec.rb - spec/logistic_spec.rb - spec/lognormal_spec.rb - spec/math_extension_spec.rb - spec/normal_spec.rb - spec/poisson_spec.rb - spec/shorthand_spec.rb - spec/spec.opts - spec/spec_helper.rb - spec/t_spec.rb - spec/weibull_spec.rb - vendor/java/commons-math-2.2.jar homepage: https://github.com/sciruby/distribution licenses: [] metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.4.5 signing_key: specification_version: 4 summary: Distribution test_files: [] distribution-0.7.3/distribution.gemspec0000644000004100000410000000134012540356202020351 0ustar www-datawww-data$LOAD_PATH.unshift File.expand_path('../lib', __FILE__) require 'date' require 'distribution/version' Gem::Specification.new do |s| s.name = "distribution" s.version = Distribution::VERSION s.date = Date.today.to_s s.homepage = "https://github.com/sciruby/distribution" s.authors = ['Claudio Bustos'] s.email = ['clbustos@gmail.com'] s.platform = Gem::Platform::RUBY s.summary = "Distribution" s.description = "Distribution" s.files = `git ls-files`.split("\n") s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact s.require_path = 'lib' s.add_development_dependency 'bundler' s.add_development_dependency 'rake' s.add_development_dependency "rspec", '~> 3.2' end distribution-0.7.3/.gitignore0000644000004100000410000000006512540356202016260 0ustar www-datawww-data*~ *.rbc doc/* pkg/* coverage Gemfile.lock .autotest distribution-0.7.3/README.md0000644000004100000410000000515712540356202015556 0ustar www-datawww-data# [Distribution](https://github.com/sciruby/distribution) [![Build Status](https://travis-ci.org/SciRuby/distribution.svg?branch=master)](https://travis-ci.org/SciRuby/distribution) [![Code Climate](https://codeclimate.com/github/SciRuby/distribution/badges/gpa.svg)](https://codeclimate.com/github/SciRuby/distribution) ## Installation ``` $ gem install distribution ``` If you have GSL installed and want to speed things up, install `rb-gsl`: ```bash $ gem install rb-gsl ``` ## Description Statistical Distributions library. Includes Normal univariate and bivariate, T, F, Chi Square, Binomial, Hypergeometric, Exponential, Poisson, Beta, LogNormal and Gamma. Uses Ruby by default and C (statistics2/GSL) or Java extensions where available. Includes code from statistics2 on Normal, T, F and Chi Square ruby code [http://blade.nagaokaut.ac.jp/~sinara/ruby/math/statistics2] ## Synopsis * Returns Gaussian PDF for x ``` pdf=Distribution::Normal.pdf(x) ``` * Returns Gaussian CDF for x ``` cdf=Distribution::Normal.cdf(x) ``` * Returns inverse CDF (or p-value) for x ``` pv=Distribution::Normal.p_value(x) ``` ## Developers ``` $ git clone https://github.com/SciRuby/distribution.git ``` If you want to provide a new distribution, run `lib/distribution`: ``` $ distribution --new your_distribution ``` This should create the main distribution file, the directory with Ruby and GSL engines and specs on the spec/ directory. ## API Structure Distribution::.(cdf|pdf|p_value|rng) On discrete distributions, exact Ruby implementations of pdf, cdf and p_value could be provided, using ``` Distribution::.exact_(cdf|pdf|p_value) ``` module Distribution::Shorthand provides (you guess?) shortands method to call all methods ``` _(cdf|pdf|p|r) ``` On discrete distributions, exact cdf, pdf and p_value are ``` _(ecdf|epdf|ep) ``` Shortnames for distributions: * Normal: norm * Bivariate Normal: bnor * T: tdist * F: fdist * Chi Square: chisq * Binomial: bino * Hypergeometric: hypg * Exponential: expo * Poisson: pois * Beta: beta * Gamma: gamma * LogNormal: lognormal ### API Structure Example ``` Distribution::T.cdf ``` could be called after including Distribution::Shorthand ``` tdist_cdf ``` ## Features * Very fast ruby 1.8.7/1.9.+ implementation, with improved method to calculate factorials and others common functions * All methods tested on several ranges. See spec/ ## Issues * On JRuby and Rubinius, BivariateNormal returns incorrect pdf For current issues see the [issue tracker pages](https://github.com/sciruby/distribution/issues).