hpsqrt 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 44cd55553d14006a807f7f752e7a9ff5d72f3059da918af90c3a4b78d00bcfcb
4
+ data.tar.gz: 024a8bc0f8b197334342f78b6f91d761d2eb29a247c135c2b7f1ff45a39ce4c6
5
+ SHA512:
6
+ metadata.gz: dc828d520080593730770dee6ad5977209c6e37705551500942ccf7f5e09ef572e60f47d196c2d47fe37d50227f69b373a90a23e2ff58ea5c1b4fdb808856fa8
7
+ data.tar.gz: 55802d1412f4f89513578a0a8f5fc1da994873238f6d5efd6177d44dea8195f5cead352a62e5f882a874c9823a7f49a48d98c4a3bcccb021b89535e7b17f3f53
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.7.0
6
+ before_install: gem install bundler -v 2.1.0.pre.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in hpsqrt.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 yoshida
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # HpSqrt
2
+
3
+ High precision square root library for Ruby.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'hpsqrt'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install hpsqrt
20
+
21
+ ## Usage
22
+
23
+ require 'hpsqrt/core_ext'
24
+
25
+ p Sqrt(2)
26
+ # => #<HpSqrt:0x00003ff699526258 value=(1.4142135623730951+0.0i) expr=(√2)>
27
+
28
+ p Sqrt(2).to_f
29
+ # => 1.4142135623730951
30
+
31
+ p (Sqrt(2) ** 2).to_f
32
+ # => 2.0
33
+
34
+ p (Sqrt(3) * Sqrt(5) * Sqrt(15)).to_f
35
+ # => 15.0
36
+
37
+ p (Sqrt(1i) ** 4).to_c
38
+ # => (-1.0+0.0i)
39
+
40
+ p ((Sqrt(7) + Sqrt(11)) * (Sqrt(7) - Sqrt(11))).to_f
41
+ # => -4.0
42
+
43
+ ## Contributing
44
+
45
+ Bug reports and pull requests are welcome on GitHub at https://github.com/yoshida-eth0/ruby-sqrt.
46
+
47
+ ## License
48
+
49
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "hpsqrt"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/hpsqrt.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "hpsqrt/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "hpsqrt"
7
+ spec.version = HpSqrt::VERSION
8
+ spec.authors = ["Yoshida Tetsuya"]
9
+ spec.email = ["yoshida.eth0@gmail.com"]
10
+
11
+ spec.summary = %q{High precision square root library}
12
+ spec.description = %q{High precision square root library}
13
+ spec.homepage = "https://github.com/yoshida-eth0/ruby-sqrt"
14
+ spec.license = "MIT"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = spec.homepage
18
+ spec.metadata["changelog_uri"] = spec.homepage
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency "bundler", "~> 2.1.a"
30
+ spec.add_development_dependency "rake", "~> 12.0"
31
+ spec.add_development_dependency "minitest", "~> 5.0"
32
+ end
data/lib/hpsqrt.rb ADDED
@@ -0,0 +1,242 @@
1
+ require 'hpsqrt/inspect_mode'
2
+ require 'hpsqrt/value'
3
+ require 'hpsqrt/version'
4
+
5
+
6
+ class HpSqrt < Numeric
7
+
8
+ @@inspect_mode = INSPECT_MODE::DUMP
9
+
10
+
11
+ attr_reader :values
12
+
13
+ def initialize(values)
14
+ @values = values.freeze
15
+ freeze
16
+ end
17
+
18
+ def -@
19
+ values = self.values.map{|v,c| [v, -c]}.to_h
20
+ self.class.new(values)
21
+ end
22
+
23
+ def +(other)
24
+ other = self.class.create(other)
25
+
26
+ values = @values.merge(other.values) {|v, c1, c2|
27
+ c1 + c2
28
+ }
29
+ values.delete_if {|v,c| c==0}
30
+
31
+ self.class.new(values)
32
+ end
33
+
34
+ def -(other)
35
+ other = self.class.create(other)
36
+
37
+ other_values = other.values.map{|v,c| [v, -c]}.to_h
38
+ values = @values.merge(other_values) {|v, c1, c2|
39
+ c1 + c2
40
+ }
41
+ values.delete_if {|v,c| v==0}
42
+
43
+ self.class.new(values)
44
+ end
45
+
46
+ def *(other)
47
+ other = self.class.create(other)
48
+
49
+ values = {}
50
+ @values.each {|v1, c1|
51
+ other.values.each {|v2, c2|
52
+ v = v1 * v2
53
+ c = c1 * c2
54
+
55
+ values[v] ||= 0
56
+ values[v] += c
57
+ }
58
+ }
59
+ values.delete_if {|v,c| c==0}
60
+
61
+ self.class.new(values)
62
+ end
63
+
64
+ def /(other)
65
+ other = self.class.create(other)
66
+ other_inv = Value.new(number: Rational(1, other.value))
67
+
68
+ values = {}
69
+ @values.each {|v, c|
70
+ v *= other_inv
71
+
72
+ values[v] ||= 0
73
+ values[v] += c
74
+ }
75
+ values.delete_if {|v,c| c==0}
76
+
77
+ self.class.new(values)
78
+ end
79
+
80
+ def **(other)
81
+ other = self.class.create(other)
82
+
83
+ if other.int?
84
+ result = self.class.create(1)
85
+ other_i = other.real.to_i
86
+ other_i.abs.times {|i|
87
+ result *= self
88
+ }
89
+ if other_i<0
90
+ result = Rational(1, result)
91
+ end
92
+ result
93
+ else
94
+ self.class.number(self.value ** other.value)
95
+ end
96
+ end
97
+
98
+ def coerce(other)
99
+ [self.class.create(other), self]
100
+ end
101
+
102
+ def ==(other)
103
+ if self.class==other
104
+ self.value==other.value
105
+ elsif Numeric===other
106
+ self.value==other
107
+ else
108
+ super.==(other)
109
+ end
110
+ end
111
+
112
+ def value
113
+ @values.map {|v, c|
114
+ v.number * Math.sqrt(Complex(v.sqrt)) * c
115
+ }.sum
116
+ end
117
+
118
+ def real
119
+ value.real
120
+ end
121
+
122
+ def imag
123
+ Complex(value).imag
124
+ end
125
+
126
+ def to_i
127
+ c = to_c
128
+ if c.imag.zero?
129
+ c.real.to_i
130
+ else
131
+ raise RangeError, "can't convert %s into Integer" % c
132
+ end
133
+ end
134
+
135
+ def to_f
136
+ c = to_c
137
+ if c.imag.zero?
138
+ c.real.to_f
139
+ else
140
+ raise RangeError, "can't convert %s into Float" % c
141
+ end
142
+ end
143
+
144
+ def to_c
145
+ value.to_c
146
+ end
147
+
148
+ def to_r
149
+ value.to_r
150
+ end
151
+
152
+ def expr
153
+ value_to_s = -> (v) {
154
+ if Complex===v && v.imag.zero?
155
+ v = v.real
156
+ elsif Rational===v
157
+ v = v.to_s.sub(/\/1$/, "")
158
+ end
159
+ v = v.to_s
160
+ if v !~ /^[\d\.]+$/
161
+ v = "(%s)" % v
162
+ end
163
+ v
164
+ }
165
+
166
+ result = @values.map {|v, c|
167
+ n = v.number * c
168
+ s = v.sqrt
169
+
170
+ if s!=1
171
+ if n==1
172
+ "\u221A%s" % value_to_s[s]
173
+ elsif 0<n.real
174
+ "%s\u221A%s" % [value_to_s[n], value_to_s[s]]
175
+ elsif n==-1
176
+ "(-\u221A%s)" % value_to_s[s]
177
+ else
178
+ "(%s\u221A%s)" % [value_to_s[n], value_to_s[s]]
179
+ end
180
+ else
181
+ value_to_s[n]
182
+ end
183
+ }
184
+
185
+ if 0<result.length
186
+ result.join(" + ")
187
+ else
188
+ "0"
189
+ end
190
+ end
191
+
192
+ def inspect
193
+ to_s
194
+ end
195
+
196
+ def to_s
197
+ case @@inspect_mode
198
+ when INSPECT_MODE::VALUE
199
+ value.to_s
200
+ when INSPECT_MODE::EXPR
201
+ expr
202
+ when INSPECT_MODE::DUMP
203
+ "#<%s:0x%016x value=(%s) expr=(%s)>" % [self.class.name, self.object_id, value, expr]
204
+ end
205
+ end
206
+
207
+ def real?
208
+ imag.zero?
209
+ end
210
+
211
+ def imag?
212
+ !real?
213
+ end
214
+
215
+ def int?
216
+ v = value
217
+ is_imag = Complex===v && !v.imag.zero?
218
+ !is_imag && v.real==v.real.to_i
219
+ end
220
+
221
+ def float?
222
+ v = value
223
+ is_imag = Complex===v && !v.imag.zero?
224
+ !is_imag && Float===v.real && v.real!=v.real.to_i
225
+ end
226
+
227
+ def self.create(v)
228
+ if self===v
229
+ v
230
+ else
231
+ number(v)
232
+ end
233
+ end
234
+
235
+ def self.number(v)
236
+ new({Value.new(number: v) => 1})
237
+ end
238
+
239
+ def self.sqrt(v)
240
+ new({Value.new(sqrt: v) => 1})
241
+ end
242
+ end
@@ -0,0 +1,8 @@
1
+ require 'hpsqrt'
2
+
3
+
4
+ module Kernel
5
+ def Sqrt(v)
6
+ HpSqrt.sqrt(v)
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+
2
+ class HpSqrt < Numeric
3
+
4
+ module INSPECT_MODE
5
+ VALUE = :value
6
+ EXPR = :expr
7
+ DUMP = :dump
8
+ end
9
+
10
+ end
@@ -0,0 +1,36 @@
1
+ class HpSqrt < Numeric
2
+
3
+ class Value
4
+ attr_reader :number
5
+ attr_reader :sqrt
6
+
7
+ def initialize(number: 1, sqrt: 1)
8
+ @number = number
9
+ @sqrt = sqrt
10
+ freeze
11
+ end
12
+
13
+ def *(other)
14
+ if self.class===other
15
+ n = @number * other.number
16
+ s = 1
17
+ if @sqrt==other.sqrt
18
+ n *= @sqrt
19
+ else
20
+ s = @sqrt * other.sqrt
21
+ end
22
+
23
+ self.class.new(number: n, sqrt: s)
24
+ end
25
+ end
26
+
27
+ def eql?(other)
28
+ self.class===other && @number==other.number && @sqrt==other.sqrt
29
+ end
30
+
31
+ def hash
32
+ [@number, @sqrt].hash
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,3 @@
1
+ class HpSqrt < Numeric
2
+ VERSION = "1.0.0"
3
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hpsqrt
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Yoshida Tetsuya
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-06-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.1.a
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.1.a
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: High precision square root library
56
+ email:
57
+ - yoshida.eth0@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".travis.yml"
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - bin/console
69
+ - bin/setup
70
+ - hpsqrt.gemspec
71
+ - lib/hpsqrt.rb
72
+ - lib/hpsqrt/core_ext.rb
73
+ - lib/hpsqrt/inspect_mode.rb
74
+ - lib/hpsqrt/value.rb
75
+ - lib/hpsqrt/version.rb
76
+ homepage: https://github.com/yoshida-eth0/ruby-sqrt
77
+ licenses:
78
+ - MIT
79
+ metadata:
80
+ homepage_uri: https://github.com/yoshida-eth0/ruby-sqrt
81
+ source_code_uri: https://github.com/yoshida-eth0/ruby-sqrt
82
+ changelog_uri: https://github.com/yoshida-eth0/ruby-sqrt
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubygems_version: 3.0.3
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: High precision square root library
102
+ test_files: []