Class: VectorNumber
- Inherits:
-
Object
- Object
- VectorNumber
- Includes:
- Comparable, Enumerable
- Defined in:
- lib/vector_number.rb,
lib/vector_number/mathing.rb,
lib/vector_number/version.rb,
lib/vector_number/querying.rb,
lib/vector_number/comparing.rb,
lib/vector_number/vectoring.rb,
lib/vector_number/converting.rb,
lib/vector_number/enumerating.rb,
lib/vector_number/special_unit.rb,
lib/vector_number/stringifying.rb,
lib/vector_number/math_converting.rb,
lib/vector_number/numeric_refinements.rb
Overview
VectorNumber provides a Numeric-like experience for doing arithmetics on heterogeneous objects, with more advanced operations based on real vector spaces available when needed.
VectorNumber inherits from Object and includes Enumerable and Comparable. It implements mostly the same interface as Numeric classes, but can #coerce any value. Its behavior follows Complex when possible.
All instances are frozen after creation.
Creation
-
VectorNumber.[]: the simplest way to create a VectorNumber
-
#initialize: an alternative way, with some advanced features
Comparing
-
#==: test for equal value
-
#eql?: test for equal value and type
-
#<=>: compare real values
-
#hash: calculate hash value for use in Hashes
Querying
-
#zero?: check if all coefficients are zero
-
#nonzero?: check if any coefficient is non-zero
-
#positive?: check if all coefficients are positive
-
#negative?: check if all coefficients are negative
-
#finite?: check if all coefficients are finite
-
#infinite?: check if any coefficient is non-finite
-
#numeric?: test if value is real or complex
-
#nonnumeric?: test if value is not real or complex
-
#integer?:
false -
#real?:
false
Arithmetic operations
-
#coerce: convert any object to a VectorNumber
-
#fdiv: divide (scale) by a real number, using
fdiv -
#div: perform integer division, rounding towards -∞
-
#ceildiv: perform integer division, rounding towards +∞
-
#remainder: return remainder from integer division
Rounding
-
#round: round each coefficient
-
#ceil: round each coefficient up towards +∞
-
#floor: round each coefficient down towards -∞
-
#truncate: truncate each coefficient towards 0
Vector operations
-
#magnitude/#abs: calculate magnitude (length/absolute value)
-
#abs2: calculate square of absolute value
-
#p_norm: calculate p-norm of the vector
-
#maximum_norm/#infinity_norm: calculate maximum norm of the vector
-
#subspace_basis: return an array of vectors forming orthonormal basis
-
#uniform_vector: return a new vector with coefficients set to 1
-
#unit_vector: return a unit vector in the direction of this vector
-
#dot_product/#inner_product/#scalar_product: calculate the inner product of vectors
-
#angle: calculate angle between vectors
-
#vector_projection: calculate the vector projection onto another vector
-
#scalar_projection: calculate the scalar projection onto another vector
-
#vector_rejection: calculate the vector rejection from another vector
-
#scalar_rejection: calculate the scalar rejection from another vector
Type conversion
-
#real: return real part
-
#imag/#imaginary: return imaginary part
-
#to_f: convert to
Floatif possible -
#to_r: convert to
Rationalif possible -
#to_d: convert to
BigDecimalif possible -
#to_c: convert to
Complexif possible
Hash-like operations
-
#each/#each_pair: iterate through every pair of unit and coefficient
-
#[]: get coefficient by unit
-
#coefficients/##values: return an array of coefficients
-
#to_h: convert to Hash
Miscellaneous methods
Defined Under Namespace
Modules: NumericRefinements Classes: SpecialUnit
Constant Summary collapse
- NUMERIC_UNITS =
List of special numeric unit constants.
[SpecialUnit.new("1", "").freeze, SpecialUnit.new("i", "i").freeze].freeze
- R =
Constant for real unit (1).
Its string representation is an empty string.
- I =
Constant for imaginary unit (i).
Its string representation is “i”.
- VERSION =
"0.6.1"- MULT_STRINGS =
Predefined symbols for multiplication to display between unit and coefficient.
{ asterisk: "*", # U+002A cross: "×", # U+00D7 dot: "⋅", # U+22C5 invisible: "", # U+2062, zero-width multiplication operator space: " ", none: "", }.freeze
Miscellaneous methods collapse
-
#size ⇒ Integer
readonly
Number of non-zero dimensions.
Creation collapse
-
.[](*values) ⇒ Object
Create new VectorNumber from a list of values.
-
#initialize(values = nil) {|coefficient| ... } ⇒ VectorNumber
constructor
Create new VectorNumber from
values, possibly modifying coefficients with a block.
Miscellaneous methods collapse
-
.numeric_unit?(unit) ⇒ Boolean
Check if an object is a unit representing a numeric dimension (real or imaginary unit).
-
#+@ ⇒ VectorNumber
(also: #dup)
Return self.
-
#clone(freeze: true) ⇒ VectorNumber
Return self.
-
#inspect ⇒ String
Return string representation of the vector suitable for display.
-
#to_s(mult: :dot) {|unit, coefficient, index, operator| ... } ⇒ String
Return string representation of the vector suitable for output.
Arithmetic operations collapse
-
#%(other) ⇒ VectorNumber
(also: #modulo)
Return the modulus of dividing self by a real
otheras a vector. -
#*(other) ⇒ VectorNumber
(also: #mult)
Multiply all coefficients by a real
other, returning new vector. -
#+(other) ⇒ VectorNumber
(also: #add)
Return new vector as a sum of this and
othervalue. -
#-(other) ⇒ VectorNumber
(also: #sub)
Return new vector as a sum of this and additive inverse of
othervalue. -
#-@ ⇒ VectorNumber
(also: #neg)
Return new vector with negated coefficients (additive inverse).
-
#/(other) ⇒ VectorNumber
(also: #quo)
Divide all coefficients by a real
other, returning new vector. -
#ceil(digits = 0) ⇒ VectorNumber
Return a new vector with every coefficient rounded using their
#ceil. -
#ceildiv(other) ⇒ VectorNumber
Divide all coefficients by a real
other, converting results to integers using#ceil. -
#coerce(other) ⇒ Array(VectorNumber, VectorNumber)
The coerce method provides support for Ruby type coercion.
-
#div(other) ⇒ VectorNumber
Divide all coefficients by a real
other, converting results to integers using#floor. -
#divmod(other) ⇒ Array(VectorNumber, VectorNumber)
Return the quotient and modulus of dividing self by a real
other. -
#fdiv(other) ⇒ VectorNumber
Divide all coefficients by a real
otherusingfdiv, returning new vector with decimal coefficients. -
#floor(digits = 0) ⇒ VectorNumber
Return a new vector with every coefficient rounded using their
#floor. -
#remainder(other) ⇒ VectorNumber
Return the remainder of dividing self by a real
otheras a vector. -
#round(digits = 0, half: :up) ⇒ VectorNumber
Return a new vector with every coefficient rounded using their
#round. -
#truncate(digits = 0) ⇒ VectorNumber
Return a new vector with every coefficient truncated using their
#truncate.
Querying collapse
-
#finite? ⇒ Boolean
Returns
trueif all coefficients are finite,falseotherwise. -
#infinite? ⇒ 1?
Returns
1if any coefficients are non-finite,nilotherwise. -
#integer? ⇒ false
Always returns
false, as vectors are not Integers. -
#negative? ⇒ Boolean
Returns
trueif number is non-zero and all non-zero coefficients are negative, andfalseotherwise. -
#nonnumeric?(dimensions = 2) ⇒ Boolean
Returns
trueif this VectorNumber contains any non-zero dimensions with non-numeric units, andfalseotherwise. -
#nonzero? ⇒ VectorNumber?
Returns
selfif there are any non-zero coefficients,nilotherwise. -
#numeric?(dimensions = 2) ⇒ Boolean
Returns
trueif all non-zero dimensions in this VectorNumber are numeric (real or complex), andfalseotherwise. -
#positive? ⇒ Boolean
Returns
trueif number is non-zero and all non-zero coefficients are positive, andfalseotherwise. -
#real? ⇒ false
Always returns
false, as vectors are not real numbers. -
#zero? ⇒ Boolean
Returns
trueif there are no non-zero coefficients, andfalseotherwise.
Comparing collapse
-
#<=>(other) ⇒ Integer?
Compare to
otherand return -1, 0, or 1 ifselfis less than, equal, or larger thanotheron real number line, ornilif any or both values are non-real. -
#==(other) ⇒ Boolean
Test whether
otherhas the same value with == semantics. -
#eql?(other) ⇒ Boolean
Test whether
otheris VectorNumber and has the same value witheql?semantics. -
#hash ⇒ Integer
Generate an Integer hash value for self.
Vector operations collapse
-
#abs2 ⇒ Numeric
Calculate the square of absolute value.
-
#angle(other) ⇒ Numeric
Calculate the angle between this vector and
othervector in radians. -
#dot_product(other) ⇒ Numeric
(also: #inner_product, #scalar_product)
Calculate the dot product (inner product/scalar product) of this vector with
othervector. -
#magnitude ⇒ Numeric
(also: #abs)
Calculate the magnitude of the vector (its length/absolute value).
-
#maximum_norm ⇒ Numeric
(also: #infinity_norm)
Calculate the maximum norm (infinity norm) of the vector.
-
#p_norm(p) ⇒ Numeric
Calculate the p-norm of the vector.
-
#scalar_projection(other) ⇒ Numeric
Calculate the scalar projection of this vector onto
othervector. -
#scalar_rejection(other) ⇒ Numeric
Calculate the scalar rejection of this vector from
othervector. -
#subspace_basis ⇒ Array<VectorNumber>
Return an array of vectors forming orthonormal basis of linear subspace this vector belongs to.
-
#uniform_vector ⇒ VectorNumber
Return a new vector with the same non-zero dimensions, but with coefficients equal to 1.
-
#unit_vector ⇒ VectorNumber
Return a unit vector (vector with magnitude 1) in the direction of this vector.
-
#vector_projection(other) ⇒ VectorNumber
Calculate the vector projection of this vector onto
othervector. -
#vector_rejection(other) ⇒ VectorNumber
Calculate the vector rejection of this vector from
othervector.
Type conversion collapse
-
#imaginary ⇒ Numeric
(also: #imag)
Return imaginary part of the number.
-
#real ⇒ Numeric
Return real part of the number.
-
#to_c ⇒ Complex
Return value as a Complex if only real and/or imaginary parts are non-zero.
-
#to_d(ndigits = nil) ⇒ BigDecimal
Return value as a BigDecimal if only real part is non-zero.
-
#to_f ⇒ Float
Return value as a Float if only real part is non-zero.
-
#to_i ⇒ Integer
(also: #to_int)
Return value as an Integer, truncating it, if only real part is non-zero.
-
#to_r ⇒ Rational
Return value as a Rational if only real part is non-zero.
Hash-like operations collapse
-
#[](unit) ⇒ Numeric
Get the coefficient for the unit.
-
#coefficients ⇒ Array<Numeric>
(also: #values)
Get a list of non-zero coefficients.
-
#each(&block) ⇒ Object
(also: #each_pair)
Iterate through every pair of unit and coefficient.
-
#to_h(&block) ⇒ Hash{Object => Numeric}
Get mutable hash with vector’s data.
-
#unit?(unit) ⇒ Boolean
(also: #key?)
Check if a unit has a non-zero coefficient.
-
#units ⇒ Array<Object>
(also: #keys)
Get a list of units with non-zero coefficients.
Constructor Details
#initialize(values = nil) {|coefficient| ... } ⇒ VectorNumber
Create new VectorNumber from values, possibly modifying coefficients with a block.
Using VectorNumber.new() directly is more efficient than VectorNumber[values...].
values can be:
-
an array of values (see []);
-
a VectorNumber to copy;
-
a hash in the format returned by #to_h;
-
nilto specify a 0-sized vector (same as an empty array or hash).
Using a hash as values is an advanced technique which allows to quickly construct a VectorNumber with desired units and coefficients, but it can also lead to unexpected results if care is not taken to provide only valid keys and values.
202 203 204 205 206 207 208 |
# File 'lib/vector_number.rb', line 202 def initialize(values = nil, **nil, &transform) initialize_from(values) apply_transform(&transform) finalize_contents @data.freeze freeze end |
Instance Attribute Details
#size ⇒ Integer (readonly)
Number of non-zero dimensions.
164 165 166 |
# File 'lib/vector_number.rb', line 164 def size @size end |
Class Method Details
.[](*values) ⇒ Object
Create new VectorNumber from a list of values.
136 137 138 139 140 |
# File 'lib/vector_number.rb', line 136 def self.[](*values, **nil) raise ArgumentError, "no block accepted" if block_given? new(values) end |
.numeric_unit?(unit) ⇒ Boolean
Check if an object is a unit representing a numeric dimension (real or imaginary unit).
157 158 159 |
# File 'lib/vector_number.rb', line 157 def self.numeric_unit?(unit) NUMERIC_UNITS.include?(unit) end |
Instance Method Details
#%(other) ⇒ VectorNumber Also known as: modulo
Return the modulus of dividing self by a real other as a vector.
This is equal to self - other * (self/other).floor, or, alternatively, self - other * self.div(other).
294 295 296 297 298 299 300 |
# File 'lib/vector_number/mathing.rb', line 294 def %(other) check_divisibility(other) other = other.real # @type var other: Float new { _1 % other } end |
#*(other) ⇒ VectorNumber Also known as: mult
Multiply all coefficients by a real other, returning new vector.
This effectively multiplies #magnitude by other.
115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/vector_number/mathing.rb', line 115 def *(other) if real_number?(other) other = other.real # @type var other: Float new { _1 * other } elsif real_number?(self) && VectorNumber === other # @type var other: untyped other * self else raise RangeError, "can't multiply #{self} and #{other}" end end |
#+(other) ⇒ VectorNumber Also known as: add
Return new vector as a sum of this and other value. This is analogous to [].
66 67 68 |
# File 'lib/vector_number/mathing.rb', line 66 def +(other) new([self, other]) end |
#+@ ⇒ VectorNumber Also known as: dup
Return self.
217 218 |
# File 'lib/vector_number.rb', line 217 def +@ = self # @since 0.2.4 |
#-(other) ⇒ VectorNumber Also known as: sub
89 90 91 |
# File 'lib/vector_number/mathing.rb', line 89 def -(other) self + new([other], &:-@) end |
#-@ ⇒ VectorNumber Also known as: neg
Return new vector with negated coefficients (additive inverse).
44 45 46 |
# File 'lib/vector_number/mathing.rb', line 44 def -@ new(&:-@) end |
#/(other) ⇒ VectorNumber Also known as: quo
This method never does integer division.
Divide all coefficients by a real other, returning new vector.
This effectively multiplies #magnitude by reciprocal of other.
153 154 155 156 157 158 159 160 161 |
# File 'lib/vector_number/mathing.rb', line 153 def /(other) check_divisibility(other) other = other.real # Prevent integer division, but without loss of accuracy. other = Rational(other) if other.integer? # @type var other: Float new { _1 / other } end |
#<=>(other) ⇒ Integer?
Compare to other and return -1, 0, or 1 if self is less than, equal, or larger than other on real number line, or nil if any or both values are non-real.
Most VectorNumbers are non-real and therefore not comparable with this method.
116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/vector_number/comparing.rb', line 116 def <=>(other) return nil unless numeric?(1) case other when VectorNumber other.numeric?(1) ? real <=> other.real : nil when Numeric other.imaginary.zero? ? real <=> other.real : nil else nil end end |
#==(other) ⇒ Boolean
Test whether other has the same value with == semantics.
Values are considered equal if
-
otheris a VectorNumber and it has the same units and equal coefficients, or -
otheris a Numeric equal in value to this (real or complex) number.
32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/vector_number/comparing.rb', line 32 def ==(other) return true if equal?(other) case other when VectorNumber size == other.size && @data == other.to_h when Numeric numeric?(2) && other.real == real && other.imaginary == imaginary else # Can't compare a number-like value to a non-number. false end end |
#[](unit) ⇒ Numeric
Get the coefficient for the unit.
If the unit?(unit) is false, 0 is returned. Note that units for real and imaginary parts are VectorNumber::R and VectorNumber::I respectively.
98 |
# File 'lib/vector_number/enumerating.rb', line 98 def [](unit) = @data[unit] |
#abs2 ⇒ Numeric
Calculate the square of absolute value.
35 36 37 |
# File 'lib/vector_number/vectoring.rb', line 35 def abs2 @data.values.sum(&:abs2) end |
#angle(other) ⇒ Numeric
Calculate the angle between this vector and other vector in radians.
If other is not a VectorNumber, it is automatically promoted.
183 184 185 186 187 188 189 190 191 192 |
# File 'lib/vector_number/vectoring.rb', line 183 def angle(other) has_direction? return 0.0 if equal?(other) other = new([other]) unless VectorNumber === other has_direction?(other) return Math::PI / 2.0 if (product = dot_product(other)).zero? Math.acos(product / magnitude / other.magnitude) end |
#ceil(digits = 0) ⇒ VectorNumber
Return a new vector with every coefficient rounded using their #ceil.
36 37 38 |
# File 'lib/vector_number/math_converting.rb', line 36 def ceil(digits = 0) new { _1.ceil(digits) } end |
#ceildiv(other) ⇒ VectorNumber
Divide all coefficients by a real other, converting results to integers using #ceil.
This is equal to (self / other).ceil.
255 256 257 258 259 260 261 262 |
# File 'lib/vector_number/mathing.rb', line 255 def ceildiv(other) check_divisibility(other) other = other.real other = Rational(other) if other.integer? # @type var other: Float new { (_1 / other).ceil } end |
#clone(freeze: true) ⇒ VectorNumber
Return self.
227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/vector_number.rb', line 227 def clone(freeze: true) case freeze when true, nil self when false raise ArgumentError, "can't unfreeze VectorNumber" else raise ArgumentError, "unexpected value for freeze: #{Kernel.instance_method(:class).bind_call(freeze)}" end end |
#coefficients ⇒ Array<Numeric> Also known as: values
Get a list of non-zero coefficients.
62 |
# File 'lib/vector_number/enumerating.rb', line 62 def coefficients = @data.values |
#coerce(other) ⇒ Array(VectorNumber, VectorNumber)
The coerce method provides support for Ruby type coercion.
Unlike other numeric types, VectorNumber can coerce anything.
25 26 27 28 29 30 31 32 |
# File 'lib/vector_number/mathing.rb', line 25 def coerce(other) case other when VectorNumber [other, self] else [new([other]), self] end end |
#div(other) ⇒ VectorNumber
Divide all coefficients by a real other, converting results to integers using #floor.
This is equal to (self / other).floor.
224 225 226 227 228 229 230 |
# File 'lib/vector_number/mathing.rb', line 224 def div(other) check_divisibility(other) other = other.real # @type var other: Float new { _1.div(other) } end |
#divmod(other) ⇒ Array(VectorNumber, VectorNumber)
328 329 330 |
# File 'lib/vector_number/mathing.rb', line 328 def divmod(other) [div(other), modulo(other)] end |
#dot_product(other) ⇒ Numeric Also known as: inner_product, scalar_product
Calculate the dot product (inner product/scalar product) of this vector with other vector.
If other is not a VectorNumber, it is automatically promoted.
150 151 152 153 154 155 156 157 158 |
# File 'lib/vector_number/vectoring.rb', line 150 def dot_product(other) return 0.0 if zero? return abs2 if equal?(other) other = new([other]) unless VectorNumber === other return 0.0 if other.zero? @data.sum { |u, c| c * other[u] } end |
#each {|unit, coefficient| ... } ⇒ VectorNumber #each ⇒ Enumerator Also known as: each_pair
Iterate through every pair of unit and coefficient. Returns Enumerator (with set size) if no block is given.
35 36 37 38 39 40 |
# File 'lib/vector_number/enumerating.rb', line 35 def each(&block) return to_enum { size } unless block_given? @data.each(&block) self end |
#eql?(other) ⇒ Boolean
Test whether other is VectorNumber and has the same value with eql? semantics.
Values are considered equal only if other is a VectorNumber and it has exactly the same units and coefficients, though possibly in a different order. Additionally, ‘a.eql?(b)` implies `a.hash == b.hash`.
61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/vector_number/comparing.rb', line 61 def eql?(other) return true if equal?(other) return false unless self.class == other.class size.eql?(other.size) && @data.eql?(other.to_h) rescue NoMethodError => e # :nocov: raise unless e.receiver.equal?(other) # :nocov: # Should only happen if `other.class` is undefined. false end |
#fdiv(other) ⇒ VectorNumber
Divide all coefficients by a real other using fdiv, returning new vector with decimal coefficients.
There isn’t much benefit to this method, as #/ doesn’t do integer division, but it is provided for consistency.
189 190 191 192 193 194 195 |
# File 'lib/vector_number/mathing.rb', line 189 def fdiv(other) check_divisibility(other) other = other.real # @type var other: Float new { _1.fdiv(other) } end |
#finite? ⇒ Boolean
Returns true if all coefficients are finite, false otherwise.
60 61 62 |
# File 'lib/vector_number/querying.rb', line 60 def finite? all? { |_u, v| v.finite? } end |
#floor(digits = 0) ⇒ VectorNumber
Return a new vector with every coefficient rounded using their #floor.
53 54 55 |
# File 'lib/vector_number/math_converting.rb', line 53 def floor(digits = 0) new { _1.floor(digits) } end |
#hash ⇒ Integer
Generate an Integer hash value for self.
85 86 87 |
# File 'lib/vector_number/comparing.rb', line 85 def hash [self.class, @data].hash end |
#imaginary ⇒ Numeric Also known as: imag
Return imaginary part of the number.
22 |
# File 'lib/vector_number/converting.rb', line 22 def imaginary = @data[I] |
#infinite? ⇒ 1?
Returns 1 if any coefficients are non-finite, nil otherwise.
This behavior is the same as Complex‘s.
74 75 76 |
# File 'lib/vector_number/querying.rb', line 74 def infinite? finite? ? nil : 1 # rubocop:disable Style/ReturnNilInPredicateMethodDefinition end |
#inspect ⇒ String
Return string representation of the vector suitable for display.
This is similar to Complex#inspect — it returns result of #to_s in round brackets.
68 69 70 |
# File 'lib/vector_number/stringifying.rb', line 68 def inspect "(#{self})" end |
#integer? ⇒ false
Always returns false, as vectors are not Integers.
149 |
# File 'lib/vector_number/querying.rb', line 149 def integer? = false |
#magnitude ⇒ Numeric Also known as: abs
Calculate the magnitude of the vector (its length/absolute value).
This is also known as Euclidean norm or 2-norm.
18 19 20 |
# File 'lib/vector_number/vectoring.rb', line 18 def magnitude abs2**0.5 end |
#maximum_norm ⇒ Numeric Also known as: infinity_norm
Calculate the maximum norm (infinity norm) of the vector.
67 68 69 70 71 |
# File 'lib/vector_number/vectoring.rb', line 67 def maximum_norm return 0 if zero? @data.values.map(&:abs).max end |
#negative? ⇒ Boolean
Returns true if number is non-zero and all non-zero coefficients are negative, and false otherwise.
131 132 133 |
# File 'lib/vector_number/querying.rb', line 131 def negative? !zero? && all? { |_u, c| c.negative? } end |
#nonnumeric?(dimensions = 2) ⇒ Boolean
Returns true if this VectorNumber contains any non-zero dimensions with non-numeric units, and false otherwise.
This is exactly the opposite of #numeric?.
50 |
# File 'lib/vector_number/querying.rb', line 50 def nonnumeric?(dimensions = 2) = !numeric?(dimensions) |
#nonzero? ⇒ VectorNumber?
Returns self if there are any non-zero coefficients, nil otherwise.
This is synonymous with size not being equal to 0. Behavior of returning self or nil is the same as Numeric‘s.
103 104 105 |
# File 'lib/vector_number/querying.rb', line 103 def nonzero? zero? ? nil : self # rubocop:disable Style/ReturnNilInPredicateMethodDefinition end |
#numeric?(dimensions = 2) ⇒ Boolean
Returns true if all non-zero dimensions in this VectorNumber are numeric (real or complex), and false otherwise.
This is exactly the opposite of #nonnumeric?.
27 28 29 30 31 32 |
# File 'lib/vector_number/querying.rb', line 27 def numeric?(dimensions = 2) raise ArgumentError, "`dimensions` must be non-negative" unless dimensions >= 0 size <= dimensions && (0...dimensions).count { (unit = NUMERIC_UNITS[_1]) && @data[unit].nonzero? } == size end |
#p_norm(p) ⇒ Numeric
Calculate the p-norm of the vector.
52 53 54 |
# File 'lib/vector_number/vectoring.rb', line 52 def p_norm(p) # rubocop:disable Naming/MethodParameterName @data.values.sum { _1.abs**p }**(1.0 / p) end |
#positive? ⇒ Boolean
Returns true if number is non-zero and all non-zero coefficients are positive, and false otherwise.
117 118 119 |
# File 'lib/vector_number/querying.rb', line 117 def positive? !zero? && all? { |_u, c| c.positive? } end |
#real ⇒ Numeric
Return real part of the number.
13 |
# File 'lib/vector_number/converting.rb', line 13 def real = @data[R] |
#real? ⇒ false
Always returns false, as vectors are not real numbers.
This behavior is the same as Complex‘s.
142 |
# File 'lib/vector_number/querying.rb', line 142 def real? = false |
#remainder(other) ⇒ VectorNumber
Return the remainder of dividing self by a real other as a vector.
This is equal to self - other * (self/other).truncate.
359 360 361 362 363 364 365 |
# File 'lib/vector_number/mathing.rb', line 359 def remainder(other) check_divisibility(other) other = other.real # @type var other: Float new { _1.remainder(other) } end |
#round(digits = 0, half: :up) ⇒ VectorNumber
Return a new vector with every coefficient rounded using their #round.
In the case of BigDecimal coefficients, the half parameter is converted to the corresponding BigDecimal rounding mode (one of :half_up, :half_down, or :half_even). Other modes can not be specified.
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/vector_number/math_converting.rb', line 80 def round(digits = 0, half: :up) if defined?(BigDecimal) bd_mode = case half when :down then :half_down when :even then :half_even else :half_up end new { (BigDecimal === _1) ? _1.round(digits, bd_mode) : _1.round(digits, half: half) } # :nocov: else new { _1.round(digits, half: half) } end # :nocov: end |
#scalar_projection(other) ⇒ Numeric
Calculate the scalar projection of this vector onto other vector.
Absolute value of scalar projection is equal to #magnitude of #vector_projection. Sign of scalar projection depends on the #angle between vectors. If other is not a VectorNumber, it is automatically promoted.
243 244 245 246 247 248 249 250 |
# File 'lib/vector_number/vectoring.rb', line 243 def scalar_projection(other) return magnitude if equal?(other) && has_direction? other = new([other]) unless VectorNumber === other has_direction?(other) dot_product(other) / other.magnitude end |
#scalar_rejection(other) ⇒ Numeric
Calculate the scalar rejection of this vector from other vector.
Scalar rejection is equal to #magnitude of #vector_rejection, and is always non-negative. If other is not a VectorNumber, it is automatically promoted.
302 303 304 305 306 307 308 309 |
# File 'lib/vector_number/vectoring.rb', line 302 def scalar_rejection(other) return 0.0 if equal?(other) && has_direction? other = new([other]) unless VectorNumber === other has_direction?(other) (abs2 - dot_product(other)**2 / other.abs2)**0.5 end |
#subspace_basis ⇒ Array<VectorNumber>
Return an array of vectors forming orthonormal basis of linear subspace this vector belongs to.
88 89 90 |
# File 'lib/vector_number/vectoring.rb', line 88 def subspace_basis units.map { new([_1]) } end |
#to_c ⇒ Complex
Return value as a Complex if only real and/or imaginary parts are non-zero.
131 132 133 134 135 |
# File 'lib/vector_number/converting.rb', line 131 def to_c raise_convert_error(Complex) unless numeric?(2) Complex(real, imaginary) end |
#to_d(ndigits = nil) ⇒ BigDecimal
Return value as a BigDecimal if only real part is non-zero.
109 110 111 112 113 114 115 116 |
# File 'lib/vector_number/converting.rb', line 109 def to_d(ndigits = nil) raise_convert_error(BigDecimal) unless numeric?(1) return BigDecimal(real, ndigits) if ndigits return BigDecimal(real, Float::DIG) if Float === real BigDecimal(real) end |
#to_f ⇒ Float
Return value as a Float if only real part is non-zero.
62 63 64 65 66 |
# File 'lib/vector_number/converting.rb', line 62 def to_f raise_convert_error(Float) unless numeric?(1) real.to_f end |
#to_h(&block) ⇒ Hash{Object => Numeric}
Get mutable hash with vector’s data.
Returned hash has a default value of 0.
75 76 77 78 79 80 81 82 |
# File 'lib/vector_number/enumerating.rb', line 75 def to_h(&block) # TODO: Remove block argument. if block_given? @data.to_h(&block) else @data.dup end end |
#to_i ⇒ Integer Also known as: to_int
Return value as an Integer, truncating it, if only real part is non-zero.
41 42 43 44 45 |
# File 'lib/vector_number/converting.rb', line 41 def to_i raise_convert_error(Integer) unless numeric?(1) real.to_i end |
#to_r ⇒ Rational
Return value as a Rational if only real part is non-zero.
81 82 83 84 85 |
# File 'lib/vector_number/converting.rb', line 81 def to_r raise_convert_error(Rational) unless numeric?(1) real.to_r end |
#to_s(mult: :dot) {|unit, coefficient, index, operator| ... } ⇒ String
Return string representation of the vector suitable for output.
An optional block can be supplied to provide customized substrings for each unit and coefficient pair. Care needs to be taken in handling VectorNumber::R and VectorNumber::I units. numeric_unit? can be used to check if a particular unit needs special handling.
48 49 50 51 52 53 54 55 56 |
# File 'lib/vector_number/stringifying.rb', line 48 def to_s(mult: :dot, &block) if !(String === mult) && !MULT_STRINGS.key?(mult) raise ArgumentError, "unknown key #{mult.inspect}", caller end return "0" if zero? operator = (String === mult) ? mult : MULT_STRINGS[mult] build_string(operator, &block) end |
#truncate(digits = 0) ⇒ VectorNumber
Return a new vector with every coefficient truncated using their #truncate.
19 20 21 |
# File 'lib/vector_number/math_converting.rb', line 19 def truncate(digits = 0) new { _1.truncate(digits) } end |
#uniform_vector ⇒ VectorNumber
Return a new vector with the same non-zero dimensions, but with coefficients equal to 1.
Resulting vector is equal to self.subspace_basis.sum.
107 108 109 |
# File 'lib/vector_number/vectoring.rb', line 107 def uniform_vector new { 1 } end |
#unit?(unit) ⇒ Boolean Also known as: key?
Check if a unit has a non-zero coefficient.
110 |
# File 'lib/vector_number/enumerating.rb', line 110 def unit?(unit) = @data.key?(unit) |
#unit_vector ⇒ VectorNumber
Return a unit vector (vector with magnitude 1) in the direction of this vector.
Magnitude of resulting vector may not be exactly 1 due to rounding errors.
125 126 127 128 129 |
# File 'lib/vector_number/vectoring.rb', line 125 def unit_vector has_direction? self / magnitude end |
#units ⇒ Array<Object> Also known as: keys
Get a list of units with non-zero coefficients.
51 |
# File 'lib/vector_number/enumerating.rb', line 51 def units = @data.keys |
#vector_projection(other) ⇒ VectorNumber
Calculate the vector projection of this vector onto other vector.
If other is not a VectorNumber, it is automatically promoted.
213 214 215 216 217 218 219 220 |
# File 'lib/vector_number/vectoring.rb', line 213 def vector_projection(other) return self if equal?(other) && has_direction? other = new([other]) unless VectorNumber === other has_direction?(other) other * dot_product(other) / other.abs2 end |
#vector_rejection(other) ⇒ VectorNumber
Calculate the vector rejection of this vector from other vector.
Vector rejection is equal to self - self.vector_projection(other). If other is not a VectorNumber, it is automatically promoted.
272 273 274 275 276 277 278 279 |
# File 'lib/vector_number/vectoring.rb', line 272 def vector_rejection(other) return VectorNumber[0] if equal?(other) && has_direction? other = new([other]) unless VectorNumber === other has_direction?(other) self - vector_projection(other) end |
#zero? ⇒ Boolean
Returns true if there are no non-zero coefficients, and false otherwise.
This is synonymous with size being 0.
89 |
# File 'lib/vector_number/querying.rb', line 89 def zero? = size.zero? |