int 0.0.1.interval

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