Module: VectorNumber::Mathing

Included in:
VectorNumber
Defined in:
lib/vector_number/mathing.rb

Overview

Methods for performing actual math.

All operators (like *) have aliases (like mult) to make method chaining easier and more natural.

Instance Method Summary collapse

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).

Examples:

VectorNumber[10] % 3 # => (1)
VectorNumber["a", "b", 6].modulo(2) # => (1⋅'a' + 1⋅'b')
-VectorNumber["a"] % VectorNumber[2] # => (1⋅'a')
# Can't divide by a non-real:
VectorNumber["a"] % VectorNumber["b"] # RangeError

numeric types can be divided in reverse

3 % VectorNumber[10] # => (3)
# Can't divide by a non-real:
3 % VectorNumber["a"] # RangeError

compare to #remainder

VectorNumber[-5] % 3 # => (1)
VectorNumber[-5].remainder(3) # => (-2)

Parameters:

  • other (Integer, Float, Rational, BigDecimal, VectorNumber)

Returns:

Raises:

  • (RangeError)

    if other is not a number or is not a real number

  • (ZeroDivisionError)

    if other is zero

See Also:

Since:

  • 0.2.6



257
258
259
260
261
262
# File 'lib/vector_number/mathing.rb', line 257

def %(other)
  check_divisibility(other)

  other = other.real
  new { _1 % other }
end

#*(other) ⇒ VectorNumber Also known as: mult

Multiply all coefficients by a real other, returning new vector.

This effectively multiplies VectorNumber::MathConverting#magnitude by other.

Examples:

VectorNumber[5] * 2 # => (10)
VectorNumber["a", "b", 6].mult(2) # => (2⋅'a' + 2⋅'b' + 12)
VectorNumber["a"] * VectorNumber[2] # => (2⋅'a')
# Can't multiply by a non-real:
VectorNumber["a"] * VectorNumber["b"] # RangeError

numeric types can be multiplied in reverse

2 * VectorNumber[5] # => (10)
2 * VectorNumber["a"] # => (2⋅'a')

Parameters:

  • other (Integer, Float, Rational, BigDecimal, VectorNumber)

Returns:

Raises:

  • (RangeError)

    if other is not a number or other can’t be multiplied by this one

Since:

  • 0.2.1



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) && other.is_a?(self.class)
    # @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 VectorNumber.[].

Examples:

VectorNumber[5] + 10 # => (15)
VectorNumber["a"].add(VectorNumber["b"]) # => (1⋅'a' + 1⋅'b')
VectorNumber["a"] + "b" # => (1⋅'a' + 1⋅'b')

numeric types can be added in reverse

10 + VectorNumber[5] # => (15)
10 + VectorNumber["a"] # => (10 + 1⋅'a')

Parameters:

  • other (Object)

Returns:

Since:

  • 0.2.0



66
67
68
# File 'lib/vector_number/mathing.rb', line 66

def +(other)
  new([self, other])
end

#-(other) ⇒ VectorNumber Also known as: sub

Return new vector as a sum of this and additive inverse of other value.

This is implemented through #+ and #-@.

Examples:

VectorNumber[5] - 3 # => (2)
VectorNumber["a"].sub(VectorNumber["b"]) # => (1⋅'a' - 1⋅'b')
VectorNumber["a"] - "b" # => (1⋅'a' - 1⋅'b')

numeric types can be subtracted in reverse

3 - VectorNumber[5] # => (-2)
3 - VectorNumber["a"] # => (3 - 1⋅'a')

Parameters:

  • other (Object)

Returns:

Since:

  • 0.2.0



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).

Examples:

-VectorNumber[12, "i"] # => (-12 - 1⋅'i')
VectorNumber["a", "b", "a"].neg # => (-2⋅'a' - 1⋅'b')
-VectorNumber["a"] + VectorNumber["a"] # => (0)

Returns:

Since:

  • 0.2.0



44
45
46
# File 'lib/vector_number/mathing.rb', line 44

def -@
  new(&:-@)
end

#/(other) ⇒ VectorNumber Also known as: quo

Note:

This method never does integer division.

Divide all coefficients by a real other, returning new vector.

This effectively multiplies VectorNumber::MathConverting#magnitude by reciprocal of other.

Examples:

VectorNumber[10] / 2 # => (5)
VectorNumber["a", "b", 6].quo(2) # => (1/2⋅'a' + 1/2⋅'b' + 3/1)
VectorNumber["a"] / VectorNumber[2] # => (1/2⋅'a')
# Can't divide by a non-real:
VectorNumber["a"] / VectorNumber["b"] # RangeError

numeric types can be divided in reverse

2 / VectorNumber[10] # => (1/5)
# Can't divide by a non-real:
2 / VectorNumber["a"] # RangeError

Parameters:

  • other (Integer, Float, Rational, BigDecimal, VectorNumber)

Returns:

Raises:

  • (RangeError)

    if other is not a number or is not a real number

  • (ZeroDivisionError)

    if other is zero

Since:

  • 0.2.1



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

#coerce(other) ⇒ Array(VectorNumber, VectorNumber)

The coerce method provides support for Ruby type coercion.

Unlike other numeric types, VectorNumber can coerce anything.

Examples:

VectorNumber["a"].coerce(5) # => [(5), (1⋅'a')]
VectorNumber[7].coerce([]) # => [(1⋅[]), (7)]
VectorNumber["a"] + 5 # => (1⋅'a' + 5)
# Direct reverse coercion doesn't work, but Numeric types know how to call #coerce:
5.coerce(VectorNumber["a"]) # RangeError
5 + VectorNumber["a"] # => (5 + 1⋅'a')

Parameters:

  • other (Object)

Returns:

Since:

  • 0.2.0



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, rounding results with #floor.

This is requal to (self / other).floor.

Examples:

VectorNumber[10].div(3) # => (3)
VectorNumber["a"].div(2) # => (0⋅'a')
VectorNumber["a"].div(VectorNumber[2]) # => (0⋅'a')
# Can't divide by a non-real:
VectorNumber["a"].div(VectorNumber["b"]) # RangeError

numeric types can be divided in reverse

2.div(VectorNumber[10]) # => (0)
# Can't divide by a non-real:
2.div(VectorNumber["a"]) # RangeError

Parameters:

  • other (Integer, Float, Rational, BigDecimal, VectorNumber)

Returns:

Raises:

  • (RangeError)

    if other is not a number or is not a real number

  • (ZeroDivisionError)

    if other is zero

See Also:

Since:

  • 0.2.6



220
221
222
223
224
225
# File 'lib/vector_number/mathing.rb', line 220

def div(other)
  check_divisibility(other)

  other = other.real
  new { _1.div(other) }
end

#divmod(other) ⇒ Array(VectorNumber, VectorNumber)

Return the quotient and modulus of dividing self by a real other. There is no performance benefit compared to calling #div and #% separately.

Examples:

VectorNumber[10].divmod(3) # => [(3), (1)]
VectorNumber["a"].divmod(2) # => [(0⋅'a'), (1⋅'a')]
VectorNumber["a"].divmod(VectorNumber[2]) # => [(0⋅'a'), (1⋅'a')]
# Can't divide by a non-real:
VectorNumber["a"].divmod(VectorNumber["b"]) # RangeError

numeric types can be divided in reverse

3.divmod(VectorNumber[10]) # => [(0), (3)]
# Can't divide by a non-real:
3.divmod(VectorNumber["a"]) # RangeError

Parameters:

  • other (Integer, Float, Rational, BigDecimal, VectorNumber)

Returns:

Raises:

  • (RangeError)

    if other is not a number or is not a real number

  • (ZeroDivisionError)

    if other is zero

See Also:

Since:

  • 0.2.6



290
291
292
# File 'lib/vector_number/mathing.rb', line 290

def divmod(other)
  [div(other), modulo(other)]
end

#fdiv(other) ⇒ VectorNumber

Divide all coefficients by a real other using fdiv, returning new vector with Float (or BigDecimal) coefficients.

There isn’t much benefit to this method, as #/ doesn’t do integer division, but it is provided for consistency.

Examples:

VectorNumber[10].fdiv(2) # => (5.0)
VectorNumber["a", "b", 6].fdiv(2) # => (0.5⋅'a' + 0.5⋅'b' + 3.0)
VectorNumber["a"].fdiv(VectorNumber[2]) # => (0.5⋅'a')
# Can't divide by a non-real:
VectorNumber["a"].fdiv(VectorNumber["b"]) # RangeError

reverse division may return non-vector results

2.fdiv(VectorNumber[10]) # => 0.2 (Float)
2.0.fdiv(VectorNumber[10]) # => (0.2) (VectorNumber)

Parameters:

  • other (Integer, Float, Rational, BigDecimal, VectorNumber)

Returns:

Raises:

  • (RangeError)

    if other is not a number or is not a real number

  • (ZeroDivisionError)

    if other is zero

Since:

  • 0.2.1



189
190
191
192
193
194
# File 'lib/vector_number/mathing.rb', line 189

def fdiv(other)
  check_divisibility(other)

  other = other.real
  new { _1.fdiv(other) }
end

#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.

Examples:

VectorNumber[10].remainder(3) # => (1)
VectorNumber["a"].remainder(2) # => (1⋅'a')
-VectorNumber["a"].remainder(VectorNumber[2]) # => (-1⋅'a')
# Can't divide by a non-real:
VectorNumber["a"].remainder(VectorNumber["b"]) # RangeError

numeric types can be divided in reverse

3.remainder(VectorNumber[10]) # => (3)
# Can't divide by a non-real:
3.remainder(VectorNumber["a"]) # RangeError

compare to #%

VectorNumber[-5] % 3 # => (1)
VectorNumber[-5].remainder(3) # => (-2)

Parameters:

  • other (Integer, Float, Rational, BigDecimal, VectorNumber)

Returns:

Raises:

  • (RangeError)

    if other is not a number or is not a real number

  • (ZeroDivisionError)

    if other is zero

See Also:

  • #%
  • Numeric#remainder

Since:

  • 0.2.6



321
322
323
324
325
326
# File 'lib/vector_number/mathing.rb', line 321

def remainder(other)
  check_divisibility(other)

  other = other.real
  new { _1.remainder(other) }
end