long-decimal 1.00.01 → 1.00.02

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a9b2ae9e4c8f0f4af956ca3603f351f2c45ecef1
4
+ data.tar.gz: b0d237ee8813f6e5f2ac6d458b0f22a5afc3b9c4
5
+ SHA512:
6
+ metadata.gz: 40718a7b4ac4011aee592fd16516fe79ea39e1aaa585113b0220463057064ef14f7f934071e45313014427121862297fde386726bad73d6525ee530353b1ddd6
7
+ data.tar.gz: 4ce22512fcba5dc1b57bd9dc389a269b52046f1d6e20ca134a5cc57aed34303ee9d5248249d84ce36d8e529549cad86b318f0d7eb6f2c3096ab0fc7ace9b58a9
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Copyright � 2006-2012 Karl Brodowsky
2
+ by Karl Brodowsky (IT Sky Consulting GmbH) 2006-2012
3
+ http://www.it-sky-consulting.com/
4
+
5
+ It is free software; you can use it, modify it and redistribute under the terms of either
6
+ Ruby's license or LGPL.
7
+ Find copies of these licenses on http://www.gnu.org/ or http://www.ruby-lang.org/
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
10
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
12
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
13
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
14
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
15
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README CHANGED
@@ -1,25 +1,49 @@
1
1
  Version
2
2
  -------
3
3
 
4
- This version ($Name: RELEASE_1_00_01 $) is similar to the previous beta-0.02.01
4
+ This version (1.00.02) is fixing bugs from version 1.00.01.
5
+ It also can be considered as a release candidate from the upcoming
6
+ version 1.01.00, adding new features.
5
7
 
6
8
  Improvements over the previous version:
7
9
 
8
- - better rubydoc
9
-
10
- All this functionality did not show any bugs during intensive
10
+ - migration from CVS (rubyforge) to GIT (github)
11
+ - bug fixed with frozen string attempted to be changed when parsing a string for a long-decimal number.
12
+ - removed some code duplication between rounding of LongDecimal, LongDecimalQuot and rounding of Integers to remainder set.
13
+ - added more rounding modes based on geometric, harmonic, quadratic and cubic mean
14
+ - fixed calculation of powers in such a way that it fails yielding a reasonably accurate result less often. Cases that are sensitive are powers with a base that is close to 1 (for example off by 1e-35) with an exponent that is huge (for example like 1e20). With "reasonable" values power of a LongDecimal by a LongDecimal works quite well.
15
+ - added functions to calculate arithmetic, harmonic, quadratic, cubic, geometric, arithmetic-geometric and harmonic-geometric means.
16
+ - added functions to round summand in such a way that their sum is the rounded value of the sum of the unrounded values (experimental)
17
+ - moved power, log10, log2 etc. from long-decimal-extra.rb to long-decimal.rb
18
+ - added more unit tests
19
+
20
+ Work to do for 1.01.00:
21
+ - go through functions that are working with rounding modes as parameter (like transcendental functions, sqrt, cbrt etc.) to ensure that they work properly with all new rounding modes
22
+ - improve algorithm for rounding with sum constraint
23
+ - go through unit tests to see they are covering all rounding modes
24
+ - add unit tests for rounding with sum constraint
25
+ - rubydoc-documentation
26
+ - external documentation
27
+
28
+ Work to do for 1.02.00 (or 2.00.00):
29
+ - add the following transcendental functions: sin, cos, tan, cot, sec, csc, sinh, cosh, tanh, coth, sech, csch, asin, acos, atan, atan2, acot, asec, acsc, asinh, acosh, atanh, acoth, asech, acsch
30
+ - documentation
31
+ - external documentation
32
+ - interoperability with flt
33
+
34
+ The existing functionality did not show any bugs during intensive
11
35
  testing, so it could be assumed that the whole library is good for
12
- for production/stable.
36
+ for production/stable. The library is used for productive software by the author.
13
37
 
14
- This software development effort is hosted on RubyForge (
15
- http://rubyforge.org/ ) under the project name "long-decimal", to be
16
- found directly with http://rubyforge.org/projects/long-decimal/ . So
17
- you should feel encouraged to look if there is a newer version, when
38
+ This software development effort is hosted on GitHub ( https://github.com/ )
39
+ under the project name "long-decimal", to be
40
+ found directly with http://rubyforge.org/projects/long-decimal/
41
+ So you should feel encouraged to look if there is a newer version, when
18
42
  you install long-decimal.
19
43
 
20
- This version is an beta-version.
44
+ This version is an production stable version.
21
45
  Operations +, -, *, / and sqrt should be working properly
22
- and could probably justify calling this release production/stable.
46
+ and justify calling this release production/stable.
23
47
  Even log and exp should be fine. log, log2, log10 and exp have been
24
48
  tested for several million random values and the current version
25
49
  should cover all of these correctly. But it is still possible, that
@@ -53,7 +77,6 @@ after which the decimal point is inserted again.
53
77
  Usage
54
78
  -----
55
79
 
56
- require 'rubygems'
57
80
  require 'long-decimal'
58
81
 
59
82
  (then use it.)
@@ -106,36 +129,14 @@ ruby test/testrandpower.rb
106
129
  These random tests require installation of the ruby-library
107
130
  crypt-isaac for its random numbers, which works well with Linux or
108
131
  Windows in combination with Cygwin. Installation of crypt-isaac is
109
- slightly special. You have to download the gem, then install it using
110
- gem install:
111
-
112
- $ cd /tmp
113
- $ wget http://rubyforge.org/frs/download.php/6461/crypt-isaac_0.9.1.gem
114
- $ su -l
115
- # cd /tmp
116
- # gem install crypt-isaac
117
- (you may need to adjust the URL for downloading the gem)
118
-
119
- .... and then go into the directory, where the gem is
120
- (/usr/local/lib/ruby/gems/1.8/gems/Crypt::ISAAC-0.9.1/ or
121
- /usr/lib/ruby/gems/1.8/gems/Crypt::ISAAC-0.9.1/ or ...)
122
-
123
- # cd /usr/local/lib/ruby/gems/1.8/gems/Crypt::ISAAC-0.9.1/
124
- # ruby setup.rb install
125
- # exit
126
- $
132
+ required for the random tests.
127
133
 
128
134
  If you actually want to run tests for long-decimal or
129
- long-decimal-extra and find an error with it, please report it with
130
- the lines of output revealing the bug on
131
- http://rubyforge.org/projects/long-decimal/ -> tracker
135
+ long-decimal-extra and find an error with it, please report it.
132
136
 
133
137
  Install
134
138
  -------
135
139
 
136
- (REMARK: installation has only been successfully tested on Linux with
137
- ruby 1.8.7 and on Windows 2000 with Cygwin and on Windows 2000 with
138
- native ruby)
139
140
 
140
141
  1. Using ruby-gems (preferred)
141
142
  - open a shell window
@@ -154,7 +155,6 @@ native ruby)
154
155
 
155
156
  - Usage from your ruby-programs:
156
157
 
157
- require "rubygems"
158
158
  require "long-decimal"
159
159
 
160
160
  - documentation will be found in HTML-format in the directory
@@ -229,17 +229,17 @@ a sophisticated library like this additional external documentation
229
229
  should be provided in the long term. Currently this does not exist at
230
230
  all.
231
231
 
232
- Please report any bugs you come across on
233
- http://rubyforge.org/projects/long-decimal -> Tracker.
232
+ Please report any bugs you come across.
234
233
 
235
- The status of long-decimal is considered to be beta.
234
+ The status of long-decimal is considered to be production stable.
236
235
 
237
236
  License
238
237
  -------
239
238
 
240
239
  Ruby's license or LGPL
241
240
  Find copies of these licenses on http://www.gnu.org/ or http://www.ruby-lang.org/
242
- � Karl Brodowsky (IT Sky Consulting GmbH) 2006-2009
241
+ � Karl Brodowsky (IT Sky Consulting GmbH) 2006-2014
242
+ http://www.it-sky-consulting.com/
243
243
 
244
244
  Warranty
245
245
  --------
data/Rakefile CHANGED
@@ -1,89 +1,35 @@
1
+ # encoding: utf-8
2
+
1
3
  #
2
4
  # Rakefile for long-decimal project
3
5
  #
4
6
  # (C) Karl Brodowsky (IT Sky Consulting GmbH) 2006-2009
5
7
  #
6
8
  # CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/Rakefile,v 1.4 2009/04/15 19:29:37 bk1 Exp $
7
- # CVS-Label: $Name: RELEASE_1_00_01 $
9
+ # CVS-Label: $Name: $
8
10
  # Author: $Author: bk1 $ (Karl Brodowsky)
9
11
  #
10
12
 
11
- require 'rake/gempackagetask'
12
- require 'rbconfig'
13
-
14
- include Config
15
-
16
- PKG_NAME = 'long-decimal'
17
- PKG_VERSION = File.read('VERSION').chomp
18
- PKG_FILES = Dir.glob("**/*").delete_if { |item|
19
- item.include?("CVS") || item.include?("RCS") || item.include?("pkg") || item.include?("~") || item.include?("#")
20
- }
13
+ require "bundler/gem_tasks"
14
+ require 'rubygems'
15
+ require 'bundler'
21
16
 
22
- desc "Creating VERSION file"
23
- task :version do
24
- ruby 'version.rb lib/long-decimal.rb > VERSION'
17
+ require 'rake/testtask'
18
+ Rake::TestTask.new(:test) do |test|
19
+ test.libs << 'lib' << 'test'
20
+ test.pattern = 'test/testlongdecimal.rb'
21
+ test.verbose = true
25
22
  end
26
23
 
27
- desc "Installing library"
28
- task :install do
29
- ruby 'install.rb'
30
- end
31
-
32
- desc "Creating documentation"
33
- task :doc do
34
- ruby 'make_doc.rb'
35
- end
36
-
37
- desc "Testing library"
38
- task :test do
39
- ruby %{test/testlongdecimal.rb}
40
- end
41
-
42
- spec = Gem::Specification.new do |s|
43
-
44
- #### Basic information.
45
-
46
- s.name = 'long-decimal'
47
- s.version = PKG_VERSION
48
- s.summary = 'LongDecimal for numbers with fixed point'
49
- s.description = ""
50
-
51
- #### Dependencies and requirements.
52
-
53
- s.files = PKG_FILES
54
-
55
- #### C code extensions.
56
-
57
- #### Load-time details: library and application (you will need one or both).
58
-
59
- s.require_path = 'lib' # 'lib' # Use these for libraries.
60
- s.autorequire = 'long-decimal'
61
-
62
- #s.bindir = "bin" # Use these for applications.
63
- #s.executables = ["bla.rb"]
64
- #s.default_executable = "bla.rb"
65
-
66
- #### Documentation and testing.
67
-
68
- s.has_rdoc = true
69
- #s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a
70
- #s.rdoc_options <<
71
- # '--title' << 'Rake -- Ruby Make' <<
72
- # '--main' << 'README' <<
73
- # '--line-numbers'
74
- s.test_files << 'test/testlongdecimal.rb'
75
-
76
- #### Author and project details.
77
-
78
- s.author = "Karl Brodowsky"
79
- s.email = "http://www.velofahren.de/mail.html"
80
- s.homepage = "http://long-decimal.rubyforge.org/"
81
- s.rubyforge_project = "long-decimal"
82
- end
24
+ require 'rdoc/task'
25
+ Rake::RDocTask.new do |rdoc|
26
+ version = File.exist?('VERSION') ? File.read('VERSION').strip : LongDecimalSupport::VERSION
83
27
 
84
- Rake::GemPackageTask.new(spec) do |pkg|
85
- pkg.need_tar = true
86
- pkg.package_files += PKG_FILES
28
+ rdoc.rdoc_dir = 'rdoc'
29
+ rdoc.title = "long-decimal #{version}"
30
+ rdoc.main = "README"
31
+ rdoc.rdoc_files.include('README*')
32
+ rdoc.rdoc_files.include('lib/*.rb')
87
33
  end
88
34
 
89
35
  # end of file Rakefile
@@ -3,8 +3,8 @@
3
3
  #
4
4
  # (C) Karl Brodowsky (IT Sky Consulting GmbH) 2006-2009
5
5
  #
6
- # CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/long-decimal-extra.rb,v 1.26 2011/01/16 18:12:50 bk1 Exp $
7
- # CVS-Label: $Name: RELEASE_1_00_00 $
6
+ # CVS-ID: $Header: /var/cvs/long-decimal/long-decimal/lib/long-decimal-extra.rb,v 1.29 2011/02/04 23:17:21 bk1 Exp $
7
+ # CVS-Label: $Name: $
8
8
  # Author: $Author: bk1 $ (Karl Brodowsky)
9
9
  #
10
10
  require "complex"
@@ -23,6 +23,7 @@ class LongDecimal
23
23
  @timer[i] = Time.now
24
24
  end
25
25
 
26
+ # helper method for performance measurements
26
27
  def te(i)
27
28
  @@tt ||= []
28
29
  @@tt[i] ||= 0
@@ -32,6 +33,7 @@ class LongDecimal
32
33
  @@tc[i] += 1
33
34
  end
34
35
 
36
+ # helper method for performance measurements
35
37
  def tt(i)
36
38
  @@tt ||= []
37
39
  @@tt[i] ||= 0
@@ -318,14 +320,12 @@ class LongDecimal
318
320
  elsif dividend < divisor
319
321
  # self is between 0 and 1 and dividend > LongMath::MAX_FLOATABLE
320
322
  # return LongDecimal(dividend.div(LongMath.npower10(digits)), scale -digits).to_f
321
- # puts "via s (1): #{self.inspect}"
322
323
  return self.to_s.to_f
323
324
  else
324
325
  q = dividend.abs / divisor
325
326
  if (q.abs > 1000000000000000000000)
326
327
  return q.to_f
327
328
  else
328
- # puts "via s (2): #{self.inspect}"
329
329
  return self.to_s.to_f
330
330
  end
331
331
  end
@@ -342,343 +342,9 @@ end
342
342
  # LongDecimal instead of Float.
343
343
  #
344
344
  module LongMath
345
-
346
- #
347
- # calc the base-2-exponential function of x to the given precision as
348
- # LongDecimal. Only supports values of x such that the result still
349
- # fits into a float (x <= 709). This limitation is somewhat
350
- # arbitrary, but it is enforced in order to avoid producing numbers
351
- # with the exponential function that exceed the memory.
352
- #
353
- def LongMath.exp2(x, prec, mode = LongMath.standard_mode) # down?
354
- LongMath.power(2, x, prec, mode)
355
- end
356
-
357
- #
358
- # calc the base-10-exponential function of x to the given precision as
359
- # LongDecimal. Only supports values of x such that the result still
360
- # fits into a float (x <= 709). This limitation is somewhat
361
- # arbitrary, but it is enforced in order to avoid producing numbers
362
- # with the exponential function that exceed the memory.
363
- #
364
- def LongMath.exp10(x, prec, mode = LongMath.standard_mode) # down?
365
- LongMath.power(10, x, prec, mode)
366
- end
367
-
368
- #
369
- # calculate the base 10 logarithm of x to the given precision as
370
- # LongDecimal.
371
- #
372
- def LongMath.log10(x, prec, mode = LongMath.standard_mode) # down?
373
-
374
- prec = check_is_prec(prec, "prec")
375
- check_is_mode(mode, "mode")
376
- iprec = prec + 6
377
- unless (x.kind_of? LongDecimal)
378
- x = x.to_ld(iprec, mode)
379
- end
380
- if (x.one?) then
381
- return LongDecimal.zero!(prec)
382
- end
383
-
384
- id = x.int_digits10
385
- xx = x.move_point_left(id)
386
- lnxx = log_internal(xx, iprec, mode)
387
- ln10 = log_internal(10, iprec, mode)
388
- y = id + (lnxx / ln10).round_to_scale(prec, mode)
389
- return y
390
- end
391
-
392
- #
393
- # calculate the base 2 logarithm of x to the given precision as
394
- # LongDecimal.
395
- #
396
- def LongMath.log2(x, prec, mode = LongMath.standard_mode)
397
-
398
- prec = check_is_prec(prec, "prec")
399
- check_is_mode(mode, "mode")
400
- iprec = prec + 6
401
- unless (x.kind_of? LongDecimal)
402
- x = x.to_ld(iprec, mode)
403
- end
404
- if (x.one?) then
405
- return LongDecimal.zero!(prec)
406
- end
407
- id = x.int_digits2
408
- xx = (x / (1 << id)).round_to_scale(x.scale+id)
409
- lnxx = log_internal(xx, iprec, mode)
410
- ln2 = log_internal(2.to_ld, iprec, mode)
411
- y = id + (lnxx / ln2).round_to_scale(prec, mode)
412
- return y
413
- end
414
-
415
-
416
- #
417
- # calculate the natural logarithm of x as floating point number,
418
- # even if x cannot reasonably be expressed as Float.
419
- #
420
- def LongMath.log_f(x)
421
- raise TypeError, "x=#{x.inspect} must not be positive" unless x > 0
422
- unless x.kind_of? LongDecimal
423
- x = x.to_ld(18, LongDecimalRoundingMode::ROUND_HALF_UP)
424
- end
425
- y = 0
426
- while (x > LongMath::MAX_FLOATABLE)
427
- y += LOG_1E100
428
- x = x.move_point_left(100)
429
- end
430
- while (x < LongMath::MIN_FLOATABLE)
431
- y -= LOG_1E100
432
- x = x.move_point_right(100)
433
- end
434
- x_f = x.to_f
435
- y += Math.log(x_f)
436
- y
437
- end
438
345
 
439
346
  private
440
347
 
441
- LOG_1E100 = Math.log(1e100)
442
-
443
- #
444
- # internal helper method for calculating the internal precision for power
445
- #
446
- def LongMath.calc_iprec_for_power(x, y, prec)
447
-
448
- logx_f = LongMath.log_f(x.abs)
449
-
450
- y_f = nil
451
- if (y.abs <= LongMath::MAX_FLOATABLE) then
452
- y_f = y.to_f
453
- else
454
- y_f = y.round_to_scale(18, LongMath::ROUND_UP)
455
- end
456
-
457
- logx_y_f = logx_f * y_f
458
-
459
- if (logx_y_f.abs > LongMath::MAX_FLOATABLE) then
460
- raise ArgumentError, "power would be way too big: y*log(x)=#{logx_y_f}";
461
- end
462
- logx_y_f = logx_y_f.to_f unless logx_y_f.kind_of? Float
463
-
464
- iprec_x = calc_iprec_for_exp(logx_y_f.abs.ceil, prec, logx_y_f < 0)
465
- iprec_y = iprec_x
466
- iprec = iprec_x + 2
467
- if (logx_f < 0)
468
- iprec_x -= (logx_f/LOG10).round
469
- end
470
- if (y_f.abs < 1)
471
- logy_f = LongMath.log_f(y.abs)
472
- iprec_y -= (logy_f/LOG10).round
473
- end
474
- [ iprec, iprec_x, iprec_y, logx_y_f ]
475
-
476
- end
477
-
478
- public
479
-
480
- #
481
- # calc the power of x with exponent y to the given precision as
482
- # LongDecimal. Only supports values of y such that the result still
483
- # fits into a float
484
- #
485
- def LongMath.power(x, y, prec, mode = LongMath.standard_mode)
486
-
487
- raise TypeError, "x=#{x} must be numeric" unless x.kind_of? Numeric
488
- raise TypeError, "y=#{y} must be numeric" unless y.kind_of? Numeric
489
- raise TypeError, "x=#{x.inspect} must not be greater #{MAX_FLOATABLE}" unless x.abs <= MAX_FLOATABLE
490
- raise TypeError, "y=#{y.inspect} must not be greater #{MAX_FLOATABLE}" unless y.abs <= MAX_FLOATABLE
491
- raise TypeError, "y=#{y.inspect} must not be negative if base is zero}" if y < 0 && x.zero?
492
- raise TypeError, "x=#{x.inspect} must not negative" unless x >= 0
493
- prec = check_is_prec(prec, "prec")
494
- check_is_mode(mode, "mode")
495
- puts "LongMath.power(x=#{x} y=#{y} prec=#{prec} mode=#{mode})"
496
-
497
- # handle the special cases where base or exponent are 0 or 1 explicitely
498
- if y.zero? then
499
- return LongDecimal.one!(prec)
500
- elsif x.zero? then
501
- return LongDecimal.zero!(prec)
502
- elsif y.one? then
503
- return x.to_ld(prec, mode)
504
- elsif x.one? then
505
- return LongDecimal.one!(prec)
506
- end
507
-
508
- # could be result with our precision
509
- # x ** y <= 10**-s/2 <=> y * log(x) <= -s log(10) - log(2)
510
-
511
- iprec, iprec_x, iprec_y, logx_y_f = calc_iprec_for_power(x, y, prec)
512
- puts "x=#{x} y=#{y} prec=#{prec} iprec=#{iprec} iprec_x=#{iprec_x} iprec_y=#{iprec_y} logx_y_f=#{logx_y_f}: checking x < 1 && y > 0 || x > 1 && y < 0=#{x < 1 && y > 0 || x > 1 && y < 0}"
513
- $stdout.flush
514
- if (x < 1 && y > 0 || x > 1 && y < 0) then
515
- puts "checking if zero logx_y_f=#{logx_y_f} <= #{- prec * LOG10 - LOG2}"
516
- if (logx_y_f <= - prec * LOG10 - LOG2) then
517
- return LongDecimal.zero!(prec)
518
- end
519
- end
520
-
521
- unless (x.kind_of? LongDecimalBase) || (x.kind_of? Integer)
522
- x = x.to_ld(iprec_x, mode)
523
- end
524
- unless (y.kind_of? LongDecimalBase) || (y.kind_of? Integer)
525
- y = y.to_ld(iprec_y, mode)
526
- end
527
-
528
- # try shortcut if exponent is an integer
529
- if (y.kind_of? LongDecimalBase) && y.is_int? then
530
- y = y.to_i
531
- end
532
- unless (y.kind_of? Integer)
533
- y2 = y*2
534
- if (y2.kind_of? LongDecimalBase) && y2.is_int? then
535
- y2 = y2.to_i
536
- end
537
- if (y2.kind_of? Integer)
538
- x = LongMath.sqrt(x, 2*iprec_x, mode)
539
- y = y2
540
- end
541
- end
542
- if (y.kind_of? Integer)
543
- unless x.kind_of? LongDecimal
544
- x = x.to_ld(iprec_x)
545
- end
546
- z = LongMath.ipower(x, y, 2*iprec, mode)
547
- return z.to_ld(prec, mode)
548
- end
549
-
550
- # it can be assumed that the exponent is not an integer, so it should
551
- # be converted into LongDecimal
552
- unless (y.kind_of? LongDecimal)
553
- y = y.to_ld(iprec_y, mode)
554
- end
555
-
556
- # if x < 1 && y < 0 then
557
- # working with x < 1 should be improved, less precision needed
558
- if x < 1 then
559
- # since we do not allow x < 0 and we have handled x = 0 already,
560
- # we can be sure that x is no integer, so it has been converted
561
- # if necessary to LongDecimalBase
562
- y = -y
563
- x = (1/x).round_to_scale(iprec_x*2, mode)
564
- iprec, iprec_x, iprec_y, logx_y_f = calc_iprec_for_power(x, y, prec)
565
- puts "x=#{x} y=#{y} prec=#{prec} iprec=#{iprec} iprec_x=#{iprec_x} iprec_y=#{iprec_y} logx_y_f=#{logx_y_f}: checking x < 1 && y > 0 || x > 1 && y < 0=#{x < 1 && y > 0 || x > 1 && y < 0}"
566
- $stdout.flush
567
- if (x < 1 && y > 0 || x > 1 && y < 0) then
568
- puts "checking if zero logx_y_f=#{logx_y_f} <= #{- prec * LOG10 - LOG2}"
569
- if (logx_y_f <= - prec * LOG10 - LOG2) then
570
- return LongDecimal.zero!(prec)
571
- end
572
- end
573
- end
574
-
575
- # exponent is split in two parts, an integer part and a
576
- # LongDecimal with absolute value <= 0.5
577
- y0 = y.round_to_scale(0, LongMath.standard_imode).to_i
578
- x0 = x
579
- point_shift = 0
580
- puts "x0=#{x0} y0=#{y0}"
581
- while x0 > LongMath::MAX_FLOATABLE
582
- x0 = x0.move_point_left(100)
583
- point_shift += 100
584
- end
585
- iprec2 = 2 * (iprec + point_shift)
586
- iprec3 = [ iprec2, LongMath.prec_limit() - 24 ].min
587
- puts "x0=#{x0} y0=#{y0} point_shift=#{point_shift} iprec=#{iprec} iprec2=#{iprec2} iprec3=#{iprec3}"
588
- z0 = LongMath.ipower(x0, y0, iprec3, mode)
589
- if (point_shift > 0)
590
- unless z0.kind_of? LongDecimal
591
- z0 = z0.to_ld(2*(iprec + point_shift))
592
- end
593
- z0 = z0.move_point_right(point_shift * y0)
594
- end
595
- y1 = y - y0
596
- prec_extra = 0
597
- if (y0 > 0)
598
- prec_extra = (y0*Math.log10(x.to_f).abs).ceil
599
- end
600
- # z1 = LongMath.power_internal(x, y1, prec+prec_extra , mode)
601
- z1 = LongMath.power_internal(x, y1, prec+prec_extra + 4, mode)
602
- z = z0 * z1
603
- # puts("x=#{x} y=#{y} z=#{z} y not int")
604
- return z.to_ld(prec, mode)
605
- end
606
-
607
- #
608
- # internal functionality to calculate the y-th power of x assuming
609
- # that y is an integer
610
- # prec is a hint on how much internal precision is needed at most
611
- # final rounding is left to the caller
612
- #
613
- def LongMath.ipower(x, y, prec, mode)
614
-
615
- t0 = Time.now
616
- raise TypeError, "base x=#{x} must be numeric" unless x.kind_of? Numeric
617
- raise TypeError, "exponent y=#{y} must be integer" unless y.kind_of? Integer
618
- raise TypeError, "base x=#{x.inspect} must not be greater MAX_FLOATABLE=#{MAX_FLOATABLE}" unless x.abs <= MAX_FLOATABLE
619
- raise TypeError, "exponent y=#{y.inspect} must not be greater MAX_FLOATABLE=#{MAX_FLOATABLE}" unless y.abs <= MAX_FLOATABLE
620
- prec = check_is_prec(prec, "prec")
621
- check_is_mode(mode, "mode")
622
- puts "LongMath.ipower(x=#{x} y=#{y} prec=#{prec} mode=#{mode})"
623
-
624
- if (y.zero?)
625
- return 1
626
- elsif ! (x.kind_of? LongDecimalBase) || x.scale * y.abs <= prec
627
- puts "x=#{x} y=#{y} using **"
628
- return x ** y
629
- elsif (y < 0)
630
- l = Math.log10(x.abs.to_f)
631
- if (l > 0)
632
- prec += (2*l).ceil
633
- end
634
- # return (1/LongMath.ipower(x, -y, prec + 2, mode)).round_to_scale(prec, mode)
635
- xi = 1/x
636
- puts "x=#{x} y=#{y} prec=#{prec} using (1/x)**y xi=#{xi}"
637
- xr = xi.round_to_scale(prec + 6, mode)
638
- return LongMath.ipower(xr, -y, prec, mode)
639
- else
640
- # y > 0
641
- puts "x=#{x} y=#{y} regular"
642
- cnt = 0
643
- z = x
644
- y0 = y
645
- x0 = x
646
- while true do
647
-
648
- cnt++
649
- y -= 1
650
- if (y.zero?)
651
- break
652
- end
653
- while (y & 0x01) == 0 do
654
-
655
- cnt++
656
- y = y >> 1
657
- x = (x*x)
658
- if (x.kind_of? LongDecimalBase)
659
- x = x.round_to_scale(prec+4, mode)
660
- end
661
- if (cnt > 1000)
662
- puts("ipower x=#{x} y=#{y} cnt=#{cnt} z=#{z} t=#{Time.now - t0}")
663
- cnt = 0
664
- end
665
-
666
- end
667
- z *= x
668
- if (z.kind_of? LongDecimalBase)
669
- z = z.round_to_scale(prec+3, mode)
670
- if (z.zero?)
671
- break
672
- end
673
- end
674
- end
675
- puts "z=#{z} rounding prec=#{prec}"
676
- z = z.round_to_scale(prec, mode)
677
- puts "rounded -> z=#{z}"
678
- return z
679
- end
680
- end
681
-
682
348
  #
683
349
  # internal functionality to calculate the y-th power of x assuming
684
350
  # that y is an integer
@@ -741,340 +407,7 @@ module LongMath
741
407
  end
742
408
  end
743
409
 
744
- #
745
- # internal functionality of exp. exposes some more parameters, that
746
- # should usually be set to defaut values, in order to allow better testing.
747
- # do not actually call this method unless you are testing exp.
748
- # create a bug report, if the default settings for the parameters do
749
- # not work correctly
750
- #
751
- def LongMath.power_internal(x, y, prec = nil, final_mode = LongMath.standard_mode, iprec = nil, mode = LongMath.standard_imode)
752
-
753
- if (prec.nil?) then
754
- if (x.kind_of? LongDecimalBase) && (y.kind_of? LongDecimalBase)
755
- prec = [x.scale, y.scale].max
756
- elsif (x.kind_of? LongDecimalBase)
757
- prec = x.scale
758
- elsif (y.kind_of? LongDecimalBase)
759
- prec = y.scale
760
- else
761
- raise ArgumentError, "precision must be supplied either as precision of x=#{x} or explicitely"
762
- end
763
- end
764
- prec = check_is_prec(prec, "prec")
765
-
766
- if (final_mode.nil?)
767
- final_mode = LongMath.standard_mode
768
- end
769
- check_is_mode(final_mode, "final_mode")
770
- check_is_mode(mode, "mode")
771
-
772
- if y.zero? then
773
- return LongDecimal.one!(prec)
774
- elsif x.zero? then
775
- return LongDecimal.zero!(prec)
776
- end
777
-
778
- if (iprec.nil?) then
779
- iprec, iprec_x, iprec_y = calc_iprec_for_power(x, y, prec)
780
- end
781
- unless (x.kind_of? LongDecimal)
782
- # x = x.to_ld(iprec, mode)
783
- x = x.to_ld(iprec_x, mode)
784
- end
785
- unless (y.kind_of? LongDecimal)
786
- # y = y.to_ld(iprec, mode)
787
- y = y.to_ld(iprec_y, mode)
788
- end
789
-
790
- # logx = log(x, iprec, mode)
791
- logx = log(x, iprec + 20, mode)
792
- logx_y = logx*y
793
- # xy = exp_internal(logx_y, prec + 1, mode)
794
- # xy = exp_internal(logx_y, prec + 4, mode)
795
- xy = exp_internal(logx_y, prec + 3, mode)
796
- xy.round_to_scale(prec, final_mode)
797
-
798
- end # power_internal
799
-
800
- LOGARR = [ nil, \
801
- 0.0, \
802
- 1.0, \
803
- 1.58496250072116, \
804
- 2.0, \
805
- 2.32192809488736, \
806
- 2.58496250072116, \
807
- 2.8073549220576, \
808
- 3.0, \
809
- 3.16992500144231, \
810
- 3.32192809488736, \
811
- 3.4594316186373, \
812
- 3.58496250072116, \
813
- 3.70043971814109, \
814
- 3.8073549220576, \
815
- 3.90689059560852, \
816
- 4.0, \
817
- 4.08746284125034, \
818
- 4.16992500144231, \
819
- 4.24792751344359, \
820
- 4.32192809488736, \
821
- 4.39231742277876, \
822
- 4.4594316186373, \
823
- 4.52356195605701, \
824
- 4.58496250072116, \
825
- 4.64385618977472, \
826
- 4.70043971814109, \
827
- 4.75488750216347, \
828
- 4.8073549220576, \
829
- 4.85798099512757, \
830
- 4.90689059560852, \
831
- 4.95419631038688, \
832
- 5.0, \
833
- 5.04439411935845, \
834
- 5.08746284125034, \
835
- 5.12928301694497, \
836
- 5.16992500144231, \
837
- 5.20945336562895, \
838
- 5.24792751344359, \
839
- 5.28540221886225, \
840
- 5.32192809488736, \
841
- 5.35755200461808, \
842
- 5.39231742277876, \
843
- 5.4262647547021, \
844
- 5.4594316186373, \
845
- 5.49185309632967, \
846
- 5.52356195605701, \
847
- 5.55458885167764, \
848
- 5.58496250072116, \
849
- 5.61470984411521, \
850
- 5.64385618977472, \
851
- 5.6724253419715, \
852
- 5.70043971814109, \
853
- 5.7279204545632, \
854
- 5.75488750216347, \
855
- 5.78135971352466, \
856
- 5.8073549220576, \
857
- 5.83289001416474, \
858
- 5.85798099512757, \
859
- 5.88264304936184, \
860
- 5.90689059560852, \
861
- 5.93073733756289, \
862
- 5.95419631038688, \
863
- 5.97727992349992, \
864
- 6.0, \
865
- 6.02236781302845, \
866
- 6.04439411935845, \
867
- 6.06608919045777, \
868
- 6.08746284125034, \
869
- 6.10852445677817, \
870
- 6.12928301694497, \
871
- 6.14974711950468, \
872
- 6.16992500144231, \
873
- 6.18982455888002, \
874
- 6.20945336562895, \
875
- 6.22881869049588, \
876
- 6.24792751344359, \
877
- 6.2667865406949, \
878
- 6.28540221886225, \
879
- 6.3037807481771, \
880
- 6.32192809488736, \
881
- 6.33985000288463, \
882
- 6.35755200461808, \
883
- 6.37503943134693, \
884
- 6.39231742277876, \
885
- 6.4093909361377, \
886
- 6.4262647547021, \
887
- 6.44294349584873, \
888
- 6.4594316186373, \
889
- 6.4757334309664, \
890
- 6.49185309632967, \
891
- 6.5077946401987, \
892
- 6.52356195605701, \
893
- 6.53915881110803, \
894
- 6.55458885167764, \
895
- 6.56985560833095, \
896
- 6.58496250072116, \
897
- 6.59991284218713, \
898
- 6.61470984411521, \
899
- 6.62935662007961, \
900
- 6.64385618977473, \
901
- 6.6582114827518, \
902
- 6.6724253419715, \
903
- 6.68650052718322, \
904
- 6.70043971814109, \
905
- 6.71424551766612, \
906
- 6.7279204545632, \
907
- 6.74146698640115, \
908
- 6.75488750216347, \
909
- 6.76818432477693, \
910
- 6.78135971352466, \
911
- 6.79441586635011, \
912
- 6.8073549220576, \
913
- 6.82017896241519, \
914
- 6.83289001416474, \
915
- 6.84549005094438, \
916
- 6.85798099512757, \
917
- 6.8703647195834, \
918
- 6.88264304936184, \
919
- 6.89481776330794, \
920
- 6.90689059560852, \
921
- 6.9188632372746, \
922
- 6.93073733756289, \
923
- 6.94251450533924, \
924
- 6.95419631038688, \
925
- 6.96578428466209, \
926
- 6.97727992349992, \
927
- 6.98868468677217, \
928
- 7.0, \
929
- 7.01122725542325, \
930
- 7.02236781302845, \
931
- 7.03342300153745, \
932
- 7.04439411935845, \
933
- 7.05528243550119, \
934
- 7.06608919045777, \
935
- 7.07681559705083, \
936
- 7.08746284125034, \
937
- 7.09803208296053, \
938
- 7.10852445677817, \
939
- 7.11894107272351, \
940
- 7.12928301694497, \
941
- 7.13955135239879, \
942
- 7.14974711950468, \
943
- 7.15987133677839, \
944
- 7.16992500144231, \
945
- 7.17990909001493, \
946
- 7.18982455888002, \
947
- 7.19967234483636, \
948
- 7.20945336562895, \
949
- 7.21916852046216, \
950
- 7.22881869049588, \
951
- 7.23840473932508, \
952
- 7.24792751344359, \
953
- 7.25738784269265, \
954
- 7.2667865406949, \
955
- 7.27612440527424, \
956
- 7.28540221886225, \
957
- 7.29462074889163, \
958
- 7.3037807481771, \
959
- 7.31288295528436, \
960
- 7.32192809488736, \
961
- 7.33091687811462, \
962
- 7.33985000288462, \
963
- 7.34872815423108, \
964
- 7.35755200461808, \
965
- 7.36632221424582, \
966
- 7.37503943134693, \
967
- 7.38370429247405, \
968
- 7.39231742277876, \
969
- 7.40087943628218, \
970
- 7.4093909361377, \
971
- 7.4178525148859, \
972
- 7.4262647547021, \
973
- 7.43462822763673, \
974
- 7.44294349584873, \
975
- 7.45121111183233, \
976
- 7.4594316186373, \
977
- 7.467605550083, \
978
- 7.4757334309664, \
979
- 7.48381577726426, \
980
- 7.49185309632967, \
981
- 7.49984588708321, \
982
- 7.5077946401987, \
983
- 7.51569983828404, \
984
- 7.52356195605701, \
985
- 7.53138146051631, \
986
- 7.53915881110803, \
987
- 7.54689445988764, \
988
- 7.55458885167764, \
989
- 7.56224242422107, \
990
- 7.56985560833095, \
991
- 7.57742882803575, \
992
- 7.58496250072116, \
993
- 7.59245703726808, \
994
- 7.59991284218713, \
995
- 7.60733031374961, \
996
- 7.61470984411521, \
997
- 7.62205181945638, \
998
- 7.62935662007961, \
999
- 7.63662462054365, \
1000
- 7.64385618977472, \
1001
- 7.65105169117893, \
1002
- 7.6582114827518, \
1003
- 7.66533591718518, \
1004
- 7.6724253419715, \
1005
- 7.67948009950545, \
1006
- 7.68650052718322, \
1007
- 7.69348695749933, \
1008
- 7.70043971814109, \
1009
- 7.70735913208088, \
1010
- 7.71424551766612, \
1011
- 7.72109918870719, \
1012
- 7.7279204545632, \
1013
- 7.73470962022584, \
1014
- 7.74146698640115, \
1015
- 7.74819284958946, \
1016
- 7.75488750216347, \
1017
- 7.76155123244448, \
1018
- 7.76818432477693, \
1019
- 7.77478705960117, \
1020
- 7.78135971352466, \
1021
- 7.78790255939143, \
1022
- 7.79441586635011, \
1023
- 7.8008998999203, \
1024
- 7.8073549220576, \
1025
- 7.81378119121704, \
1026
- 7.82017896241519, \
1027
- 7.82654848729092, \
1028
- 7.83289001416474, \
1029
- 7.83920378809694, \
1030
- 7.84549005094438, \
1031
- 7.85174904141606, \
1032
- 7.85798099512757, \
1033
- 7.86418614465428, \
1034
- 7.8703647195834, \
1035
- 7.876516946565, \
1036
- 7.88264304936184, \
1037
- 7.88874324889826, \
1038
- 7.89481776330794, \
1039
- 7.90086680798075, \
1040
- 7.90689059560852, \
1041
- 7.91288933622996, \
1042
- 7.9188632372746, \
1043
- 7.92481250360578, \
1044
- 7.93073733756289, \
1045
- 7.93663793900257, \
1046
- 7.94251450533924, \
1047
- 7.94836723158468, \
1048
- 7.95419631038688, \
1049
- 7.96000193206808, \
1050
- 7.96578428466209, \
1051
- 7.97154355395077, \
1052
- 7.97727992349992, \
1053
- 7.98299357469431, \
1054
- 7.98868468677217, \
1055
- 7.99435343685886, \
1056
- 8.0 ]
1057
-
1058
- def LongMath.log2int(x)
1059
- unless x.kind_of? Integer
1060
- raise TypeError, "x=#{x.inspect} must be Integer"
1061
- end
1062
- if (x <= 0)
1063
- raise ArgumentError, "x=#{x} < 0"
1064
- end
1065
-
1066
- s = x.size
1067
- l = [ 8 * s - 36 , 0 ].max
1068
-
1069
- xx = x >> l
1070
- while xx >= 256
1071
- l += 1
1072
- xx = xx >> 1
1073
- end
1074
- yy = LOGARR[xx]
1075
- y = l + yy
1076
- y
1077
- end
410
+ public
1078
411
 
1079
412
  # alternative calculations of sqrt using newtons algorithm
1080
413
  def LongMath.sqrtn(x)