vector_number 0.4.2 → 0.5.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 +2 -2
- data/lib/vector_number/comparing.rb +110 -107
- data/lib/vector_number/converting.rb +152 -147
- data/lib/vector_number/enumerating.rb +107 -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 +22 -3
- data/lib/vector_number/querying.rb +143 -136
- data/lib/vector_number/stringifying.rb +79 -82
- data/lib/vector_number/version.rb +1 -1
- data/lib/vector_number.rb +125 -55
- data/sig/vector_number.rbs +128 -161
- metadata +6 -6
|
@@ -1,345 +1,338 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class VectorNumber
|
|
4
|
-
#
|
|
4
|
+
# @group Mathematical operations
|
|
5
5
|
#
|
|
6
6
|
# All operators (like +*+) have aliases (like +mult+)
|
|
7
7
|
# to make method chaining easier and more natural.
|
|
8
|
-
module Mathing
|
|
9
|
-
# The coerce method provides support for Ruby type coercion.
|
|
10
|
-
#
|
|
11
|
-
# Unlike other numeric types, VectorNumber can coerce *anything*.
|
|
12
|
-
#
|
|
13
|
-
# @example
|
|
14
|
-
# VectorNumber["a"].coerce(5) # => [(5), (1⋅'a')]
|
|
15
|
-
# VectorNumber[7].coerce([]) # => [(1⋅[]), (7)]
|
|
16
|
-
# VectorNumber["a"] + 5 # => (1⋅'a' + 5)
|
|
17
|
-
# # Direct reverse coercion doesn't work, but Numeric types know how to call #coerce:
|
|
18
|
-
# 5.coerce(VectorNumber["a"]) # RangeError
|
|
19
|
-
# 5 + VectorNumber["a"] # => (5 + 1⋅'a')
|
|
20
|
-
#
|
|
21
|
-
# @param other [Object]
|
|
22
|
-
# @return [Array(VectorNumber, VectorNumber)]
|
|
23
|
-
#
|
|
24
|
-
# @since 0.2.0
|
|
25
|
-
def coerce(other)
|
|
26
|
-
case other
|
|
27
|
-
when VectorNumber
|
|
28
|
-
[other, self]
|
|
29
|
-
else
|
|
30
|
-
[new([other]), self]
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Return new vector with negated coefficients (additive inverse).
|
|
35
|
-
#
|
|
36
|
-
# @example
|
|
37
|
-
# -VectorNumber[12, "i"] # => (-12 - 1⋅'i')
|
|
38
|
-
# VectorNumber["a", "b", "a"].neg # => (-2⋅'a' - 1⋅'b')
|
|
39
|
-
# -VectorNumber["a"] + VectorNumber["a"] # => (0)
|
|
40
|
-
#
|
|
41
|
-
# @return [VectorNumber]
|
|
42
|
-
#
|
|
43
|
-
# @since 0.2.0
|
|
44
|
-
def -@
|
|
45
|
-
new(&:-@)
|
|
46
|
-
end
|
|
47
8
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
9
|
+
# The coerce method provides support for Ruby type coercion.
|
|
10
|
+
#
|
|
11
|
+
# Unlike other numeric types, VectorNumber can coerce *anything*.
|
|
12
|
+
#
|
|
13
|
+
# @example
|
|
14
|
+
# VectorNumber["a"].coerce(5) # => [(5), (1⋅'a')]
|
|
15
|
+
# VectorNumber[7].coerce([]) # => [(1⋅[]), (7)]
|
|
16
|
+
# VectorNumber["a"] + 5 # => (1⋅'a' + 5)
|
|
17
|
+
# # Direct reverse coercion doesn't work, but Numeric types know how to call #coerce:
|
|
18
|
+
# 5.coerce(VectorNumber["a"]) # RangeError
|
|
19
|
+
# 5 + VectorNumber["a"] # => (5 + 1⋅'a')
|
|
20
|
+
#
|
|
21
|
+
# @param other [Object]
|
|
22
|
+
# @return [Array(VectorNumber, VectorNumber)]
|
|
23
|
+
#
|
|
24
|
+
# @since 0.2.0
|
|
25
|
+
def coerce(other)
|
|
26
|
+
case other
|
|
27
|
+
when VectorNumber
|
|
28
|
+
[other, self]
|
|
29
|
+
else
|
|
30
|
+
[new([other]), self]
|
|
68
31
|
end
|
|
32
|
+
end
|
|
69
33
|
|
|
70
|
-
|
|
71
|
-
|
|
34
|
+
# Return new vector with negated coefficients (additive inverse).
|
|
35
|
+
#
|
|
36
|
+
# @example
|
|
37
|
+
# -VectorNumber[12, "i"] # => (-12 - 1⋅'i')
|
|
38
|
+
# VectorNumber["a", "b", "a"].neg # => (-2⋅'a' - 1⋅'b')
|
|
39
|
+
# -VectorNumber["a"] + VectorNumber["a"] # => (0)
|
|
40
|
+
#
|
|
41
|
+
# @return [VectorNumber]
|
|
42
|
+
#
|
|
43
|
+
# @since 0.2.0
|
|
44
|
+
def -@
|
|
45
|
+
new(&:-@)
|
|
46
|
+
end
|
|
72
47
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
# This is implemented through {#+} and {#-@}.
|
|
76
|
-
#
|
|
77
|
-
# @example
|
|
78
|
-
# VectorNumber[5] - 3 # => (2)
|
|
79
|
-
# VectorNumber["a"].sub(VectorNumber["b"]) # => (1⋅'a' - 1⋅'b')
|
|
80
|
-
# VectorNumber["a"] - "b" # => (1⋅'a' - 1⋅'b')
|
|
81
|
-
# @example numeric types can be subtracted in reverse
|
|
82
|
-
# 3 - VectorNumber[5] # => (-2)
|
|
83
|
-
# 3 - VectorNumber["a"] # => (3 - 1⋅'a')
|
|
84
|
-
#
|
|
85
|
-
# @param other [Object]
|
|
86
|
-
# @return [VectorNumber]
|
|
87
|
-
#
|
|
88
|
-
# @since 0.2.0
|
|
89
|
-
def -(other)
|
|
90
|
-
self + new([other], &:-@)
|
|
91
|
-
end
|
|
48
|
+
# @since 0.3.0
|
|
49
|
+
alias neg -@
|
|
92
50
|
|
|
93
|
-
|
|
94
|
-
|
|
51
|
+
# Return new vector as a sum of this and +other+ value.
|
|
52
|
+
# This is analogous to {VectorNumber.[]}.
|
|
53
|
+
#
|
|
54
|
+
# @example
|
|
55
|
+
# VectorNumber[5] + 10 # => (15)
|
|
56
|
+
# VectorNumber["a"].add(VectorNumber["b"]) # => (1⋅'a' + 1⋅'b')
|
|
57
|
+
# VectorNumber["a"] + "b" # => (1⋅'a' + 1⋅'b')
|
|
58
|
+
# @example numeric types can be added in reverse
|
|
59
|
+
# 10 + VectorNumber[5] # => (15)
|
|
60
|
+
# 10 + VectorNumber["a"] # => (10 + 1⋅'a')
|
|
61
|
+
#
|
|
62
|
+
# @param other [Object]
|
|
63
|
+
# @return [VectorNumber]
|
|
64
|
+
#
|
|
65
|
+
# @since 0.2.0
|
|
66
|
+
def +(other)
|
|
67
|
+
new([self, other])
|
|
68
|
+
end
|
|
95
69
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
# This effectively multiplies {#magnitude} by +other+.
|
|
99
|
-
#
|
|
100
|
-
# @example
|
|
101
|
-
# VectorNumber[5] * 2 # => (10)
|
|
102
|
-
# VectorNumber["a", "b", 6].mult(2) # => (2⋅'a' + 2⋅'b' + 12)
|
|
103
|
-
# VectorNumber["a"] * VectorNumber[2] # => (2⋅'a')
|
|
104
|
-
# # Can't multiply by a non-real:
|
|
105
|
-
# VectorNumber["a"] * VectorNumber["b"] # RangeError
|
|
106
|
-
# @example numeric types can be multiplied in reverse
|
|
107
|
-
# 2 * VectorNumber[5] # => (10)
|
|
108
|
-
# 2 * VectorNumber["a"] # => (2⋅'a')
|
|
109
|
-
#
|
|
110
|
-
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
111
|
-
# @return [VectorNumber]
|
|
112
|
-
# @raise [RangeError] if +other+ is not a number or +other+ can't be multiplied by this one
|
|
113
|
-
#
|
|
114
|
-
# @since 0.2.1
|
|
115
|
-
def *(other)
|
|
116
|
-
if real_number?(other)
|
|
117
|
-
other = other.real
|
|
118
|
-
# @type var other: Float
|
|
119
|
-
new { _1 * other }
|
|
120
|
-
elsif real_number?(self) && other.is_a?(self.class)
|
|
121
|
-
# @type var other: untyped
|
|
122
|
-
other * self
|
|
123
|
-
else
|
|
124
|
-
raise RangeError, "can't multiply #{self} and #{other}"
|
|
125
|
-
end
|
|
126
|
-
end
|
|
70
|
+
# @since 0.3.0
|
|
71
|
+
alias add +
|
|
127
72
|
|
|
128
|
-
|
|
129
|
-
|
|
73
|
+
# Return new vector as a sum of this and additive inverse of +other+ value.
|
|
74
|
+
#
|
|
75
|
+
# This is implemented through {#+} and {#-@}.
|
|
76
|
+
#
|
|
77
|
+
# @example
|
|
78
|
+
# VectorNumber[5] - 3 # => (2)
|
|
79
|
+
# VectorNumber["a"].sub(VectorNumber["b"]) # => (1⋅'a' - 1⋅'b')
|
|
80
|
+
# VectorNumber["a"] - "b" # => (1⋅'a' - 1⋅'b')
|
|
81
|
+
# @example numeric types can be subtracted in reverse
|
|
82
|
+
# 3 - VectorNumber[5] # => (-2)
|
|
83
|
+
# 3 - VectorNumber["a"] # => (3 - 1⋅'a')
|
|
84
|
+
#
|
|
85
|
+
# @param other [Object]
|
|
86
|
+
# @return [VectorNumber]
|
|
87
|
+
#
|
|
88
|
+
# @since 0.2.0
|
|
89
|
+
def -(other)
|
|
90
|
+
self + new([other], &:-@)
|
|
91
|
+
end
|
|
130
92
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
# This effectively multiplies {#magnitude} by reciprocal of +other+.
|
|
134
|
-
# @note This method never does integer division.
|
|
135
|
-
#
|
|
136
|
-
# @example
|
|
137
|
-
# VectorNumber[10] / 2 # => (5)
|
|
138
|
-
# VectorNumber["a", "b", 6].quo(2) # => (1/2⋅'a' + 1/2⋅'b' + 3/1)
|
|
139
|
-
# VectorNumber["a"] / VectorNumber[2] # => (1/2⋅'a')
|
|
140
|
-
# # Can't divide by a non-real:
|
|
141
|
-
# VectorNumber["a"] / VectorNumber["b"] # RangeError
|
|
142
|
-
# @example numeric types can be divided in reverse
|
|
143
|
-
# 2 / VectorNumber[10] # => (1/5)
|
|
144
|
-
# # Can't divide by a non-real:
|
|
145
|
-
# 2 / VectorNumber["a"] # RangeError
|
|
146
|
-
#
|
|
147
|
-
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
148
|
-
# @return [VectorNumber]
|
|
149
|
-
# @raise [RangeError] if +other+ is not a number or is not a real number
|
|
150
|
-
# @raise [ZeroDivisionError] if +other+ is zero
|
|
151
|
-
#
|
|
152
|
-
# @since 0.2.1
|
|
153
|
-
def /(other)
|
|
154
|
-
check_divisibility(other)
|
|
93
|
+
# @since 0.3.0
|
|
94
|
+
alias sub -
|
|
155
95
|
|
|
96
|
+
# Multiply all coefficients by a real +other+, returning new vector.
|
|
97
|
+
#
|
|
98
|
+
# This effectively multiplies {#magnitude} by +other+.
|
|
99
|
+
#
|
|
100
|
+
# @example
|
|
101
|
+
# VectorNumber[5] * 2 # => (10)
|
|
102
|
+
# VectorNumber["a", "b", 6].mult(2) # => (2⋅'a' + 2⋅'b' + 12)
|
|
103
|
+
# VectorNumber["a"] * VectorNumber[2] # => (2⋅'a')
|
|
104
|
+
# # Can't multiply by a non-real:
|
|
105
|
+
# VectorNumber["a"] * VectorNumber["b"] # RangeError
|
|
106
|
+
# @example numeric types can be multiplied in reverse
|
|
107
|
+
# 2 * VectorNumber[5] # => (10)
|
|
108
|
+
# 2 * VectorNumber["a"] # => (2⋅'a')
|
|
109
|
+
#
|
|
110
|
+
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
111
|
+
# @return [VectorNumber]
|
|
112
|
+
# @raise [RangeError] if +other+ is not a number or +other+ can't be multiplied by this one
|
|
113
|
+
#
|
|
114
|
+
# @since 0.2.1
|
|
115
|
+
def *(other)
|
|
116
|
+
if real_number?(other)
|
|
156
117
|
other = other.real
|
|
157
|
-
# Prevent integer division, but without loss of accuracy.
|
|
158
|
-
other = Rational(other) if other.integer?
|
|
159
118
|
# @type var other: Float
|
|
160
|
-
new { _1
|
|
119
|
+
new { _1 * other }
|
|
120
|
+
elsif real_number?(self) && other.is_a?(self.class)
|
|
121
|
+
# @type var other: untyped
|
|
122
|
+
other * self
|
|
123
|
+
else
|
|
124
|
+
raise RangeError, "can't multiply #{self} and #{other}"
|
|
161
125
|
end
|
|
126
|
+
end
|
|
162
127
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
# to fix syntax highlighting: /
|
|
128
|
+
# @since 0.3.0
|
|
129
|
+
alias mult *
|
|
166
130
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
131
|
+
# Divide all coefficients by a real +other+, returning new vector.
|
|
132
|
+
#
|
|
133
|
+
# This effectively multiplies {#magnitude} by reciprocal of +other+.
|
|
134
|
+
# @note This method never does integer division.
|
|
135
|
+
#
|
|
136
|
+
# @example
|
|
137
|
+
# VectorNumber[10] / 2 # => (5)
|
|
138
|
+
# VectorNumber["a", "b", 6].quo(2) # => (1/2⋅'a' + 1/2⋅'b' + 3/1)
|
|
139
|
+
# VectorNumber["a"] / VectorNumber[2] # => (1/2⋅'a')
|
|
140
|
+
# # Can't divide by a non-real:
|
|
141
|
+
# VectorNumber["a"] / VectorNumber["b"] # RangeError
|
|
142
|
+
# @example numeric types can be divided in reverse
|
|
143
|
+
# 2 / VectorNumber[10] # => (1/5)
|
|
144
|
+
# # Can't divide by a non-real:
|
|
145
|
+
# 2 / VectorNumber["a"] # RangeError
|
|
146
|
+
#
|
|
147
|
+
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
148
|
+
# @return [VectorNumber]
|
|
149
|
+
# @raise [RangeError] if +other+ is not a number or is not a real number
|
|
150
|
+
# @raise [ZeroDivisionError] if +other+ is zero
|
|
151
|
+
#
|
|
152
|
+
# @since 0.2.1
|
|
153
|
+
def /(other)
|
|
154
|
+
check_divisibility(other)
|
|
191
155
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
156
|
+
other = other.real
|
|
157
|
+
# Prevent integer division, but without loss of accuracy.
|
|
158
|
+
other = Rational(other) if other.integer?
|
|
159
|
+
# @type var other: Float
|
|
160
|
+
new { _1 / other }
|
|
161
|
+
end
|
|
195
162
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
#
|
|
200
|
-
# @example
|
|
201
|
-
# VectorNumber[10].div(3) # => (3)
|
|
202
|
-
# VectorNumber["a"].div(2) # => (0⋅'a')
|
|
203
|
-
# VectorNumber["a"].div(VectorNumber[2]) # => (0⋅'a')
|
|
204
|
-
# # Can't divide by a non-real:
|
|
205
|
-
# VectorNumber["a"].div(VectorNumber["b"]) # RangeError
|
|
206
|
-
# @example numeric types can be divided in reverse
|
|
207
|
-
# 2.div(VectorNumber[10]) # => (0)
|
|
208
|
-
# # Can't divide by a non-real:
|
|
209
|
-
# 2.div(VectorNumber["a"]) # RangeError
|
|
210
|
-
#
|
|
211
|
-
# @see #divmod
|
|
212
|
-
# @see #%
|
|
213
|
-
#
|
|
214
|
-
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
215
|
-
# @return [VectorNumber]
|
|
216
|
-
# @raise [RangeError] if +other+ is not a number or is not a real number
|
|
217
|
-
# @raise [ZeroDivisionError] if +other+ is zero
|
|
218
|
-
#
|
|
219
|
-
# @since 0.2.6
|
|
220
|
-
def div(other)
|
|
221
|
-
check_divisibility(other)
|
|
163
|
+
# @since 0.2.6
|
|
164
|
+
alias quo /
|
|
165
|
+
# to fix syntax highlighting: /
|
|
222
166
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
167
|
+
# Divide all coefficients by a real +other+ using +fdiv+,
|
|
168
|
+
# returning new vector with decimal coefficients.
|
|
169
|
+
#
|
|
170
|
+
# There isn't much benefit to this method, as {#/} doesn't do integer division,
|
|
171
|
+
# but it is provided for consistency.
|
|
172
|
+
#
|
|
173
|
+
# @example
|
|
174
|
+
# VectorNumber[10].fdiv(2) # => (5.0)
|
|
175
|
+
# VectorNumber["a", "b", 6].fdiv(2) # => (0.5⋅'a' + 0.5⋅'b' + 3.0)
|
|
176
|
+
# VectorNumber["a"].fdiv(VectorNumber[2]) # => (0.5⋅'a')
|
|
177
|
+
# # Can't divide by a non-real:
|
|
178
|
+
# VectorNumber["a"].fdiv(VectorNumber["b"]) # RangeError
|
|
179
|
+
# @example reverse division may return non-vector results
|
|
180
|
+
# 2.fdiv(VectorNumber[10]) # => 0.2 (Float)
|
|
181
|
+
# 2.0.fdiv(VectorNumber[10]) # => (0.2) (VectorNumber)
|
|
182
|
+
#
|
|
183
|
+
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
184
|
+
# @return [VectorNumber]
|
|
185
|
+
# @raise [RangeError] if +other+ is not a number or is not a real number
|
|
186
|
+
# @raise [ZeroDivisionError] if +other+ is zero
|
|
187
|
+
#
|
|
188
|
+
# @since 0.2.1
|
|
189
|
+
def fdiv(other)
|
|
190
|
+
check_divisibility(other)
|
|
226
191
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
# or, alternatively, +self - other * self.div(other)+.
|
|
231
|
-
#
|
|
232
|
-
# @example
|
|
233
|
-
# VectorNumber[10] % 3 # => (1)
|
|
234
|
-
# VectorNumber["a", "b", 6].modulo(2) # => (1⋅'a' + 1⋅'b')
|
|
235
|
-
# -VectorNumber["a"] % VectorNumber[2] # => (1⋅'a')
|
|
236
|
-
# # Can't divide by a non-real:
|
|
237
|
-
# VectorNumber["a"] % VectorNumber["b"] # RangeError
|
|
238
|
-
# @example numeric types can be divided in reverse
|
|
239
|
-
# 3 % VectorNumber[10] # => (3)
|
|
240
|
-
# # Can't divide by a non-real:
|
|
241
|
-
# 3 % VectorNumber["a"] # RangeError
|
|
242
|
-
# @example compare to #remainder
|
|
243
|
-
# VectorNumber[-5] % 3 # => (1)
|
|
244
|
-
# VectorNumber[-5].remainder(3) # => (-2)
|
|
245
|
-
#
|
|
246
|
-
# @see #divmod
|
|
247
|
-
# @see #div
|
|
248
|
-
# @see #remainder
|
|
249
|
-
# @see Numeric#%
|
|
250
|
-
#
|
|
251
|
-
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
252
|
-
# @return [VectorNumber]
|
|
253
|
-
# @raise [RangeError] if +other+ is not a number or is not a real number
|
|
254
|
-
# @raise [ZeroDivisionError] if +other+ is zero
|
|
255
|
-
#
|
|
256
|
-
# @since 0.2.6
|
|
257
|
-
def %(other)
|
|
258
|
-
check_divisibility(other)
|
|
192
|
+
other = other.real
|
|
193
|
+
new { _1.fdiv(other) }
|
|
194
|
+
end
|
|
259
195
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
196
|
+
# Divide all coefficients by a real +other+,
|
|
197
|
+
# converting results to integers using +#floor+.
|
|
198
|
+
#
|
|
199
|
+
# This is requal to +(self / other).floor+.
|
|
200
|
+
#
|
|
201
|
+
# @example
|
|
202
|
+
# VectorNumber[10].div(3) # => (3)
|
|
203
|
+
# VectorNumber["a"].div(2) # => (0⋅'a')
|
|
204
|
+
# VectorNumber["a"].div(VectorNumber[2]) # => (0⋅'a')
|
|
205
|
+
# # Can't divide by a non-real:
|
|
206
|
+
# VectorNumber["a"].div(VectorNumber["b"]) # RangeError
|
|
207
|
+
# @example numeric types can be divided in reverse
|
|
208
|
+
# 2.div(VectorNumber[10]) # => (0)
|
|
209
|
+
# # Can't divide by a non-real:
|
|
210
|
+
# 2.div(VectorNumber["a"]) # RangeError
|
|
211
|
+
#
|
|
212
|
+
# @see #divmod
|
|
213
|
+
# @see #%
|
|
214
|
+
# @see #floor
|
|
215
|
+
#
|
|
216
|
+
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
217
|
+
# @return [VectorNumber]
|
|
218
|
+
# @raise [RangeError] if +other+ is not a number or is not a real number
|
|
219
|
+
# @raise [ZeroDivisionError] if +other+ is zero
|
|
220
|
+
#
|
|
221
|
+
# @since 0.2.6
|
|
222
|
+
def div(other)
|
|
223
|
+
check_divisibility(other)
|
|
263
224
|
|
|
264
|
-
|
|
265
|
-
|
|
225
|
+
other = other.real
|
|
226
|
+
new { _1.div(other) }
|
|
227
|
+
end
|
|
266
228
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
229
|
+
# Return the modulus of dividing self by a real +other+ as a vector.
|
|
230
|
+
#
|
|
231
|
+
# This is equal to +self - other * (self/other).floor+,
|
|
232
|
+
# or, alternatively, +self - other * self.div(other)+.
|
|
233
|
+
#
|
|
234
|
+
# @example
|
|
235
|
+
# VectorNumber[10] % 3 # => (1)
|
|
236
|
+
# VectorNumber["a", "b", 6].modulo(2) # => (1⋅'a' + 1⋅'b')
|
|
237
|
+
# -VectorNumber["a"] % VectorNumber[2] # => (1⋅'a')
|
|
238
|
+
# # Can't divide by a non-real:
|
|
239
|
+
# VectorNumber["a"] % VectorNumber["b"] # RangeError
|
|
240
|
+
# @example numeric types can be divided in reverse
|
|
241
|
+
# 3 % VectorNumber[10] # => (3)
|
|
242
|
+
# # Can't divide by a non-real:
|
|
243
|
+
# 3 % VectorNumber["a"] # RangeError
|
|
244
|
+
# @example compare to #remainder
|
|
245
|
+
# VectorNumber[-5] % 3 # => (1)
|
|
246
|
+
# VectorNumber[-5].remainder(3) # => (-2)
|
|
247
|
+
#
|
|
248
|
+
# @see #divmod
|
|
249
|
+
# @see #div
|
|
250
|
+
# @see #remainder
|
|
251
|
+
# @see Numeric#%
|
|
252
|
+
#
|
|
253
|
+
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
254
|
+
# @return [VectorNumber]
|
|
255
|
+
# @raise [RangeError] if +other+ is not a number or is not a real number
|
|
256
|
+
# @raise [ZeroDivisionError] if +other+ is zero
|
|
257
|
+
#
|
|
258
|
+
# @since 0.2.6
|
|
259
|
+
def %(other)
|
|
260
|
+
check_divisibility(other)
|
|
293
261
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
#
|
|
298
|
-
# @example
|
|
299
|
-
# VectorNumber[10].remainder(3) # => (1)
|
|
300
|
-
# VectorNumber["a"].remainder(2) # => (1⋅'a')
|
|
301
|
-
# -VectorNumber["a"].remainder(VectorNumber[2]) # => (-1⋅'a')
|
|
302
|
-
# # Can't divide by a non-real:
|
|
303
|
-
# VectorNumber["a"].remainder(VectorNumber["b"]) # RangeError
|
|
304
|
-
# @example numeric types can be divided in reverse
|
|
305
|
-
# 3.remainder(VectorNumber[10]) # => (3)
|
|
306
|
-
# # Can't divide by a non-real:
|
|
307
|
-
# 3.remainder(VectorNumber["a"]) # RangeError
|
|
308
|
-
# @example compare to #%
|
|
309
|
-
# VectorNumber[-5] % 3 # => (1)
|
|
310
|
-
# VectorNumber[-5].remainder(3) # => (-2)
|
|
311
|
-
#
|
|
312
|
-
# @see #%
|
|
313
|
-
# @see Numeric#remainder
|
|
314
|
-
#
|
|
315
|
-
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
316
|
-
# @return [VectorNumber]
|
|
317
|
-
# @raise [RangeError] if +other+ is not a number or is not a real number
|
|
318
|
-
# @raise [ZeroDivisionError] if +other+ is zero
|
|
319
|
-
#
|
|
320
|
-
# @since 0.2.6
|
|
321
|
-
def remainder(other)
|
|
322
|
-
check_divisibility(other)
|
|
262
|
+
other = other.real
|
|
263
|
+
new { _1 % other }
|
|
264
|
+
end
|
|
323
265
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
end
|
|
266
|
+
# @since 0.2.6
|
|
267
|
+
alias modulo %
|
|
327
268
|
|
|
328
|
-
|
|
269
|
+
# Return the quotient and modulus of dividing self by a real +other+.
|
|
270
|
+
# There is no performance benefit compared to calling {#div} and {#%} separately.
|
|
271
|
+
#
|
|
272
|
+
# @example
|
|
273
|
+
# VectorNumber[10].divmod(3) # => [(3), (1)]
|
|
274
|
+
# VectorNumber["a"].divmod(2) # => [(0⋅'a'), (1⋅'a')]
|
|
275
|
+
# VectorNumber["a"].divmod(VectorNumber[2]) # => [(0⋅'a'), (1⋅'a')]
|
|
276
|
+
# # Can't divide by a non-real:
|
|
277
|
+
# VectorNumber["a"].divmod(VectorNumber["b"]) # RangeError
|
|
278
|
+
# @example numeric types can be divided in reverse
|
|
279
|
+
# 3.divmod(VectorNumber[10]) # => [(0), (3)]
|
|
280
|
+
# # Can't divide by a non-real:
|
|
281
|
+
# 3.divmod(VectorNumber["a"]) # RangeError
|
|
282
|
+
#
|
|
283
|
+
# @see #div
|
|
284
|
+
# @see #%
|
|
285
|
+
#
|
|
286
|
+
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
287
|
+
# @return [Array(VectorNumber, VectorNumber)]
|
|
288
|
+
# @raise [RangeError] if +other+ is not a number or is not a real number
|
|
289
|
+
# @raise [ZeroDivisionError] if +other+ is zero
|
|
290
|
+
#
|
|
291
|
+
# @since 0.2.6
|
|
292
|
+
def divmod(other)
|
|
293
|
+
[div(other), modulo(other)]
|
|
294
|
+
end
|
|
329
295
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
296
|
+
# Return the remainder of dividing self by a real +other+ as a vector.
|
|
297
|
+
#
|
|
298
|
+
# This is equal to +self - other * (self/other).truncate+.
|
|
299
|
+
#
|
|
300
|
+
# @example
|
|
301
|
+
# VectorNumber[10].remainder(3) # => (1)
|
|
302
|
+
# VectorNumber["a"].remainder(2) # => (1⋅'a')
|
|
303
|
+
# -VectorNumber["a"].remainder(VectorNumber[2]) # => (-1⋅'a')
|
|
304
|
+
# # Can't divide by a non-real:
|
|
305
|
+
# VectorNumber["a"].remainder(VectorNumber["b"]) # RangeError
|
|
306
|
+
# @example numeric types can be divided in reverse
|
|
307
|
+
# 3.remainder(VectorNumber[10]) # => (3)
|
|
308
|
+
# # Can't divide by a non-real:
|
|
309
|
+
# 3.remainder(VectorNumber["a"]) # RangeError
|
|
310
|
+
# @example compare to #%
|
|
311
|
+
# VectorNumber[-5] % 3 # => (1)
|
|
312
|
+
# VectorNumber[-5].remainder(3) # => (-2)
|
|
313
|
+
#
|
|
314
|
+
# @see #%
|
|
315
|
+
# @see Numeric#remainder
|
|
316
|
+
#
|
|
317
|
+
# @param other [Integer, Float, Rational, BigDecimal, VectorNumber]
|
|
318
|
+
# @return [VectorNumber]
|
|
319
|
+
# @raise [RangeError] if +other+ is not a number or is not a real number
|
|
320
|
+
# @raise [ZeroDivisionError] if +other+ is zero
|
|
321
|
+
#
|
|
322
|
+
# @since 0.2.6
|
|
323
|
+
def remainder(other)
|
|
324
|
+
check_divisibility(other)
|
|
325
|
+
|
|
326
|
+
other = other.real
|
|
327
|
+
new { _1.remainder(other) }
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
private
|
|
331
|
+
|
|
332
|
+
# @raise [RangeError] unless +other+ is a real number
|
|
333
|
+
# @raise [ZeroDivisionError]
|
|
334
|
+
def check_divisibility(other)
|
|
335
|
+
raise RangeError, "can't divide #{self} by #{other.inspect}", caller unless real_number?(other)
|
|
336
|
+
raise ZeroDivisionError, "divided by 0", caller if other.zero?
|
|
344
337
|
end
|
|
345
338
|
end
|