vector_number 0.4.3 → 0.6.0
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.
- checksums.yaml +4 -4
- data/README.md +47 -22
- data/doc/vector_space.svg +94 -0
- data/lib/vector_number/comparing.rb +103 -107
- data/lib/vector_number/converting.rb +137 -147
- data/lib/vector_number/enumerating.rb +94 -108
- data/lib/vector_number/math_converting.rb +113 -109
- data/lib/vector_number/mathing.rb +305 -312
- data/lib/vector_number/numeric_refinements.rb +7 -0
- data/lib/vector_number/querying.rb +136 -136
- data/lib/vector_number/special_unit.rb +36 -0
- data/lib/vector_number/stringifying.rb +89 -80
- data/lib/vector_number/version.rb +1 -1
- data/lib/vector_number.rb +155 -126
- data/sig/vector_number.rbs +141 -168
- metadata +14 -11
|
@@ -1,152 +1,142 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class VectorNumber
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
#
|
|
141
|
-
# @since 0.1.0
|
|
142
|
-
def to_c
|
|
143
|
-
numeric?(2) ? Complex(real, imaginary) : raise_convert_error(Complex)
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
private
|
|
147
|
-
|
|
148
|
-
def raise_convert_error(klass)
|
|
149
|
-
raise RangeError, "can't convert #{self} into #{klass}", caller
|
|
150
|
-
end
|
|
4
|
+
# @group Converting to different numeric classes
|
|
5
|
+
|
|
6
|
+
# Return real part of the number.
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# VectorNumber[23, "a"].real # => 23
|
|
10
|
+
# VectorNumber["a"].real # => 0
|
|
11
|
+
#
|
|
12
|
+
# @return [Integer, Float, Rational, BigDecimal]
|
|
13
|
+
def real = @data[R]
|
|
14
|
+
|
|
15
|
+
# Return imaginary part of the number.
|
|
16
|
+
#
|
|
17
|
+
# @example
|
|
18
|
+
# VectorNumber[23, "a"].imaginary # => 0
|
|
19
|
+
# VectorNumber["a", Complex(1, 2r)].imag # => (2/1)
|
|
20
|
+
#
|
|
21
|
+
# @return [Integer, Float, Rational, BigDecimal]
|
|
22
|
+
def imaginary = @data[I]
|
|
23
|
+
|
|
24
|
+
# @since 0.2.1
|
|
25
|
+
alias imag imaginary
|
|
26
|
+
|
|
27
|
+
# Return value as an Integer, truncating it, if only real part is non-zero.
|
|
28
|
+
#
|
|
29
|
+
# @example
|
|
30
|
+
# VectorNumber[13.5].to_i # => 13
|
|
31
|
+
# VectorNumber[13r/12].to_int # => 1
|
|
32
|
+
# [1.1, 2.2, 3.3][VectorNumber[2]] # => 3.3
|
|
33
|
+
# VectorNumber[2, 2i].to_i # RangeError
|
|
34
|
+
# VectorNumber[2, :i].to_f # RangeError
|
|
35
|
+
#
|
|
36
|
+
# Integer(VectorNumber[2]) # => 2
|
|
37
|
+
# Integer(VectorNumber[2, "i"]) # RangeError
|
|
38
|
+
#
|
|
39
|
+
# @return [Integer]
|
|
40
|
+
# @raise [RangeError] if any non-real part is non-zero
|
|
41
|
+
def to_i
|
|
42
|
+
raise_convert_error(Integer) unless numeric?(1)
|
|
43
|
+
|
|
44
|
+
real.to_i
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
alias to_int to_i
|
|
48
|
+
|
|
49
|
+
# Return value as a Float if only real part is non-zero.
|
|
50
|
+
#
|
|
51
|
+
# @example
|
|
52
|
+
# VectorNumber[13.5].to_f # => 13.5
|
|
53
|
+
# VectorNumber[13r/12].to_f # => 1.0833333333333333
|
|
54
|
+
# VectorNumber[2, 2i].to_f # RangeError
|
|
55
|
+
# VectorNumber[2, :i].to_f # RangeError
|
|
56
|
+
#
|
|
57
|
+
# Float(VectorNumber[2]) # => 2.0
|
|
58
|
+
# Float(VectorNumber[2, "i"]) # RangeError
|
|
59
|
+
#
|
|
60
|
+
# @return [Float]
|
|
61
|
+
# @raise [RangeError] if any non-real part is non-zero
|
|
62
|
+
def to_f
|
|
63
|
+
raise_convert_error(Float) unless numeric?(1)
|
|
64
|
+
|
|
65
|
+
real.to_f
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Return value as a Rational if only real part is non-zero.
|
|
69
|
+
#
|
|
70
|
+
# @example
|
|
71
|
+
# VectorNumber[13.5].to_r # => (27/2)
|
|
72
|
+
# VectorNumber[13r/12].to_r # => (13/12)
|
|
73
|
+
# VectorNumber[2, 2i].to_r # RangeError
|
|
74
|
+
# VectorNumber[2, :i].to_r # RangeError
|
|
75
|
+
#
|
|
76
|
+
# Rational(VectorNumber[2]) # => (2/1)
|
|
77
|
+
# Rational(VectorNumber[2, "i"]) # RangeError
|
|
78
|
+
#
|
|
79
|
+
# @return [Rational]
|
|
80
|
+
# @raise [RangeError] if any non-real part is non-zero
|
|
81
|
+
def to_r
|
|
82
|
+
raise_convert_error(Rational) unless numeric?(1)
|
|
83
|
+
|
|
84
|
+
real.to_r
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Return value as a BigDecimal if only real part is non-zero.
|
|
88
|
+
#
|
|
89
|
+
# @example
|
|
90
|
+
# VectorNumber[13.5].to_d # => 0.135e2
|
|
91
|
+
# VectorNumber[13r/12].to_d # ArgumentError
|
|
92
|
+
# VectorNumber[13r/12].to_d(5) # => 0.10833e1
|
|
93
|
+
# VectorNumber[2, 2i].to_d # RangeError
|
|
94
|
+
# VectorNumber[2, :i].to_d # RangeError
|
|
95
|
+
#
|
|
96
|
+
# # This does't work without NumericRefinements:
|
|
97
|
+
# BigDecimal(VectorNumber[2]) # TypeError
|
|
98
|
+
# # #to_s can be used as a workaround if refinements aren't used:
|
|
99
|
+
# BigDecimal(VectorNumber[2].to_s) # => 0.2e1
|
|
100
|
+
# BigDecimal(VectorNumber[2, "i"].to_s) # => ArgumentError
|
|
101
|
+
#
|
|
102
|
+
# @param ndigits [Integer] precision
|
|
103
|
+
# @return [BigDecimal]
|
|
104
|
+
# @raise [RangeError] if any non-real part is non-zero
|
|
105
|
+
# @raise [NameError] if BigDecimal is not defined
|
|
106
|
+
#
|
|
107
|
+
# @see Kernel.BigDecimal
|
|
108
|
+
# @see NumericRefinements
|
|
109
|
+
def to_d(ndigits = nil)
|
|
110
|
+
raise_convert_error(BigDecimal) unless numeric?(1)
|
|
111
|
+
|
|
112
|
+
return BigDecimal(real, ndigits) if ndigits
|
|
113
|
+
return BigDecimal(real, Float::DIG) if real.is_a?(Float)
|
|
114
|
+
|
|
115
|
+
BigDecimal(real)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Return value as a Complex if only real and/or imaginary parts are non-zero.
|
|
119
|
+
#
|
|
120
|
+
# @example
|
|
121
|
+
# VectorNumber[13.5].to_c # => (13.5+0i)
|
|
122
|
+
# VectorNumber[13r/12].to_c # => ((13/12)+0i)
|
|
123
|
+
# VectorNumber[2, 2i].to_c # => (2+2i)
|
|
124
|
+
# VectorNumber[2, :i].to_c # RangeError
|
|
125
|
+
#
|
|
126
|
+
# Complex(VectorNumber[2]) # => (2+0i)
|
|
127
|
+
# Complex(VectorNumber[2, "i"]) # RangeError
|
|
128
|
+
#
|
|
129
|
+
# @return [Complex]
|
|
130
|
+
# @raise [RangeError] if any non-real, non-imaginary part is non-zero
|
|
131
|
+
def to_c
|
|
132
|
+
raise_convert_error(Complex) unless numeric?(2)
|
|
133
|
+
|
|
134
|
+
Complex(real, imaginary)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
private
|
|
138
|
+
|
|
139
|
+
def raise_convert_error(klass)
|
|
140
|
+
raise RangeError, "can't convert #{self} into #{klass}", caller
|
|
151
141
|
end
|
|
152
142
|
end
|
|
@@ -1,128 +1,114 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class VectorNumber
|
|
4
|
-
#
|
|
5
|
-
|
|
4
|
+
# @group Hash-like operations
|
|
5
|
+
|
|
6
6
|
# +Enumerable+ is included so its methods can be used.
|
|
7
7
|
# @example using Enumerable methods
|
|
8
8
|
# VectorNumber["a", "b", 6].include?(["a", 1]) # => true
|
|
9
9
|
# VectorNumber["a", "b", 6].select { |u, c| u.is_a?(String) } # => [["a", 1], ["b", 1]]
|
|
10
|
-
|
|
11
|
-
# @since 0.1.0
|
|
12
|
-
include ::Enumerable
|
|
10
|
+
include ::Enumerable
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def each(&block)
|
|
40
|
-
return to_enum { size } unless block_given?
|
|
12
|
+
# Iterate through every pair of unit and coefficient.
|
|
13
|
+
# Returns +Enumerator+ (with set +size+) if no block is given.
|
|
14
|
+
#
|
|
15
|
+
# @example
|
|
16
|
+
# v = VectorNumber["a", "b", 6]
|
|
17
|
+
# units = []
|
|
18
|
+
# v.each { |u, c| units << u unless u.is_a?(Numeric) } # => (1⋅'a' + 1⋅'b' + 6)
|
|
19
|
+
# units # => ["a", "b"]
|
|
20
|
+
# @example Enumerator
|
|
21
|
+
# v.each.size # => 3
|
|
22
|
+
# (v.each + [["d", 0]]).map(&:first) # => ["a", "b", 1, "d"]
|
|
23
|
+
# v.each_pair.peek # => ["a", 1]
|
|
24
|
+
#
|
|
25
|
+
# @overload each
|
|
26
|
+
# @yieldparam unit [Object]
|
|
27
|
+
# @yieldparam coefficient [Numeric]
|
|
28
|
+
# @yieldreturn [void]
|
|
29
|
+
# @return [VectorNumber] self
|
|
30
|
+
# @overload each
|
|
31
|
+
# @return [Enumerator]
|
|
32
|
+
#
|
|
33
|
+
# @see Enumerable
|
|
34
|
+
# @see Enumerator
|
|
35
|
+
def each(&block)
|
|
36
|
+
return to_enum { size } unless block_given?
|
|
41
37
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
@data.each(&block)
|
|
39
|
+
self
|
|
40
|
+
end
|
|
45
41
|
|
|
46
|
-
|
|
47
|
-
alias each_pair each
|
|
42
|
+
alias each_pair each
|
|
48
43
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
# @since 0.1.0
|
|
58
|
-
def units = @data.keys
|
|
44
|
+
# Get a list of units with non-zero coefficients.
|
|
45
|
+
#
|
|
46
|
+
# @example
|
|
47
|
+
# VectorNumber["a", "b", 6].units # => ["a", "b", 1]
|
|
48
|
+
# VectorNumber.new.keys # => []
|
|
49
|
+
#
|
|
50
|
+
# @return [Array<Object>]
|
|
51
|
+
def units = @data.keys
|
|
59
52
|
|
|
60
|
-
|
|
61
|
-
alias keys units
|
|
53
|
+
alias keys units
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
# @since 0.1.0
|
|
72
|
-
def coefficients = @data.values
|
|
55
|
+
# Get a list of non-zero coefficients.
|
|
56
|
+
#
|
|
57
|
+
# @example
|
|
58
|
+
# VectorNumber["a", "b", 6].coefficients # => [1, 1, 6]
|
|
59
|
+
# VectorNumber.new.values # => []
|
|
60
|
+
#
|
|
61
|
+
# @return [Array<Numeric>]
|
|
62
|
+
def coefficients = @data.values
|
|
73
63
|
|
|
74
|
-
|
|
75
|
-
alias values coefficients
|
|
64
|
+
alias values coefficients
|
|
76
65
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
#
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
else
|
|
93
|
-
@data.dup
|
|
94
|
-
end
|
|
66
|
+
# Get mutable hash with vector's data.
|
|
67
|
+
#
|
|
68
|
+
# Returned hash has a default value of 0.
|
|
69
|
+
#
|
|
70
|
+
# @example
|
|
71
|
+
# VectorNumber["a", "b", 6].to_h # => {"a"=>1, "b"=>1, 1=>6}
|
|
72
|
+
# VectorNumber["a", "b", 6].to_h["c"] # => 0
|
|
73
|
+
#
|
|
74
|
+
# @return [Hash{Object => Numeric}]
|
|
75
|
+
def to_h(&block)
|
|
76
|
+
# TODO: Remove block argument.
|
|
77
|
+
if block_given?
|
|
78
|
+
@data.to_h(&block)
|
|
79
|
+
else
|
|
80
|
+
@data.dup
|
|
95
81
|
end
|
|
82
|
+
end
|
|
96
83
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
84
|
+
# Get the coefficient for the unit.
|
|
85
|
+
#
|
|
86
|
+
# If the +unit?(unit)+ is false, 0 is returned.
|
|
87
|
+
# Note that units for real and imaginary parts are
|
|
88
|
+
# VectorNumber::R and VectorNumber::I respectively.
|
|
89
|
+
#
|
|
90
|
+
# @example
|
|
91
|
+
# VectorNumber["a", "b", 6]["a"] # => 1
|
|
92
|
+
# VectorNumber["a", "b", 6]["c"] # => 0
|
|
93
|
+
#
|
|
94
|
+
# @param unit [Object]
|
|
95
|
+
# @return [Numeric]
|
|
96
|
+
#
|
|
97
|
+
# @since 0.2.4
|
|
98
|
+
def [](unit) = @data[unit]
|
|
112
99
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
100
|
+
# Check if a unit has a non-zero coefficient.
|
|
101
|
+
#
|
|
102
|
+
# @example
|
|
103
|
+
# VectorNumber["a", "b", 6].unit?("a") # => true
|
|
104
|
+
# VectorNumber["a", "b", 6].key?("c") # => false
|
|
105
|
+
#
|
|
106
|
+
# @param unit [Object]
|
|
107
|
+
# @return [Boolean]
|
|
108
|
+
#
|
|
109
|
+
# @since 0.2.4
|
|
110
|
+
def unit?(unit) = @data.key?(unit)
|
|
124
111
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
end
|
|
112
|
+
# @since 0.2.4
|
|
113
|
+
alias key? unit?
|
|
128
114
|
end
|