vector_number 0.3.0 → 0.3.1
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/CHANGELOG.md +47 -1
- data/LICENSE.txt +21 -0
- data/README.md +16 -7
- data/lib/vector_number/comparing.rb +55 -2
- data/lib/vector_number/converting.rb +86 -6
- data/lib/vector_number/enumerating.rb +70 -13
- data/lib/vector_number/math_converting.rb +66 -6
- data/lib/vector_number/mathing.rb +207 -33
- data/lib/vector_number/numeric_refinements.rb +33 -9
- data/lib/vector_number/querying.rb +84 -15
- data/lib/vector_number/stringifying.rb +31 -2
- data/lib/vector_number/version.rb +2 -2
- data/lib/vector_number.rb +97 -18
- data/sig/vector_number.rbs +3 -3
- metadata +12 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b935cacefb185478f7f923046b28589c6da2763574c315f19c6b8050cd5835e1
|
4
|
+
data.tar.gz: a93dd71a4de2d07255962e13a81a357c92f5a1653d916e95d5a54a99afa984a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d6ea64b09d12434470d65c7ff808b63b9ccc59cb1e479bc7659ed973a8f03a3fb137dfe3641163dc56b06163b7d0c472ed74af2f49f6623b866eff90961aa7c
|
7
|
+
data.tar.gz: 85a927c88c99533e434a185a239f2d129567adf8d2e8c4d8d62e6239560d889e24fc7d3e478039b6d8c4213596e9ea7a61da5d0ab867162f9fbe7bee4edf05e5
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
8
|
## [Next]
|
9
|
+
## [v0.3.1] — 2025-06-21
|
10
|
+
|
11
|
+
This is mostly a documentation update with a side of improved gemspec.
|
12
|
+
|
13
|
+
**Changed**
|
14
|
+
- Improve method documentation and unify documentation style across the board.
|
15
|
+
- Improve gemspec:
|
16
|
+
- change source code and changelog links to point to a tagged commit;
|
17
|
+
- add links to bugtracker and documentation (for appropriate version);
|
18
|
+
- properly add CHANGELOG.md to doc generation.
|
19
|
+
- Improve documentation for NumericRefinements to include examples and more info.
|
20
|
+
- `#dup` is now an alias of `#+@` with no change in function.
|
21
|
+
- `#abs` is now calculated from `#abs2` instead of the other way around to reduce errors.
|
22
|
+
|
23
|
+
**Fixed**
|
24
|
+
- Correct broken changelog link in gem metadata.
|
25
|
+
|
26
|
+
[Compare v0.3.0...main](https://github.com/trinistr/vector_number/compare/v0.3.0...main)
|
27
|
+
|
9
28
|
## [v0.3.0] — 2025-05-12
|
10
29
|
|
11
30
|
**Added**
|
@@ -18,7 +37,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
18
37
|
When creating new vector through any operation, participating vector's options
|
19
38
|
are copied to the new one. When several vectors are present, only first one matters.
|
20
39
|
- Both `#+@` and `#dup` are now aliases of `#itself` instead of full methods.
|
21
|
-
- [🚀 CI]
|
40
|
+
- [🚀 CI] "CI" workflow now reports status of all checks,
|
41
|
+
excluding allowed-to-fail workflows (currently JRuby and TruffleRuby).
|
42
|
+
|
43
|
+
[Compare v0.2.6...v0.3.0](https://github.com/trinistr/vector_number/compare/v0.2.6...v0.3.0)
|
22
44
|
|
23
45
|
## [v0.2.6] — 2025-04-30
|
24
46
|
|
@@ -33,11 +55,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
33
55
|
**Changed**
|
34
56
|
- [🚀 CI] Add Ruby 3.4 to CI.
|
35
57
|
|
58
|
+
[Compare v0.2.5...v0.2.6](https://github.com/trinistr/vector_number/compare/v0.2.5...v0.2.6)
|
59
|
+
|
36
60
|
## [v0.2.5] — 2025-02-26
|
37
61
|
|
38
62
|
Technical update after release to rubygems.org.
|
39
63
|
README was updated to reflect this change.
|
40
64
|
|
65
|
+
[Compare v0.2.4...v0.2.5](https://github.com/trinistr/vector_number/compare/v0.2.4...v0.2.5)
|
66
|
+
|
41
67
|
## [v0.2.4] — 2025-02-26
|
42
68
|
|
43
69
|
**Added**
|
@@ -55,11 +81,15 @@ README was updated to reflect this change.
|
|
55
81
|
**Fixed**
|
56
82
|
- `#dup` and `#clone` now behave exactly like Numeric versions, preventing unfreezing.
|
57
83
|
|
84
|
+
[Compare v0.2.3...v0.2.4](https://github.com/trinistr/vector_number/compare/v0.2.3...v0.2.4)
|
85
|
+
|
58
86
|
## [v0.2.3] — 2024-10-15
|
59
87
|
|
60
88
|
**Fixed**
|
61
89
|
- BigDecimal tests are now properly skipped when BigDecimal is not available, instead of always.
|
62
90
|
|
91
|
+
[Compare v0.2.2...v0.2.3](https://github.com/trinistr/vector_number/compare/v0.2.2...v0.2.3)
|
92
|
+
|
63
93
|
## [v0.2.2] — 2024-10-07
|
64
94
|
|
65
95
|
**Added**
|
@@ -74,6 +104,8 @@ README was updated to reflect this change.
|
|
74
104
|
**Fixed**
|
75
105
|
- `Kernel#BigDecimal` refinement now correctly works without `ndigits` argument.
|
76
106
|
|
107
|
+
[Compare v0.2.1...v0.2.2](https://github.com/trinistr/vector_number/compare/v0.2.1...v0.2.2)
|
108
|
+
|
77
109
|
## [v0.2.1] — 2024-08-24
|
78
110
|
|
79
111
|
**Added**
|
@@ -90,6 +122,8 @@ README was updated to reflect this change.
|
|
90
122
|
- Remove `#to_str`, as VectorNumber is not a String-like object.
|
91
123
|
- Due to the above, `Kernel.BigDecimal` no longer works without refinements.
|
92
124
|
|
125
|
+
[Compare v0.2.0...v0.2.1](https://github.com/trinistr/vector_number/compare/v0.2.0...v0.2.1)
|
126
|
+
|
93
127
|
## [v0.2.0] — 2024-08-19
|
94
128
|
|
95
129
|
**Added**
|
@@ -97,8 +131,20 @@ README was updated to reflect this change.
|
|
97
131
|
- Addition and subtraction are supported.
|
98
132
|
- VectorNumbers are mostly interoperable with core numbers.
|
99
133
|
|
134
|
+
[Compare v0.1.0...v0.2.0](https://github.com/trinistr/vector_number/compare/v0.1.0...v0.2.0)
|
135
|
+
|
100
136
|
## [v0.1.0] — 2024-05-09
|
101
137
|
|
102
138
|
- Initial work.
|
103
139
|
|
140
|
+
[Next]: https://github.com/trinistr/vector_number/tree/main
|
141
|
+
[v0.3.0]: https://github.com/trinistr/vector_number/tree/v0.3.0
|
142
|
+
[v0.2.6]: https://github.com/trinistr/vector_number/tree/v0.2.6
|
143
|
+
[v0.2.5]: https://github.com/trinistr/vector_number/tree/v0.2.5
|
144
|
+
[v0.2.4]: https://github.com/trinistr/vector_number/tree/v0.2.4
|
145
|
+
[v0.2.3]: https://github.com/trinistr/vector_number/tree/v0.2.3
|
146
|
+
[v0.2.2]: https://github.com/trinistr/vector_number/tree/v0.2.2
|
147
|
+
[v0.2.1]: https://github.com/trinistr/vector_number/tree/v0.2.1
|
148
|
+
[v0.2.0]: https://github.com/trinistr/vector_number/tree/v0.2.0
|
149
|
+
[v0.1.0]: https://github.com/trinistr/vector_number/tree/v0.1.0
|
104
150
|
[🚀 CI]: https://github.com/trinistr/vector_number/actions/workflows/CI.yaml
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024-2025 Alexandr Bulancov
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,26 +1,35 @@
|
|
1
1
|
# VectorNumber
|
2
2
|
|
3
|
+
> [!TIP]
|
4
|
+
> You may be viewing documentation for an older (or newer) version of the gem.
|
5
|
+
> Check badges below to see what the latest released version is.
|
6
|
+
> Look at [Changelog](https://github.com/trinistr/vector_number/blob/main/CHANGELOG.md)
|
7
|
+
> to see all versions, including unreleased changes!
|
8
|
+
|
9
|
+
Latest: [](https://rubygems.org/gems/vector_number)
|
3
10
|
[](https://github.com/trinistr/vector_number/actions/workflows/CI.yaml)
|
4
11
|
|
5
|
-
|
12
|
+
***
|
6
13
|
|
7
|
-
|
14
|
+
A library to add together anything: be it a number, string or random Object, it can be added together with math operations available on results in a real vector space, though some operations are modeled on hypercomplex numbers.
|
8
15
|
|
9
16
|
Similar projects:
|
10
|
-
- [vector_space](https://github.com/tomstuart/vector_space) aims to provide typed vector spaces with limited dimensions and nice formatting
|
11
|
-
- [named_vector](https://rubygems.org/gems/named_vector) provides simple vectors with named dimensions
|
12
|
-
-
|
17
|
+
- [vector_space](https://github.com/tomstuart/vector_space) aims to provide typed vector spaces with limited dimensions and nice formatting;
|
18
|
+
- [named_vector](https://rubygems.org/gems/named_vector) provides simple vectors with named dimensions;
|
19
|
+
- various quaternion libraries like [quaternion](https://github.com/tanahiro/quaternion) or [rmath3d](https://github.com/vaiorabbit/rmath3d).
|
20
|
+
|
21
|
+
However, none of them have been updated in *years*.
|
13
22
|
|
14
23
|
## Installation
|
15
24
|
|
16
25
|
VectorNumber does not have any dependencies and does not include extensions.
|
17
26
|
|
18
|
-
Install with `gem` (available from 0.2.4):
|
27
|
+
Install with `gem` (available from [0.2.4](https://github.com/trinistr/vector_number/tree/v0.2.4)):
|
19
28
|
```sh
|
20
29
|
gem install vector_number
|
21
30
|
```
|
22
31
|
|
23
|
-
If using
|
32
|
+
If using Bundler, add gem to your Gemfile:
|
24
33
|
```ruby
|
25
34
|
gem "vector_number"
|
26
35
|
```
|
@@ -2,17 +2,33 @@
|
|
2
2
|
|
3
3
|
class VectorNumber
|
4
4
|
# Methods for comparing with other numbers.
|
5
|
+
#
|
6
|
+
# +Comparable+ is included for parity with numbers.
|
7
|
+
# @example using Comparable methods
|
8
|
+
# VectorNumber[12] < 0 # => false
|
9
|
+
# VectorNumber[12, "a"] < 0 # ArgumentError
|
10
|
+
# (VectorNumber[12]..VectorNumber[15]).include?(13) # => true
|
5
11
|
module Comparing
|
12
|
+
# @since 0.2.0
|
6
13
|
include ::Comparable
|
7
14
|
|
8
15
|
# Compare to +other+ for equality.
|
9
16
|
#
|
10
17
|
# Values are considered equal if
|
11
18
|
# - +other+ is a VectorNumber and it is +eql?+ to this one, or
|
12
|
-
# - +other+ is a Numeric equal in value to this number.
|
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
|
13
27
|
#
|
14
28
|
# @param other [Object]
|
15
29
|
# @return [Boolean]
|
30
|
+
#
|
31
|
+
# @since 0.2.0
|
16
32
|
def ==(other)
|
17
33
|
return true if eql?(other)
|
18
34
|
|
@@ -25,8 +41,24 @@ class VectorNumber
|
|
25
41
|
end
|
26
42
|
end
|
27
43
|
|
44
|
+
# Compare to +other+ for strict equality.
|
45
|
+
#
|
46
|
+
# Values are considered equal only if +other+ is a VectorNumber
|
47
|
+
# and it has exactly the same units and coefficients, though possibly in a different order.
|
48
|
+
#
|
49
|
+
# Note that {#options} are not considered for equality.
|
50
|
+
#
|
51
|
+
# @example
|
52
|
+
# VectorNumber["a", "b", "c"].eql? VectorNumber["c", "b", "a"] # => true
|
53
|
+
# VectorNumber[3.13].eql? 3.13 # => false
|
54
|
+
# VectorNumber[1.4, 1.5i].eql? Complex(1.4, 1.5) # => false
|
55
|
+
# VectorNumber["a", 14].eql? 14 # => false
|
56
|
+
# VectorNumber["a"].eql? "a" # => false
|
57
|
+
#
|
28
58
|
# @param other [Object]
|
29
59
|
# @return [Boolean]
|
60
|
+
#
|
61
|
+
# @since 0.1.0
|
30
62
|
def eql?(other)
|
31
63
|
return true if equal?(other)
|
32
64
|
|
@@ -37,8 +69,29 @@ class VectorNumber
|
|
37
69
|
end
|
38
70
|
end
|
39
71
|
|
72
|
+
# Compare to +other+ and return -1, 0, or 1
|
73
|
+
# if +self+ is less than, equal, or larger than +other+.
|
74
|
+
#
|
75
|
+
# @example
|
76
|
+
# VectorNumber[130] <=> 12 # => 1
|
77
|
+
# 1 <=> VectorNumber[13] # => -1
|
78
|
+
# VectorNumber[12.1] <=> Complex(12.1, 0) # => 0
|
79
|
+
# # This doesn't work as expected without NumericRefinements:
|
80
|
+
# Complex(12.1, 0) <=> VectorNumber[12.1] # => nil
|
81
|
+
#
|
82
|
+
# # Any non-real comparison returns nil:
|
83
|
+
# VectorNumber[12.1] <=> Complex(12.1, 1) # => nil
|
84
|
+
# VectorNumber[12.1i] <=> 2 # => nil
|
85
|
+
# VectorNumber["a"] <=> 2 # => nil
|
86
|
+
#
|
40
87
|
# @param other [Object]
|
41
|
-
# @return [
|
88
|
+
# @return [-1, 0, 1]
|
89
|
+
# @return [nil] if +self+ or +other+ isn't a real number.
|
90
|
+
#
|
91
|
+
# @see Comparable
|
92
|
+
# @see NumericRefinements
|
93
|
+
#
|
94
|
+
# @since 0.2.0
|
42
95
|
def <=>(other)
|
43
96
|
return nil unless numeric?(1)
|
44
97
|
|
@@ -4,47 +4,115 @@ class VectorNumber
|
|
4
4
|
# Methods for converting to different number classes.
|
5
5
|
module Converting
|
6
6
|
# Return real part of the number.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# VectorNumber[23, "a"].real # => 23
|
10
|
+
# VectorNumber["a"].real # => 0
|
11
|
+
#
|
7
12
|
# @return [Integer, Float, Rational, BigDecimal]
|
8
|
-
|
9
|
-
|
10
|
-
|
13
|
+
#
|
14
|
+
# @since 0.1.0
|
15
|
+
def real = @data[R]
|
11
16
|
|
12
17
|
# Return imaginary part of the number.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# VectorNumber[23, "a"].imaginary # => 0
|
21
|
+
# VectorNumber["a", Complex(1, 2r)].imag # => (2/1)
|
22
|
+
#
|
13
23
|
# @return [Integer, Float, Rational, BigDecimal]
|
14
|
-
|
15
|
-
|
16
|
-
|
24
|
+
#
|
25
|
+
# @since 0.1.0
|
26
|
+
def imaginary = @data[I]
|
17
27
|
|
28
|
+
# @since 0.2.1
|
18
29
|
alias imag imaginary
|
19
30
|
|
20
31
|
# Return value as an Integer, truncating it, if only real part is non-zero.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# VectorNumber[13.5].to_i # => 13
|
35
|
+
# VectorNumber[13r/12].to_int # => 1
|
36
|
+
# [1.1, 2.2, 3.3][VectorNumber[2]] # => 3.3
|
37
|
+
# VectorNumber[2, 2i].to_i # RangeError
|
38
|
+
# VectorNumber[2, :i].to_f # RangeError
|
39
|
+
#
|
40
|
+
# Integer(VectorNumber[2]) # => 2
|
41
|
+
# Integer(VectorNumber[2, "i"]) # RangeError
|
42
|
+
#
|
21
43
|
# @return [Integer]
|
22
44
|
# @raise [RangeError] if any non-real part is non-zero
|
45
|
+
#
|
46
|
+
# @since 0.1.0
|
23
47
|
def to_i
|
24
48
|
numeric?(1) ? real.to_i : raise_convert_error(Integer)
|
25
49
|
end
|
26
50
|
|
51
|
+
# @since 0.1.0
|
27
52
|
alias to_int to_i
|
28
53
|
|
29
54
|
# Return value as a Float if only real part is non-zero.
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# VectorNumber[13.5].to_f # => 13.5
|
58
|
+
# VectorNumber[13r/12].to_f # => 1.0833333333333333
|
59
|
+
# VectorNumber[2, 2i].to_f # RangeError
|
60
|
+
# VectorNumber[2, :i].to_f # RangeError
|
61
|
+
#
|
62
|
+
# Float(VectorNumber[2]) # => 2.0
|
63
|
+
# Float(VectorNumber[2, "i"]) # RangeError
|
64
|
+
#
|
30
65
|
# @return [Float]
|
31
66
|
# @raise [RangeError] if any non-real part is non-zero
|
67
|
+
#
|
68
|
+
# @since 0.1.0
|
32
69
|
def to_f
|
33
70
|
numeric?(1) ? real.to_f : raise_convert_error(Float)
|
34
71
|
end
|
35
72
|
|
36
73
|
# Return value as a Rational if only real part is non-zero.
|
74
|
+
#
|
75
|
+
# @example
|
76
|
+
# VectorNumber[13.5].to_r # => (27/2)
|
77
|
+
# VectorNumber[13r/12].to_r # => (13/12)
|
78
|
+
# VectorNumber[2, 2i].to_r # RangeError
|
79
|
+
# VectorNumber[2, :i].to_r # RangeError
|
80
|
+
#
|
81
|
+
# Rational(VectorNumber[2]) # => (2/1)
|
82
|
+
# Rational(VectorNumber[2, "i"]) # RangeError
|
83
|
+
#
|
37
84
|
# @return [Rational]
|
38
85
|
# @raise [RangeError] if any non-real part is non-zero
|
86
|
+
#
|
87
|
+
# @since 0.1.0
|
39
88
|
def to_r
|
40
89
|
numeric?(1) ? real.to_r : raise_convert_error(Rational)
|
41
90
|
end
|
42
91
|
|
43
92
|
# Return value as a BigDecimal if only real part is non-zero.
|
93
|
+
#
|
94
|
+
# @example
|
95
|
+
# VectorNumber[13.5].to_d # => 0.135e2
|
96
|
+
# VectorNumber[13r/12].to_d # ArgumentError
|
97
|
+
# VectorNumber[13r/12].to_d(5) # => 0.10833e1
|
98
|
+
# VectorNumber[2, 2i].to_d # RangeError
|
99
|
+
# VectorNumber[2, :i].to_d # RangeError
|
100
|
+
#
|
101
|
+
# # This does't work without NumericRefinements:
|
102
|
+
# BigDecimal(VectorNumber[2]) # TypeError
|
103
|
+
# # #to_s can be used as a workaround if refinements aren't used:
|
104
|
+
# BigDecimal(VectorNumber[2].to_s) # => 0.2e1
|
105
|
+
# BigDecimal(VectorNumber[2, "i"].to_s) # => ArgumentError
|
106
|
+
#
|
44
107
|
# @param ndigits [Integer] precision
|
45
108
|
# @return [BigDecimal]
|
46
109
|
# @raise [RangeError] if any non-real part is non-zero
|
47
110
|
# @raise [NameError] if BigDecimal is not defined
|
111
|
+
#
|
112
|
+
# @see Kernel.BigDecimal
|
113
|
+
# @see NumericRefinements
|
114
|
+
#
|
115
|
+
# @since 0.1.0
|
48
116
|
def to_d(ndigits = nil)
|
49
117
|
if numeric?(1)
|
50
118
|
return BigDecimal(real, ndigits) if ndigits
|
@@ -57,8 +125,20 @@ class VectorNumber
|
|
57
125
|
end
|
58
126
|
|
59
127
|
# Return value as a Complex if only real and/or imaginary parts are non-zero.
|
128
|
+
#
|
129
|
+
# @example
|
130
|
+
# VectorNumber[13.5].to_c # => (13.5+0i)
|
131
|
+
# VectorNumber[13r/12].to_c # => ((13/12)+0i)
|
132
|
+
# VectorNumber[2, 2i].to_c # => (2+2i)
|
133
|
+
# VectorNumber[2, :i].to_c # RangeError
|
134
|
+
#
|
135
|
+
# Complex(VectorNumber[2]) # => (2+0i)
|
136
|
+
# Complex(VectorNumber[2, "i"]) # RangeError
|
137
|
+
#
|
60
138
|
# @return [Complex]
|
61
139
|
# @raise [RangeError] if any non-real, non-imaginary part is non-zero
|
140
|
+
#
|
141
|
+
# @since 0.1.0
|
62
142
|
def to_c
|
63
143
|
numeric?(2) ? Complex(real, imaginary) : raise_convert_error(Complex)
|
64
144
|
end
|
@@ -2,11 +2,28 @@
|
|
2
2
|
|
3
3
|
class VectorNumber
|
4
4
|
# Methods for enumerating values of the number.
|
5
|
+
#
|
6
|
+
# +Enumerable+ is included so its methods can be used.
|
7
|
+
# @example using Enumerable methods
|
8
|
+
# VectorNumber["a", "b", 6].include?(["a", 1]) # => true
|
9
|
+
# VectorNumber["a", "b", 6].select { |u, c| u.is_a?(String) } # => [["a", 1], ["b", 1]]
|
5
10
|
module Enumerating
|
11
|
+
# @since 0.1.0
|
6
12
|
include ::Enumerable
|
7
13
|
|
8
14
|
# Iterate through every pair of unit and coefficient.
|
9
|
-
# Returns
|
15
|
+
# Returns +Enumerator+ (with set +size+) if no block is given.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# v = VectorNumber["a", "b", 6]
|
19
|
+
# units = []
|
20
|
+
# v.each { |u, c| units << u unless u.is_a?(Numeric) } # => (1⋅'a' + 1⋅'b' + 6)
|
21
|
+
# units # => ["a", "b"]
|
22
|
+
# @example Enumerator
|
23
|
+
# v.each.size # => 3
|
24
|
+
# (v.each + [["d", 0]]).map(&:first) # => ["a", "b", (0+0i), "d"]
|
25
|
+
# v.each_pair.peek # => ["a", 1]
|
26
|
+
#
|
10
27
|
# @overload each
|
11
28
|
# @yieldparam unit [Object]
|
12
29
|
# @yieldparam coefficient [Integer, Float, Rational, BigDecimal]
|
@@ -14,6 +31,11 @@ class VectorNumber
|
|
14
31
|
# @return [VectorNumber] self
|
15
32
|
# @overload each
|
16
33
|
# @return [Enumerator]
|
34
|
+
#
|
35
|
+
# @see Enumerable
|
36
|
+
# @see Enumerator
|
37
|
+
#
|
38
|
+
# @since 0.1.0
|
17
39
|
def each(&)
|
18
40
|
return to_enum { size } unless block_given?
|
19
41
|
|
@@ -21,24 +43,50 @@ class VectorNumber
|
|
21
43
|
self
|
22
44
|
end
|
23
45
|
|
46
|
+
# @since 0.1.0
|
24
47
|
alias each_pair each
|
25
48
|
|
49
|
+
# Get a list of units with non-zero coefficients.
|
50
|
+
#
|
51
|
+
# @example
|
52
|
+
# VectorNumber["a", "b", 6].units # => ["a", "b", (0+0i)]
|
53
|
+
# VectorNumber.new.keys # => []
|
54
|
+
#
|
26
55
|
# @return [Array<Object>]
|
27
|
-
|
28
|
-
|
29
|
-
|
56
|
+
#
|
57
|
+
# @since 0.1.0
|
58
|
+
def units = @data.keys
|
30
59
|
|
60
|
+
# @since 0.1.0
|
31
61
|
alias keys units
|
32
62
|
|
63
|
+
# Get a list of non-zero coefficients.
|
64
|
+
#
|
65
|
+
# @example
|
66
|
+
# VectorNumber["a", "b", 6].coefficients # => [1, 1, 6]
|
67
|
+
# VectorNumber.new.values # => []
|
68
|
+
#
|
33
69
|
# @return [Array<Integer, Float, Rational, BigDecimal>]
|
34
|
-
|
35
|
-
|
36
|
-
|
70
|
+
#
|
71
|
+
# @since 0.1.0
|
72
|
+
def coefficients = @data.values
|
37
73
|
|
74
|
+
# @since 0.1.0
|
38
75
|
alias values coefficients
|
39
76
|
|
77
|
+
# Get mutable hash with vector's data.
|
78
|
+
#
|
79
|
+
# Returned hash has a default value of 0.
|
80
|
+
#
|
81
|
+
# @example
|
82
|
+
# VectorNumber["a", "b", 6].to_h # => {"a"=>1, "b"=>1, (0+0i)=>6}
|
83
|
+
# VectorNumber["a", "b", 6].to_h["c"] # => 0
|
84
|
+
#
|
40
85
|
# @return [Hash{Object => Integer, Float, Rational, BigDecimal}]
|
86
|
+
#
|
87
|
+
# @since 0.1.0
|
41
88
|
def to_h(&)
|
89
|
+
# TODO: Remove block argument.
|
42
90
|
if block_given?
|
43
91
|
@data.to_h(&)
|
44
92
|
else
|
@@ -52,20 +100,29 @@ class VectorNumber
|
|
52
100
|
# Note that units for real and imaginary parts are
|
53
101
|
# VectorNumber::R and VectorNumber::I respectively.
|
54
102
|
#
|
103
|
+
# @example
|
104
|
+
# VectorNumber["a", "b", 6]["a"] # => 1
|
105
|
+
# VectorNumber["a", "b", 6]["c"] # => 0
|
106
|
+
#
|
55
107
|
# @param unit [Object]
|
56
108
|
# @return [Integer, Float, Rational, BigDecimal]
|
57
|
-
|
58
|
-
|
59
|
-
|
109
|
+
#
|
110
|
+
# @since 0.2.4
|
111
|
+
def [](unit) = @data[unit]
|
60
112
|
|
61
113
|
# Check if a unit has a non-zero coefficient.
|
62
114
|
#
|
115
|
+
# @example
|
116
|
+
# VectorNumber["a", "b", 6].unit?("a") # => true
|
117
|
+
# VectorNumber["a", "b", 6].key?("c") # => false
|
118
|
+
#
|
63
119
|
# @param unit [Object]
|
64
120
|
# @return [Boolean]
|
65
|
-
|
66
|
-
|
67
|
-
|
121
|
+
#
|
122
|
+
# @since 0.2.4
|
123
|
+
def unit?(unit) = @data.key?(unit)
|
68
124
|
|
125
|
+
# @since 0.2.4
|
69
126
|
alias key? unit?
|
70
127
|
end
|
71
128
|
end
|
@@ -3,45 +3,105 @@
|
|
3
3
|
class VectorNumber
|
4
4
|
# Various mathematical operations that are also conversions.
|
5
5
|
module MathConverting
|
6
|
-
#
|
6
|
+
# Calculate the absolute value of the vector, i.e. its length.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# VectorNumber[5.3].abs # => 5.3
|
10
|
+
# VectorNumber[-5.3i].magnitude # => 5.3
|
11
|
+
# VectorNumber[-5.3i, "i"].abs # => 5.3935146240647205
|
12
|
+
#
|
7
13
|
# @return [Float]
|
14
|
+
#
|
15
|
+
# @since 0.2.2
|
8
16
|
def abs
|
9
|
-
Math.sqrt(
|
17
|
+
Math.sqrt(abs2)
|
10
18
|
end
|
11
19
|
|
12
20
|
alias magnitude abs
|
13
21
|
|
14
|
-
#
|
22
|
+
# Calculate the square of absolute value.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# VectorNumber[5.3].abs2 # => 5.3
|
26
|
+
# VectorNumber[-5.3i].abs2 # => 5.3
|
27
|
+
# VectorNumber[-5.3i, "i"].abs2 # => 29.09
|
28
|
+
#
|
15
29
|
# @return [Float]
|
16
|
-
|
17
|
-
|
30
|
+
#
|
31
|
+
# @since 0.2.2
|
32
|
+
def abs2
|
33
|
+
coefficients.sum(&:abs2)
|
18
34
|
end
|
19
35
|
|
20
36
|
# Return a new vector with every coefficient truncated using their +#truncate+.
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
# VectorNumber[5.39].truncate # => (5)
|
40
|
+
# VectorNumber[-5.35i].truncate # => (-5i)
|
41
|
+
# VectorNumber[-5.35i, "i"].truncate # => (-5i + 1⋅'i')
|
42
|
+
# VectorNumber[-5.35i, "i"].truncate(1) # => (-5.3i + 1⋅'i')
|
43
|
+
# VectorNumber[-5.35i, "i"].truncate(-1) # => (0)
|
44
|
+
#
|
21
45
|
# @param digits [Integer]
|
22
46
|
# @return [VectorNumber]
|
47
|
+
#
|
48
|
+
# @since 0.2.1
|
23
49
|
def truncate(digits = 0)
|
24
50
|
new { _1.truncate(digits) }
|
25
51
|
end
|
26
52
|
|
27
53
|
# Return a new vector with every coefficient rounded using their +#ceil+.
|
54
|
+
#
|
55
|
+
# @example
|
56
|
+
# VectorNumber[5.39].ceil # => (6)
|
57
|
+
# VectorNumber[-5.35i].ceil # => (-5i)
|
58
|
+
# VectorNumber[-5.35i, "i"].ceil # => (-5i + 1⋅'i')
|
59
|
+
# VectorNumber[-5.35i, "i"].ceil(1) # => (-5.3i + 1⋅'i')
|
60
|
+
# VectorNumber[-5.35i, "i"].ceil(-1) # => (10⋅'i')
|
61
|
+
#
|
28
62
|
# @param digits [Integer]
|
29
63
|
# @return [VectorNumber]
|
64
|
+
#
|
65
|
+
# @since 0.2.2
|
30
66
|
def ceil(digits = 0)
|
31
67
|
new { _1.ceil(digits) }
|
32
68
|
end
|
33
69
|
|
34
70
|
# Return a new vector with every coefficient rounded using their +#floor+.
|
71
|
+
#
|
72
|
+
# @example
|
73
|
+
# VectorNumber[5.39].floor # => (5)
|
74
|
+
# VectorNumber[-5.35i].floor # => (-6i)
|
75
|
+
# VectorNumber[-5.35i, "i"].floor # => (-6i + 1⋅'i')
|
76
|
+
# VectorNumber[-5.35i, "i"].floor(1) # => (-5.4i + 1⋅'i')
|
77
|
+
# VectorNumber[-5.35i, "i"].floor(-1) # => (-10i)
|
78
|
+
#
|
35
79
|
# @param digits [Integer]
|
36
80
|
# @return [VectorNumber]
|
81
|
+
#
|
82
|
+
# @since 0.2.2
|
37
83
|
def floor(digits = 0)
|
38
84
|
new { _1.floor(digits) }
|
39
85
|
end
|
40
86
|
|
41
87
|
# Return a new vector with every coefficient rounded using their +#round+.
|
88
|
+
#
|
89
|
+
# @example
|
90
|
+
# VectorNumber[-4.5i, "i"].round(half: :up) # => (-5i + 1⋅'i')
|
91
|
+
# VectorNumber[-4.5i, "i"].round(half: :even) # => (-4i + 1⋅'i')
|
92
|
+
# VectorNumber[-5.5i, "i"].round(half: :even) # => (-6i + 1⋅'i')
|
93
|
+
# VectorNumber[-5.5i, "i"].round(half: :down) # => (-5i + 1⋅'i')
|
94
|
+
# VectorNumber[-5.35i, "i"].round(1) # => (-5.4i + 1⋅'i')
|
95
|
+
# VectorNumber[-5.35i, "i"].round(-1) # => (-10i)
|
96
|
+
#
|
42
97
|
# @param digits [Integer]
|
43
|
-
# @param half [Symbol, nil] one of +:up+, +:down+ or +:even+,
|
98
|
+
# @param half [Symbol, nil] one of +:up+, +:down+ or +:even+,
|
99
|
+
# see +Float#round+ for meaning
|
44
100
|
# @return [VectorNumber]
|
101
|
+
#
|
102
|
+
# @see Float#round
|
103
|
+
#
|
104
|
+
# @since 0.2.2
|
45
105
|
def round(digits = 0, half: :up)
|
46
106
|
if defined?(BigDecimal)
|
47
107
|
bd_mode =
|