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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 686890049523273762a1dea1835f990e987d556bf9399356cf53572727df7ad9
|
|
4
|
+
data.tar.gz: 7c90c791c17eb9ffdcb1455174141ca857456642770acdff2e9d2ee3e19e4fab
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d22a64381f58d7c8a1dd858510734e960326af64ca9f1d109c7fceee0f7e7fd2dfee2df7ba5b7a16fe5fc67dd1b192c60caa069215c20c03e231cee050a9acd0
|
|
7
|
+
data.tar.gz: 1c2de92ef2ae14f127c0fcd121ad361cb552875999a9c3eba31d90896fb104448c925793b34d47695785042a6a03420605d4ba017c91683348ac47f074cc7c86
|
data/README.md
CHANGED
|
@@ -18,12 +18,7 @@ Features:
|
|
|
18
18
|
- Enjoy a mix of vector-, complex- and polynomial-like behavior at appropriate times.
|
|
19
19
|
- No dependencies, no extensions. It just works!
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
- [vector_space](https://github.com/tomstuart/vector_space) aims to provide typed vector spaces with limited dimensions and nice formatting;
|
|
23
|
-
- [named_vector](https://rubygems.org/gems/named_vector) provides simple vectors with named dimensions;
|
|
24
|
-
- various quaternion libraries like [quaternion](https://github.com/tanahiro/quaternion) or [rmath3d](https://github.com/vaiorabbit/rmath3d).
|
|
25
|
-
|
|
26
|
-
However, none of them have been updated in *years*.
|
|
21
|
+
Other people have created some similar gems over the years, like [vector_space](https://github.com/tomstuart/vector_space) or [named_vector](https://rubygems.org/gems/named_vector) but they don't have the characterics that I wanted, and none of them have been updated in *years*.
|
|
27
22
|
|
|
28
23
|
## Table of contents
|
|
29
24
|
|
|
@@ -31,10 +26,12 @@ However, none of them have been updated in *years*.
|
|
|
31
26
|
- [Ruby engine support status](#ruby-engine-support-status)
|
|
32
27
|
- [Usage](#usage)
|
|
33
28
|
- [Basics](#basics)
|
|
29
|
+
- [Getting values back](#getting-values-back)
|
|
34
30
|
- [(Somewhat) advanced usage](#somewhat-advanced-usage)
|
|
35
31
|
- [Frozenness](#frozenness)
|
|
36
32
|
- [Numerical behavior](#numerical-behavior)
|
|
37
33
|
- [Enumeration and hash-like behavior](#enumeration-and-hash-like-behavior)
|
|
34
|
+
- [Conceptual basis](#conceptual-basis)
|
|
38
35
|
- [Development](#development)
|
|
39
36
|
- [Contributing](#contributing)
|
|
40
37
|
- [License](#license)
|
|
@@ -54,8 +51,8 @@ gem "vector_number"
|
|
|
54
51
|
### Ruby engine support status
|
|
55
52
|
|
|
56
53
|
VectorNumber is developed on MRI (CRuby) but should work on other engines too.
|
|
57
|
-
- TruffleRuby:
|
|
58
|
-
- JRuby:
|
|
54
|
+
- TruffleRuby: minor differences in behavior, but otherwise works as expected.
|
|
55
|
+
- JRuby: minor differences in behavior, but otherwise works as expected.
|
|
59
56
|
- Other engines: untested, but should work, depending on compatibility with MRI.
|
|
60
57
|
|
|
61
58
|
## Usage
|
|
@@ -66,12 +63,12 @@ VectorNumber is developed on MRI (CRuby) but should work on other engines too.
|
|
|
66
63
|
|
|
67
64
|
### Basics
|
|
68
65
|
|
|
69
|
-
VectorNumbers are mostly useful for
|
|
66
|
+
VectorNumbers are mostly useful for summing up heterogeneous objects:
|
|
70
67
|
```ruby
|
|
71
|
-
sum = [4
|
|
72
|
-
sum # => (17 + 2⋅
|
|
73
|
-
sum.to_h # => {1=>17, "death"=>2, nil=>1}
|
|
74
|
-
sum.to_a # => [[1, 17], ["death", 2], [nil, 1]]
|
|
68
|
+
sum = VectorNumber[4] + "death" + "death" + nil
|
|
69
|
+
sum # => (17 + 2⋅"death" + 1⋅)
|
|
70
|
+
sum.to_h # => {unit/1 => 17, "death" => 2, nil => 1}
|
|
71
|
+
sum.to_a # => [[unit/1, 17], ["death", 2], [nil, 1]]
|
|
75
72
|
|
|
76
73
|
# Alternatively, the same result can be equivalently (and more efficiently)
|
|
77
74
|
# achieved by passing all values to a constructor:
|
|
@@ -81,17 +78,36 @@ VectorNumber.new([4, "death", "death", 13, nil])
|
|
|
81
78
|
|
|
82
79
|
Doing arithmetic with vectors is simple and intuitive:
|
|
83
80
|
```ruby
|
|
84
|
-
VectorNumber["string"] + "string" # => (2⋅
|
|
85
|
-
VectorNumber["string"] - "str" # => (1⋅
|
|
86
|
-
VectorNumber[5] + VectorNumber["string"] - 0.5 # => (4.5 + 1⋅
|
|
87
|
-
VectorNumber["string", "string", "string", "str"] # => (3⋅
|
|
81
|
+
VectorNumber["string"] + "string" # => (2⋅"string")
|
|
82
|
+
VectorNumber["string"] - "str" # => (1⋅"string" - 1⋅"str")
|
|
83
|
+
VectorNumber[5] + VectorNumber["string"] - 0.5 # => (4.5 + 1⋅"string")
|
|
84
|
+
VectorNumber["string", "string", "string", "str"] # => (3⋅"string" + 1⋅"str")
|
|
88
85
|
# Multiply and divide by any real number:
|
|
89
|
-
VectorNumber[:s] * 2 + VectorNumber["string"] * 0.3 # => (2⋅s + 0.3⋅
|
|
86
|
+
VectorNumber[:s] * 2 + VectorNumber["string"] * 0.3 # => (2⋅s + 0.3⋅"string")
|
|
90
87
|
VectorNumber[:s] / VectorNumber[3] # => (1/3⋅s)
|
|
91
|
-
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Ruby numbers rely on `#coerce` to promote values to a common type. This allows using regular numbers as first operand in arithmetic operations:
|
|
91
|
+
```ruby
|
|
92
|
+
2 + VectorNumber["string"] # => (2 + 1⋅"string")
|
|
92
93
|
1/3r * VectorNumber[[]] # => (1/3⋅[])
|
|
94
|
+
13 / VectorNumber[2] # => (13/2)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
> [!NOTE]
|
|
98
|
+
> VectorNumbers don't perform "integer division" to prevent unexpected loss of precision. `#div` and rounding methods can achieve this if required.
|
|
99
|
+
|
|
100
|
+
#### Getting values back
|
|
101
|
+
The simplest way to get a value for a specific unit is to use the `#[]` method:
|
|
102
|
+
```ruby
|
|
103
|
+
VectorNumber["string", "string", "string", "str"]["string"] # => 3
|
|
104
|
+
VectorNumber["string", "string", "string", "str"]["str"] # => 1
|
|
105
|
+
VectorNumber["string", "string", "string", "str"]["nonexistent"] # => 0
|
|
93
106
|
```
|
|
94
107
|
|
|
108
|
+
> [!NOTE]
|
|
109
|
+
> Accessing a unit that doesn't exist returns 0, not `nil` as you might expect.
|
|
110
|
+
|
|
95
111
|
### (Somewhat) advanced usage
|
|
96
112
|
|
|
97
113
|
> [!TIP]
|
|
@@ -118,8 +134,17 @@ VectorNumbers implement `each` (`each_pair`) in the same way as Hash does, allow
|
|
|
118
134
|
|
|
119
135
|
There are also the usual `[]`, `unit?` (`key?`), `units` (`keys`), `coefficients` (`values`) methods. `to_h` and `to_a` can be used if a regular Hash or Array is needed.
|
|
120
136
|
|
|
121
|
-
|
|
122
|
-
|
|
137
|
+
## Conceptual basis
|
|
138
|
+
|
|
139
|
+
VectorNumbers are based on the concept of a vector space over the field of real numbers (real vector space). In the case of VectorNumber, the dimensionality of the vector space is countably infinite, as most distinct objects in Ruby signify a separate dimension.
|
|
140
|
+
|
|
141
|
+
For most dimensions, an object is that distinct dimension's unit. There are two exceptions currently: real unit (1) and imaginary unit (i) which define the real and imaginary dimensions and subsume all real and complex numbers. A VectorNumber can not be a unit itself. Distinction of objects is determined by `eql?`, same as for Hash.
|
|
142
|
+
|
|
143
|
+
Length of a VectorNumber in any given dimension is given by a real number, called its coefficient. All dimensions are linearly independent — change in one coefficient does not affect any other coefficient. There is no distinction between a dimension explicitly specified as having a 0 coefficient (or arriving at 0 through calculation) and a dimension not specified at all.
|
|
144
|
+
|
|
145
|
+
This might be more easily imagined as a geometric vector. For example, this is a graphic representation of a vector `3 * VectorNumber[1] + 2 * VectorNumber[1i] + 3 * VectorNumber["string"] + 4.5 * VectorNumber[[1,2,3]]` in the vector space:
|
|
146
|
+
|
|
147
|
+

|
|
123
148
|
|
|
124
149
|
## Development
|
|
125
150
|
|
|
@@ -147,4 +172,4 @@ Bug reports and pull requests are welcome on GitHub at [https://github.com/trini
|
|
|
147
172
|
|
|
148
173
|
## License
|
|
149
174
|
|
|
150
|
-
This gem is available as open source under the terms of the
|
|
175
|
+
This gem is available as open source under the terms of the MIT License, see [LICENSE.txt](https://github.com/trinistr/vector_number/blob/main/LICENSE.txt).
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<svg width="500" height="400" viewBox="-250 -200 500 400" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<style>
|
|
3
|
+
text {
|
|
4
|
+
font-family: 'Arial', sans-serif;
|
|
5
|
+
font-size: 14px;
|
|
6
|
+
}
|
|
7
|
+
.axis-label {
|
|
8
|
+
font-weight: bold;
|
|
9
|
+
font-size: 16px;
|
|
10
|
+
}
|
|
11
|
+
.dim-label {
|
|
12
|
+
font-size: 12px;
|
|
13
|
+
fill: #666;
|
|
14
|
+
}
|
|
15
|
+
</style>
|
|
16
|
+
|
|
17
|
+
<!-- Background -->
|
|
18
|
+
<rect x="-250" y="-200" width="500" height="400" fill="#fff0cc"/>
|
|
19
|
+
|
|
20
|
+
<!-- Coordinate system center -->
|
|
21
|
+
<circle cx="0" cy="0" r="5" fill="#000"/>
|
|
22
|
+
<text x="-50" y="-5" class="dim-label">(0,0,...)</text>
|
|
23
|
+
|
|
24
|
+
<!-- 1 (numeric) axis -->
|
|
25
|
+
<line x1="0" y1="0" x2="150" y2="0" stroke="#2196F3" stroke-width="2"/>
|
|
26
|
+
<polygon points="155,0 145,-4 145,4" fill="#2196F3"/>
|
|
27
|
+
<text x="160" y="5" class="axis-label">1</text>
|
|
28
|
+
|
|
29
|
+
<!-- i (imaginary) axis -->
|
|
30
|
+
<line x1="0" y1="0" x2="0" y2="-150" stroke="#4CAF50" stroke-width="2"/>
|
|
31
|
+
<polygon points="0,-155 -4,-145 4,-145" fill="#4CAF50"/>
|
|
32
|
+
<text x="10" y="-145" class="axis-label">i</text>
|
|
33
|
+
|
|
34
|
+
<!-- [1,2,3] axis -->
|
|
35
|
+
<line x1="0" y1="0" x2="-150" y2="150" stroke="#FF9800" stroke-width="2"/>
|
|
36
|
+
<polygon points="-154,154 -150,144 -144,150" fill="#FF9800"/>
|
|
37
|
+
<text x="-205" y="140" class="axis-label">[1,2,3]</text>
|
|
38
|
+
|
|
39
|
+
<!-- "string" axis -->
|
|
40
|
+
<line x1="0" y1="0" x2="100" y2="150" stroke="#9C27B0" stroke-width="2"/>
|
|
41
|
+
<polygon points="103,155 101,144 93,149" fill="#9C27B0"/>
|
|
42
|
+
<text x="110" y="160" class="axis-label">"string"</text>
|
|
43
|
+
|
|
44
|
+
<!-- VectorNumber -->
|
|
45
|
+
<line x1="0" y1="0" x2="118" y2="-78" stroke="#F44336" stroke-width="3"/>
|
|
46
|
+
<polygon points="120,-80 107,-78 113,-68" fill="#F44336"/>
|
|
47
|
+
<text x="120" y="-90" text-anchor="middle" font-weight="bold" fill="#F44336">
|
|
48
|
+
(3 + 2i + 3⋅"string" + 4.5⋅[1,2,3])
|
|
49
|
+
</text>
|
|
50
|
+
|
|
51
|
+
<!-- Projection lines to axes -->
|
|
52
|
+
<!-- To numeric axis -->
|
|
53
|
+
<line x1="120" y1="-80" x2="120" y2="0" stroke="#2196F3" stroke-width="1" stroke-dasharray="5,5"/>
|
|
54
|
+
<circle cx="120" cy="0" r="3" fill="#2196F3"/>
|
|
55
|
+
<text x="120" y="15" class="dim-label">3</text>
|
|
56
|
+
|
|
57
|
+
<!-- To imaginary axis -->
|
|
58
|
+
<line x1="120" y1="-80" x2="0" y2="-80" stroke="#4CAF50" stroke-width="1" stroke-dasharray="5,5"/>
|
|
59
|
+
<circle cx="0" cy="-80" r="3" fill="#4CAF50"/>
|
|
60
|
+
<text x="-15" y="-80" class="dim-label">2</text>
|
|
61
|
+
|
|
62
|
+
<!-- To [1,2,3] axis -->
|
|
63
|
+
<line x1="120" y1="-80" x2="-90" y2="90" stroke="#FF9800" stroke-width="1" stroke-dasharray="5,5"/>
|
|
64
|
+
<circle cx="-90" cy="90" r="3" fill="#FF9800"/>
|
|
65
|
+
<text x="-115" y="90" class="dim-label">4.5</text>
|
|
66
|
+
|
|
67
|
+
<!-- To "string" axis -->
|
|
68
|
+
<line x1="120" y1="-80" x2="55" y2="83" stroke="#9C27B0" stroke-width="1" stroke-dasharray="5,5"/>
|
|
69
|
+
<circle cx="55" cy="83" r="3" fill="#9C27B0"/>
|
|
70
|
+
<text x="45" y="95" class="dim-label">3</text>
|
|
71
|
+
|
|
72
|
+
<!-- Legend -->
|
|
73
|
+
<rect x="-220" y="-180" width="180" height="145" fill="white" stroke="#ccc" stroke-width="1"/>
|
|
74
|
+
|
|
75
|
+
<line x1="-210" y1="-160" x2="-202" y2="-168" stroke="#F44336" stroke-width="3"/>
|
|
76
|
+
<polygon points="-200,-170 -205,-169 -201,-165" fill="#F44336"/>
|
|
77
|
+
<text x="-190" y="-160">VectorNumber</text>
|
|
78
|
+
|
|
79
|
+
<line x1="-212" y1="-145" x2="-200" y2="-145" stroke="#2196F3" stroke-width="2"/>
|
|
80
|
+
<text x="-190" y="-140">Real dimension</text>
|
|
81
|
+
|
|
82
|
+
<line x1="-212" y1="-125" x2="-200" y2="-125" stroke="#4CAF50" stroke-width="2"/>
|
|
83
|
+
<text x="-190" y="-120">Imaginary dimension</text>
|
|
84
|
+
|
|
85
|
+
<line x1="-212" y1="-105" x2="-200" y2="-105" stroke="#9C27B0" stroke-width="2"/>
|
|
86
|
+
<text x="-190" y="-100">"string" dimension</text>
|
|
87
|
+
|
|
88
|
+
<line x1="-212" y1="-85" x2="-200" y2="-85" stroke="#FF9800" stroke-width="2"/>
|
|
89
|
+
<text x="-190" y="-80">[1,2,3] dimension</text>
|
|
90
|
+
|
|
91
|
+
<line x1="-212" y1="-65" x2="-200" y2="-65" stroke="gray" stroke-width="2"/>
|
|
92
|
+
<text x="-190" y="-60">Zero dimensions</text>
|
|
93
|
+
<text x="-190" y="-45">(not portrayed)</text>
|
|
94
|
+
</svg>
|
|
@@ -1,125 +1,121 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class VectorNumber
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# +Comparable+ is included for parity with
|
|
4
|
+
# @group Comparing
|
|
5
|
+
|
|
6
|
+
# +Comparable+ is included for parity with +Numeric+.
|
|
7
7
|
# @example using Comparable methods
|
|
8
8
|
# VectorNumber[12] < 0 # => false
|
|
9
9
|
# VectorNumber[12, "a"] < 0 # ArgumentError
|
|
10
10
|
# (VectorNumber[12]..VectorNumber[15]).include?(13) # => true
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
#
|
|
12
|
+
# @since 0.2.0
|
|
13
|
+
include ::Comparable
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
15
|
+
# Test whether +other+ has the same value with +==+ semantics.
|
|
16
|
+
#
|
|
17
|
+
# Values are considered equal if
|
|
18
|
+
# - +other+ is a VectorNumber and it has the same units and equal coefficients, or
|
|
19
|
+
# - +other+ is a Numeric equal in value to this (real or complex) number.
|
|
20
|
+
#
|
|
21
|
+
# @example
|
|
22
|
+
# VectorNumber[3.13] == 3.13 # => true
|
|
23
|
+
# VectorNumber[1.4, 1.5i] == Complex(1.4, 1.5) # => true
|
|
24
|
+
# VectorNumber["a", "b", "c"] == VectorNumber["c", "b", "a"] # => true
|
|
25
|
+
# VectorNumber["a", 14] == 14 # => false
|
|
26
|
+
# VectorNumber["a"] == "a" # => false
|
|
27
|
+
#
|
|
28
|
+
# @param other [Object]
|
|
29
|
+
# @return [Boolean]
|
|
30
|
+
#
|
|
31
|
+
# @since 0.2.0
|
|
32
|
+
def ==(other)
|
|
33
|
+
return true if equal?(other)
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
case other
|
|
36
|
+
when VectorNumber
|
|
37
|
+
size == other.size && @data == other.to_h
|
|
38
|
+
when Numeric
|
|
39
|
+
numeric?(2) && other.real == real && other.imaginary == imaginary
|
|
40
|
+
else
|
|
41
|
+
# Can't compare a number-like value to a non-number.
|
|
42
|
+
false
|
|
42
43
|
end
|
|
44
|
+
end
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
# @since 0.1.0
|
|
63
|
-
def eql?(other)
|
|
64
|
-
return true if equal?(other)
|
|
46
|
+
# Test whether +other+ is VectorNumber and has the same value with +eql?+ semantics.
|
|
47
|
+
#
|
|
48
|
+
# Values are considered equal only if +other+ is a VectorNumber
|
|
49
|
+
# and it has exactly the same units and coefficients, though possibly in a different order.
|
|
50
|
+
# Additionally, `a.eql?(b)` implies `a.hash == b.hash`.
|
|
51
|
+
#
|
|
52
|
+
# @example
|
|
53
|
+
# VectorNumber["a", "b", "c"].eql? VectorNumber["c", "b", "a"] # => true
|
|
54
|
+
# VectorNumber[3.13].eql? 3.13 # => false
|
|
55
|
+
# VectorNumber[1.4, 1.5i].eql? Complex(1.4, 1.5) # => false
|
|
56
|
+
# VectorNumber["a", 14].eql? 14 # => false
|
|
57
|
+
# VectorNumber["a"].eql? "a" # => false
|
|
58
|
+
#
|
|
59
|
+
# @param other [Object]
|
|
60
|
+
# @return [Boolean]
|
|
61
|
+
def eql?(other)
|
|
62
|
+
return true if equal?(other)
|
|
63
|
+
return false unless other.is_a?(VectorNumber)
|
|
65
64
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
else
|
|
69
|
-
false
|
|
70
|
-
end
|
|
71
|
-
end
|
|
65
|
+
size.eql?(other.size) && @data.eql?(other.to_h)
|
|
66
|
+
end
|
|
72
67
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
[self.class, @data].hash
|
|
87
|
-
end
|
|
68
|
+
# Generate an Integer hash value for self.
|
|
69
|
+
#
|
|
70
|
+
# @example
|
|
71
|
+
# VectorNumber["b", "a"].hash # => 3081872088394655324
|
|
72
|
+
# VectorNumber["a", "b"].hash # => 3081872088394655324
|
|
73
|
+
# VectorNumber["b", "c"].hash # => -1002381358514682371
|
|
74
|
+
#
|
|
75
|
+
# @return [Integer]
|
|
76
|
+
#
|
|
77
|
+
# @since 0.4.2
|
|
78
|
+
def hash
|
|
79
|
+
[self.class, @data].hash
|
|
80
|
+
end
|
|
88
81
|
|
|
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
|
-
|
|
82
|
+
# Compare to +other+ and return -1, 0, or 1
|
|
83
|
+
# if +self+ is less than, equal, or larger than +other+ on real number line,
|
|
84
|
+
# or +nil+ if any or both values are non-real.
|
|
85
|
+
#
|
|
86
|
+
# Most VectorNumbers are non-real and therefore not comparable with this method.
|
|
87
|
+
#
|
|
88
|
+
# @example
|
|
89
|
+
# VectorNumber[130] <=> 12 # => 1
|
|
90
|
+
# 1 <=> VectorNumber[13] # => -1
|
|
91
|
+
# VectorNumber[12.1] <=> Complex(12.1, 0) # => 0
|
|
92
|
+
# # This doesn't work as expected without NumericRefinements:
|
|
93
|
+
# Complex(12.1, 0) <=> VectorNumber[12.1] # => nil
|
|
94
|
+
#
|
|
95
|
+
# # Any non-real comparison returns nil:
|
|
96
|
+
# VectorNumber[12.1] <=> Complex(12.1, 1) # => nil
|
|
97
|
+
# VectorNumber[12.1i] <=> 2 # => nil
|
|
98
|
+
# VectorNumber["a"] <=> 2 # => nil
|
|
99
|
+
#
|
|
100
|
+
# @see #numeric?
|
|
101
|
+
# @see Comparable
|
|
102
|
+
# @see NumericRefinements
|
|
103
|
+
#
|
|
104
|
+
# @param other [Object]
|
|
105
|
+
# @return [Integer]
|
|
106
|
+
# @return [nil] if +self+ or +other+ isn't a real number.
|
|
107
|
+
#
|
|
108
|
+
# @since 0.2.0
|
|
109
|
+
def <=>(other)
|
|
110
|
+
return nil unless numeric?(1)
|
|
114
111
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
end
|
|
112
|
+
case other
|
|
113
|
+
when VectorNumber
|
|
114
|
+
other.numeric?(1) ? real <=> other.real : nil
|
|
115
|
+
when Numeric
|
|
116
|
+
other.imaginary.zero? ? real <=> other.real : nil
|
|
117
|
+
else
|
|
118
|
+
nil
|
|
123
119
|
end
|
|
124
120
|
end
|
|
125
121
|
end
|