int 0.0.1.interval

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (7) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +41 -0
  3. data/Rakefile +10 -0
  4. data/lib/int/version.rb +3 -0
  5. data/lib/int.rb +139 -0
  6. data/sig/int.rbs +4 -0
  7. metadata +105 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 949f5639815b1a5a2655f7e1db7982baf19d8d60e1029d2cb88fb246dc2c64f8
4
+ data.tar.gz: 98b7c7df5ade14a9dca26cfb3fce1271b1eeede5950f36c8765f8b3917f76c9d
5
+ SHA512:
6
+ metadata.gz: 450dd42f73818e5dd8561cf7ac081b8c8a6d095586f8473febe1a57a397a534ff59d2ee1ff0eee22078e8133a1f8706402da8a8a7eee1969b8848db283d5145d
7
+ data.tar.gz: 119b66a9ccb05c68ab503688b9a0d7813d9d9f4fac638d6303cef07a2e7c186c0601196f2764f1c7eb03084cb8d2abc0844da12dd98b3081e948b77c75a849db
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Int
2
+
3
+ An interval-arithmetic-ish library (with a terrible name).
4
+
5
+ ## Introduction
6
+
7
+ Welcome to my new gem! In this directory, I'll find the files I need to be able to package
8
+ up my Ruby library into a gem. Put my Ruby code in the file `lib/int`. To experiment with
9
+ that code, run `bin/console` for an interactive prompt.
10
+
11
+ ## Installation
12
+
13
+ Install the gem and add to the application's Gemfile by executing:
14
+
15
+ $ bundle add int
16
+
17
+ If bundler is not being used to manage dependencies, install the gem by executing:
18
+
19
+ $ gem install int
20
+
21
+ ## Usage
22
+
23
+ ```ruby
24
+ pp Int(1, 2) + Int(3, 4) #=> Int(4..(5.0)..6)
25
+ ```
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake
30
+ test-unit` to run the tests. You can also run `bin/console` for an interactive prompt that
31
+ will allow you to experiment.
32
+
33
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a
34
+ new version, update the version number in `version.rb`, and then run `bundle exec rake
35
+ release`, which will create a git tag for the version, push git commits and the created
36
+ tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
37
+
38
+ ## Contributing
39
+
40
+ Bug reports and pull requests are welcome on GitHub at https://github.com/tadd/int
41
+ except for name change proposals.
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
@@ -0,0 +1,3 @@
1
+ class Int < Numeric
2
+ VERSION = "0.0.1.interval"
3
+ end
data/lib/int.rb ADDED
@@ -0,0 +1,139 @@
1
+ # Interval arithmetics
2
+
3
+ require_relative "int/version"
4
+
5
+ class Int < Numeric
6
+ attr_reader :begin, :end, :median
7
+ protected attr_reader :values
8
+
9
+ def initialize(beg, encl = nil, error: nil)
10
+ if error
11
+ raise ArgumentError, 'do not specify 2nd arg when `error:`' if encl
12
+ raise ArgumentError, 'error value should be non-negtative' if error.negative?
13
+ med = beg
14
+ beg, encl = med-error, med+error
15
+ else
16
+ raise ArgumentError, 'specify 2nd arg when no `error:`' unless encl
17
+ raise ArgumentError, "needs begin <= end: #{beg} <=> #{encl}" unless beg <= encl
18
+ end
19
+ @begin, @end = beg, encl
20
+ @values = [beg, encl]
21
+ @median = (beg + encl) / 2.0
22
+ end
23
+
24
+ private
25
+
26
+ def new(...) = self.class.new(...)
27
+ def scala?(other) = [Integer, Float, Rational].include?(other.class)
28
+ def ensure_coerced(other) = other.kind_of?(self.class) ? other : coerce(other).first
29
+
30
+ protected
31
+
32
+ def round_median(n) = (@median = @median.round(n)).then { self }
33
+ def invert
34
+ one = @end.zero? ? -1.0 : 1.0
35
+ new(one / @end, 1.0 / @begin)
36
+ end
37
+
38
+ public
39
+
40
+ def self.error(error)
41
+ new(1, error:)
42
+ end
43
+
44
+ def coerce(other)
45
+ if scala?(other)
46
+ other = new(*[other]*2)
47
+ else
48
+ raise "Unknown class #{other.class}: #{other}"
49
+ end
50
+ [other, self]
51
+ end
52
+
53
+ def +(other)
54
+ other = ensure_coerced(other)
55
+ new(@begin + other.begin, @end + other.end)
56
+ end
57
+
58
+ def -(other)
59
+ other = ensure_coerced(other)
60
+ new(@begin - other.end, @end - other.begin)
61
+ end
62
+
63
+ def *(other)
64
+ other = ensure_coerced(other)
65
+ mul = values.product(other.values).map{_1.inject(:*)}
66
+ raise "got a NaN; I don't know what to do" if mul.any?{|x| x.respond_to?(:nan?) && x.nan?}
67
+ new(*mul.minmax)
68
+ end
69
+
70
+ def /(other)
71
+ self * ensure_coerced(other).invert
72
+ end
73
+
74
+ def <=>(other)
75
+ other = ensure_coerced(other)
76
+ return 0 if @begin == @end && @begin == other.begin && @begin == other.end
77
+ return 1 if @begin > other.end
78
+ return -1 if @end < other.begin
79
+ nil
80
+ end
81
+
82
+ def <=(other)
83
+ other = ensure_coerced(other)
84
+ @end <= other.begin
85
+ end
86
+
87
+ def >=(other)
88
+ other = ensure_coerced(other)
89
+ @begin >= other.end
90
+ end
91
+
92
+ def comparable?(other)
93
+ other = ensure_coerced(other) rescue (return false)
94
+ !!(self <=> other) || @end == other.begin || @begin == other.end
95
+ end
96
+
97
+ def round(n)
98
+ new(*[self.begin,self.end].map{_1.round(n)}).round_median(n)
99
+ end
100
+
101
+ def with_error(e) = self * self.class.error(e)
102
+ def with_error_percent(e) = with_error(e * 0.01)
103
+
104
+ def to_s = "(#{self.begin}..#{self.end})"
105
+ def inspect = self.class.name + to_s.sub('..', "..(#{median})..")
106
+ end
107
+
108
+ def Int(...) = Int.new(...)
109
+
110
+ if $0 == __FILE__
111
+ x, y = Int(1, 2), Int(2, 3)
112
+ pp(x:, y:)
113
+
114
+ pp [x == y, x != y]
115
+ pp [x >= y, x <= y]
116
+ pp [y >= x, y <= x]
117
+ pp [x.comparable?(y), y.comparable?(x)]
118
+
119
+ z = Int(1.1, 1.4)
120
+ pp z
121
+ pp [x.comparable?(z), z.comparable?(x)]
122
+ pp z.comparable?(:foo)
123
+ pp z.round(1)
124
+ pp Int.error(0.2)
125
+
126
+ pp [x.with_error(0.01), x.with_error_percent(1)].map{_1.round(2)}
127
+
128
+ pp [z / 2, z / z].map{_1.round(2)}
129
+
130
+ i = Int(0, 1.2)
131
+ j = Int(-1.2, 0)
132
+ pp [x/i, x/j]
133
+ ji = j.send(:invert)
134
+ pp ji
135
+ pp [i, ji]
136
+ #pp i*ji
137
+ #pp i/j
138
+ #pp j/i
139
+ end
data/sig/int.rbs ADDED
@@ -0,0 +1,4 @@
1
+ class Int
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: int
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.interval
5
+ platform: ruby
6
+ authors:
7
+ - Tadashi Saito
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-01-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: test-unit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: debug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: steep
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - tad.a.digger@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - README.md
77
+ - Rakefile
78
+ - lib/int.rb
79
+ - lib/int/version.rb
80
+ - sig/int.rbs
81
+ homepage: https://github.com/tadd/int
82
+ licenses: []
83
+ metadata:
84
+ homepage_uri: https://github.com/tadd/int
85
+ source_code_uri: https://github.com/tadd/int
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubygems_version: 3.5.4
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Interval-arithmetic-ish library with a terrible name.
105
+ test_files: []