Class: HyperComplex

Inherits:
Numeric show all
Defined in:
lib/hyper_complex.rb,
lib/version.rb

Overview

Class HyperComplex Uses Cayley-Dickson construction

  • A subclass of Numeric

Constant Summary collapse

VERSION =
'1.0.3'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.[]HyperComplex

Creates a HyperComplex object.

Examples:

HyperComplex[1, 2, 3, 4, 5, 6] #=> HyperComplex[1, 2, 3, 4, 5, 6, 0, 0]

Raises:

  • (ArgumentError)


90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/hyper_complex.rb', line 90

def hrect(*args)
  begin
    raise ArgumentError, 'Not all components are real' unless args.map(&:real?).all?
  rescue NoMethodError
    raise ArgumentError, 'Not all components are numeric'
  end
  s = args.length
  if s < 2
    if s.zero?
      args = [0, 0]
    else
      args.push 0
    end
    s = 2
  end
  s1 = 1 << (s.bit_length - 1)
  if s == s1
    new(*args)
  else
    new(*args.concat(Array.new((s1 << 1) - s, 0)))
  end
end

.e(num) ⇒ HyperComplex or Integer

Creates HyperComplex basis element (identity or imaginary)

Examples:

HyperComplex.e(5) #=> HyperComplex[0, 0, 0, 0, 0, 1, 0, 0]

Raises:

  • (ArgumentError)


148
149
150
151
152
153
# File 'lib/hyper_complex.rb', line 148

def e(num)
  raise ArgumentError, 'Argument must be non-negative integer' if !num.is_a?(Integer) || num.negative?
  return 1 if num.zero?

  hrect(*Array.new(num, 0), 1)
end

.hrect(*args) ⇒ HyperComplex

Creates a HyperComplex object.

Examples:

HyperComplex[1, 2, 3, 4, 5, 6] #=> HyperComplex[1, 2, 3, 4, 5, 6, 0, 0]

Raises:

  • (ArgumentError)


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/hyper_complex.rb', line 67

def hrect(*args)
  begin
    raise ArgumentError, 'Not all components are real' unless args.map(&:real?).all?
  rescue NoMethodError
    raise ArgumentError, 'Not all components are numeric'
  end
  s = args.length
  if s < 2
    if s.zero?
      args = [0, 0]
    else
      args.push 0
    end
    s = 2
  end
  s1 = 1 << (s.bit_length - 1)
  if s == s1
    new(*args)
  else
    new(*args.concat(Array.new((s1 << 1) - s, 0)))
  end
end

.hyperrectangularHyperComplex

Creates a HyperComplex object.

Examples:

HyperComplex[1, 2, 3, 4, 5, 6] #=> HyperComplex[1, 2, 3, 4, 5, 6, 0, 0]

Raises:

  • (ArgumentError)


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/hyper_complex.rb', line 89

def hrect(*args)
  begin
    raise ArgumentError, 'Not all components are real' unless args.map(&:real?).all?
  rescue NoMethodError
    raise ArgumentError, 'Not all components are numeric'
  end
  s = args.length
  if s < 2
    if s.zero?
      args = [0, 0]
    else
      args.push 0
    end
    s = 2
  end
  s1 = 1 << (s.bit_length - 1)
  if s == s1
    new(*args)
  else
    new(*args.concat(Array.new((s1 << 1) - s, 0)))
  end
end

.polar(radius, theta, vector) ⇒ HyperComplex

Creates a HyperComplex object.

Examples:

HyperComplex.polar(1, Math::PI / 4 , [1, 2, 3])
  #=> HyperComplex[-0.9794859508794878, 0.0538564706483192, 0.1077129412966384, 0.1615694119449576]

Raises:

  • (ArgumentError, TypeError)


119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/hyper_complex.rb', line 119

def polar(radius, theta, vector)
  vs1 = vector.size + 1
  raise TypeError, 'Vector size must be at least 3' if vs1 < 4
  raise TypeError, 'Vector size is not equal to 2**n - 1' if vs1 != 1 << (vs1.bit_length - 1)

  begin
    raise ArgumentError, 'Not all components are real' unless [radius, theta, *vector].map(&:real?).all?
  rescue NoMethodError
    raise ArgumentError, 'Not all components are numeric'
  end
  vector = Vector[*vector] unless vector.is_a?(Vector)
  norm = vector.norm
  theta *= norm
  r_cos = radius * Math.cos(theta)
  r_sin = radius * Math.sin(theta)
  r_sin /= norm unless norm.zero?
  hrect(r_cos, *(r_sin * vector))
end

Prints the multiplication table to stdout

Examples:

HyperComplex.print_mt(8)
    |  e0  e1  e2  e3  e4  e5  e6  e7
----+--------------------------------
  e0|  e0  e1  e2  e3  e4  e5  e6  e7
  e1|  e1 -e0  e3 -e2  e5 -e4 -e7  e6
  e2|  e2 -e3 -e0  e1  e6  e7 -e4 -e5
  e3|  e3  e2 -e1 -e0  e7 -e6  e5 -e4
  e4|  e4 -e5 -e6 -e7 -e0  e1  e2  e3
  e5|  e5  e4 -e7  e6 -e1 -e0 -e3  e2
  e6|  e6  e7  e4 -e5 -e2  e3 -e0 -e1
  e7|  e7 -e6  e5  e4 -e3 -e2  e1 -e0

Raises:

  • (ArgumentError)


191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/hyper_complex.rb', line 191

def print_mt(dim)
  table = @@mt = calc_mt(dim) if dim > @@mt.length
  ss = dim
  sf = ss.to_s.length + 3
  out_s = "#{' ' * sf}|"
  (0...ss).each { out_s << format("%#{sf}s", "e#{_1}") }
  puts out_s
  puts "#{'-' * sf}+#{'-' * ss * sf}"
  out_s = format("%#{sf}s|", 'e0')
  (0...ss).each { out_s << format("%#{sf}s", "e#{_1}") }
  puts out_s
  (1...ss).each do |i|
    out_s = format("%#{sf}s|%#{sf}s", "e#{i}", "e#{i}")
    (1...i).each do |j|
      t = table[i][j]
      out_s << format("%#{sf}s", (t.negative? ? '-' : ' ') + "e#{t.abs}")
    end
    out_s << format("%#{sf}s", '-e0')
    ((i + 1)...ss).each do |j|
      t = table[j][i]
      out_s << format("%#{sf}s", (t.negative? ? ' ' : '-') + "e#{t.abs}")
    end
    puts out_s
  end
end

.rect(arg_a, arg_b = 0) ⇒ HyperComplex

Creates a HyperComplex object arg_a + arg_b*e[]

Examples:

HyperComplex.rect(HyperComplex.rect(1+2i, 3+4i), HyperComplex.rect(5,6))
  #=> HyperComplex[1, 2, 3, 4, 5, 6, 0, 0]

Raises:

  • (ArgumentError)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/hyper_complex.rb', line 41

def rect(arg_a, arg_b = 0)
  raise ArgumentError, 'Not all arguments are Numeric' unless arg_a.is_a?(Numeric) && arg_b.is_a?(Numeric)

  a = arg_a.real? ? [arg_a] : arg_a.hrect
  b = arg_b.real? ? [arg_b] : arg_b.hrect
  as = a.length
  bs = b.length
  if as > bs
    b.concat(Array.new(as - bs, 0))
  elsif as < bs
    a.concat(Array.new(bs - as, 0))
  end
  new(*(a + b))
end

.rectangularHyperComplex

Creates a HyperComplex object arg_a + arg_b*e[]

Examples:

HyperComplex.rect(HyperComplex.rect(1+2i, 3+4i), HyperComplex.rect(5,6))
  #=> HyperComplex[1, 2, 3, 4, 5, 6, 0, 0]

Raises:

  • (ArgumentError)


55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/hyper_complex.rb', line 55

def rect(arg_a, arg_b = 0)
  raise ArgumentError, 'Not all arguments are Numeric' unless arg_a.is_a?(Numeric) && arg_b.is_a?(Numeric)

  a = arg_a.real? ? [arg_a] : arg_a.hrect
  b = arg_b.real? ? [arg_b] : arg_b.hrect
  as = a.length
  bs = b.length
  if as > bs
    b.concat(Array.new(as - bs, 0))
  elsif as < bs
    a.concat(Array.new(bs - as, 0))
  end
  new(*(a + b))
end

.zero(num) ⇒ HyperComplex or Integer

Creates HyperComplex zero

Examples:

HyperComplex.zero(5) #=> HyperComplex[0, 0, 0, 0, 0, 0, 0, 0]

Raises:

  • (ArgumentError)


165
166
167
168
169
170
# File 'lib/hyper_complex.rb', line 165

def zero(num)
  raise ArgumentError, 'Argument must positive integer' unless num.is_a?(Integer) && num.positive?
  return 0 if num == 1

  hrect(*Array.new(num, 0))
end

Instance Method Details

#*(other) ⇒ HyperComplex

Performs multiplication (a, b)*(c, d) = (a*c - d.conj*b, d*a + b*c.conj).

Examples:

HyperComplex[1, 2, 3, 4] * HyperComplex[4, 3, 2, 1] #=> HyperComplex[-12, 6, 24, 12]


545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
# File 'lib/hyper_complex.rb', line 545

def *(other) # rubocop:disable Metrics/AbcSize
  sar, oar = homogenize(other)
  ss = sar.length
  begin
    res = Array.new(ss, 0)
    res[0] = sar[0] * oar[0]
    (1...ss).each do |i|
      res[0] -= sar[i] * oar[i]
      res[i] += sar[0] * oar[i] + sar[i] * oar[0]
      ((i + 1)...ss).each do |j|
        ind = @@mt[j][i]
        if ind.positive?
          res[ind] -= sar[i] * oar[j] - sar[j] * oar[i]
        else
          res[-ind] += sar[i] * oar[j] - sar[j] * oar[i]
        end
      end
    end
  rescue NoMethodError, TypeError
    @@mt = HyperComplex.send(:calc_mt, ss)
    retry
  end
  __new__(*res)
end

#**(other) ⇒ HyperComplex

Performs exponentiation.

Examples:

HyperComplex[1, 2, 3, 4]**HyperComplex[4, 3, 2, 1]
  #=> HyperComplex[9.648225704568818, -5.4921479890865506, -8.477947559523633, -4.2389737797618166]

Raises:

  • ArgumentError



774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
# File 'lib/hyper_complex.rb', line 774

def **(other) # rubocop:disable Metrics/AbcSize
  raise ArgumentError, 'Argument must be Numeric' unless other.is_a?(Numeric)

  if other.zero?
    return __new__(*Array.new(dim, Float::NAN)) if zero?

    return __new__(*Array.new(dim - 1, 0).unshift(1))
  end

  unless other.real?
    begin
      other.to_f
    rescue # rubocop:disable Lint/SuppressedException,Style/RescueStandardError
    else
      other = other.real
    end
  end
  other = other.numerator if other.is_a?(Rational) && other.denominator == 1
  if other.integer?
    x = other >= 0 ? self : 1.to_r / self
    n = other.abs
    z = 1
    loop do
      z *= x if n.odd?
      n >>= 1
      return z if n.zero?

      x *= x
    end
  elsif other.real?
    r, theta, vector = polar
    HyperComplex.polar(r**other, theta * other, vector)
  elsif other.is_a?(HyperComplex)
    r, theta, vector = polar
    q = HyperComplex.hrect(Math.log(r), *(theta * vector))
    q *= other
    HyperComplex.polar(Math.exp(q.real), 1, q.imag)
  else
    num2, num1 = coerce(other)
    num1**num2
  end
end

#+(other) ⇒ HyperComplex

Performs addition.

Examples:

HyperComplex[1, 1] + HyperComplex[0, 0, 0, 0, 1, 1] #=> HyperComplex[1, 1, 0, 0, 1, 1, 0, 0]


517
518
519
520
# File 'lib/hyper_complex.rb', line 517

def +(other)
  sar, oar = homogenize(other)
  __new__(*sar.zip(oar).map(&:sum))
end

#-(other) ⇒ HyperComplex

Performs subtraction.

Examples:

HyperComplex[1, 1] - HyperComplex[0, 0, 0, 0, 1, 1] #=> HyperComplex[1, 1, 0, 0, -1, -1, 0, 0]


531
532
533
534
# File 'lib/hyper_complex.rb', line 531

def -(other)
  sar, oar = homogenize(other)
  __new__(*sar.zip(oar).map { |x| x.reduce(:-) })
end

#-@HyperComplex

Returns negation of the value.

Examples:

-HyperComplex[6, 4, 1, 2] #=>  HyperComplex[-6, -4, -1, -2]


402
# File 'lib/hyper_complex.rb', line 402

def -@ = __new__(*@arv.map(&:-@))

#==(other) ⇒ true or false

Returns true if it equals to the other algebraically.

Examples:

HyperComplex[1, 2, 3] == HyperComplex[1, 2, 3, 0] #=> true


456
457
458
459
# File 'lib/hyper_complex.rb', line 456

def ==(other)
  sar, oar = homogenize(other)
  sar == oar
end

#[](index) ⇒ Integer or Rational or Float or nil

Returns the index’s element of hypercomplex number.

Examples:

HyperComplex[4, 3, 2, 1].1 #=> 3


761
# File 'lib/hyper_complex.rb', line 761

def [](index) = @arv[index]

#absInteger or Rational or Float Also known as: magnitude

Returns the absolute part of its polar form.

Examples:

HyperComplex[2, 2, 2, 2].abs #=> 4


433
# File 'lib/hyper_complex.rb', line 433

def abs = Math.sqrt(abs2)

#abs2Integer or Rational or Float

Returns square of the absolute value.

Examples:

HyperComplex[2, 2, 2, 2].abs2 #=> 16


423
# File 'lib/hyper_complex.rb', line 423

def abs2 = @arv.sum { _1**2 }

#argInteger or Rational or Float Also known as: angle, phase

Returns the angle part of its polar form.

Examples:

HyperComplex[3, 2, 2, 1].arg #=> 0.7853981633974483 (Math::PI/4)


338
# File 'lib/hyper_complex.rb', line 338

def arg = Math.atan2(imag.norm, real)

#axisVector

Returns the axis part of its polar form.

Examples:

HyperComplex[6, 4, 4, 2].axis
  #=> Vector[0.6666666666666666, 0.6666666666666666, 0.3333333333333333]


351
352
353
354
355
# File 'lib/hyper_complex.rb', line 351

def axis
  v = imag
  norm = v.norm
  norm.zero? ? Vector[1, *Array.new(@arv.length - 2, 0)] : v / norm
end

#coerce(other) ⇒ [HyperComplex, self]

Performs type conversion.

Examples:

HyperComplex[1, 2, 3, 4].coerce(1) #=> [HyperComplex[1, 0], HyperComplex[1, 2, 3, 4]]

Raises:

  • (TypeError)


668
# File 'lib/hyper_complex.rb', line 668

def coerce(other) = [__new__(*other.hrect), self]

#conjHyperComplex Also known as: conjugate

Returns its conjugate.

Examples:

HyperComplex[6, 4, 1, 2].conj #=>  HyperComplex[6, -4, -1, -2]


412
# File 'lib/hyper_complex.rb', line 412

def conj = __new__ @arv[0], *@arv[1..].map(&:-@)

#dimInteger Also known as: dimension

Returns the dimension of hypercomplex number.

Examples:

HyperComplex[4, 3, 2, 1].dim #=> 4


749
# File 'lib/hyper_complex.rb', line 749

def dim = @arv.length

#eql?(other) ⇒ true or false

Returns true if it have the same dimension and the same elements.

Examples:

HyperComplex[1, 2, 3].eql?(HyperComplex[1, 2, 3, 0]) #=> true
HyperComplex[1/1r, 2, 3, 4].eql?(HyperComplex[1, 2, 3, 4]) #=> false


471
# File 'lib/hyper_complex.rb', line 471

def eql?(other) = @arv.eql?(other.hrect)

#fdiv(other) ⇒ HyperComplex

Performs float division.

Examples:

HyperComplex[12, -4, -2, 1].fdiv(HyperComplex[1, 24, -4, -8])
  #=> HyperComplex[-0.1278538812785388, -0.4748858447488584, 0.0821917808219178, 0.0502283105022831]
HyperComplex[12, -4, -2, 1].fdiv(HyperComplex[0, 0, 0, 0]) #=> HyperComplex[NaN, NaN, NaN, NaN]


651
652
653
654
# File 'lib/hyper_complex.rb', line 651

def fdiv(other)
  t = other.abs2
  self * __new__(*other.conj.hrect.map { _1.to_f / t })
end

#finite?true or false

Returns true if its magnitude is finite, oterwise returns false.

Examples:

HyperComplex[1, 2, 3, 4].finite? #=> true
HyperComplex[1, 2, Float::INFINITY, 4].finite? #=> false


488
# File 'lib/hyper_complex.rb', line 488

def finite? = @arv.map(&:finite?).all?

#finvHyperComplex

Float Inverse element.

Examples:

HyperComplex[0.25, 0.25, 0.25, 0.25].inv #=> HyperComplex[1.0, -1.0, -1.0, -1.0]
HyperComplex[0, 0, 0, 0].inv #=> HyperComplex[NaN, NaN, NaN, NaN]


615
616
617
618
# File 'lib/hyper_complex.rb', line 615

def finv
  t = abs2
  __new__(*conj.hrect.map { _1.to_f / t })
end

#hrect[Integer or Rational or Float, ...] Also known as: hyperrectangular, to_a

Returns an array of real numbers.

Examples:

HyperComplex[1, 2, 3, 4].hrect #=> [1, 2, 3, 4]


303
# File 'lib/hyper_complex.rb', line 303

def hrect = @arv

#imagVector Also known as: imaginary, vector

Returns the imaginary part as a vector.

Examples:

HyperComplex[1, 2, 3, 4].imag #=> Vector[2, 3, 4]


326
# File 'lib/hyper_complex.rb', line 326

def imag = Vector[*hrect.drop(1)]

#infinite?true or false

Returns true if its magnitude is infinite, oterwise returns false.

Examples:

HyperComplex[1, 2, 3, 4].infinite? #=> false
HyperComplex[1, 2, Float::INFINITY, 4].infinite? #=> true


501
# File 'lib/hyper_complex.rb', line 501

def infinite? = @arv.map(&:infinite?).any?

#invHyperComplex Also known as: inverse

Inverse element. Rational arithmetic is used as possible.

Examples:

HyperComplex[1/4r, 1/4r, 1/4r, 1/4r] #=> HyperComplex[1, -1, -1, -1]

Raises:

  • (ZeroDivisionError)

    if all componetns are zero and not Float



600
601
602
603
# File 'lib/hyper_complex.rb', line 600

def inv
  t = abs2
  __new__(*conj.hrect.map { _1.to_r / t })
end

#mul(other) ⇒ HyperComplex

Same as *, but ‘classic’ non-effective algorythm is used.

Examples:

HyperComplex[1, 2, 3, 4].mul(HyperComplex[4, 3, 2, 1]) #=> HyperComplex[-12, 6, 24, 12]


579
580
581
582
583
584
585
586
587
588
589
# File 'lib/hyper_complex.rb', line 579

def mul(other)
  sar, oar = homogenize(other)
  ss = sar.length
  return __new__(sar[0] * oar[0] - oar[1] * sar[1], oar[1] * sar[0] + sar[1] * oar[0]) if ss == 2

  a = __new__(*sar[0...(ss / 2)])
  b = __new__(*sar[(ss / 2)..])
  c = __new__(*oar[0...(ss / 2)])
  d = __new__(*oar[(ss / 2)..])
  __new__(*(a.mul(c) - d.conj.mul(b)).hrect, *(d.mul(a) + b.mul(c.conj)).hrect)
end

#nan?true or false

Returns true if any component is NaN, otherwise returns false

Examples:

HyperComplex[6, 4, Float::NAN, 2].nan? #=> true


385
# File 'lib/hyper_complex.rb', line 385

def nan? = @arv.map { |i| i.equal?(Float::NAN) }.any?

#polar[Integer or Rational or Float, Integer or Rational or Float, Vector]

Returns an array; [abs, arg, axis].

Examples:

HyperComplex[3, 4, 4, 0].polar
 #=> [6.4031242374328485, 1.0831800840797905, Vector[0.7071067811865475, 0.7071067811865475, 0.0]]


445
# File 'lib/hyper_complex.rb', line 445

def polar = [abs, arg, axis]

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

Performs rational as possible division.

Examples:

HyperComplex[12, -4, -2, 1] / HyperComplex[1, 24, -4, -8]
  #=> HyperComplex[-28/219r, -104/219r, 6/73r, 11/219r]

Raises:

  • (ZeroDivisionError)

    if other is zero and no conversion to float was performed.



633
634
635
636
# File 'lib/hyper_complex.rb', line 633

def quo(other)
  t = other.abs2
  self * __new__(*other.conj.hrect.map { _1.to_r / t })
end

#realInteger or Rational or Float Also known as: scalar

Returns the real part.

Examples:

HyperComplex[1, 2, 3, 4].real #=> 1


315
# File 'lib/hyper_complex.rb', line 315

def real = @arv[0]

#real?false

HyperComplex is not real number.

Examples:

HyperComplex[6, 4, 4, 2].real? #=> false


365
# File 'lib/hyper_complex.rb', line 365

def real? = false

#rect[Integer or Rational or Float, Integer or Rational or Float] or [HyperComplex, HyperComplex] Also known as: rectangular

Returns an array of two numbers.

Examples:

HyperComplex[1, 2, 3, 4].rect #=> [HyperComplex[1, 2], HyperComplex[3, 4]]


287
288
289
290
291
292
# File 'lib/hyper_complex.rb', line 287

def rect
  ssh = @arv.length >> 1
  return @arv if ssh == 1

  [__new__(*@arv[0...(ssh)]), __new__(*@arv[ssh..])]
end

#to_cComplex

Performs conversion to Complex.

Examples:

HyperComplex[3, 1, 0, 0].to_f #=> (3+1i)

Raises:

  • (RangeError)


724
725
726
727
728
# File 'lib/hyper_complex.rb', line 724

def to_c
  return Complex(@arv[0], @arv[1]) if @arv.length <= 2 || @arv[2..].map(&:zero?).all?

  raise RangeError, "Can not convert #{inspect} to Complex"
end

#to_fFloat

Performs conversion to Float.

Examples:

HyperComplex[3, 0, 0, 0].to_f #=> 3.0

Raises:

  • (RangeError)


694
695
696
697
698
# File 'lib/hyper_complex.rb', line 694

def to_f
  raise RangeError, "Can not convert #{inspect} to Float" unless @arv[1..].map(&:zero?).all?

  @arv[0].to_f
end

#to_iInteger

Performs conversion to Integer.

Examples:

HyperComplex[3, 0, 0, 0].to_i #=> 3

Raises:

  • (RangeError)


679
680
681
682
683
# File 'lib/hyper_complex.rb', line 679

def to_i
  raise RangeError, "Can not convert #{inspect} to Integer" unless @arv[1..].map(&:zero?).all?

  @arv[0].to_i
end

#to_rRational

Performs conversion to Rational.

Examples:

HyperComplex[3, 0, 0, 0].to_r #=> 3/1r

Raises:

  • (RangeError)


709
710
711
712
713
# File 'lib/hyper_complex.rb', line 709

def to_r
  raise RangeError, "Can not convert #{inspect} to Rational" unless @arv[1..].map(&:zero?).all?

  @arv[0].to_r
end

#to_sString Also known as: inspect

Performs conversion to String.

Examples:

HyperComplex[4, 3, 2, 1].to_f #=> "HyperComplex[4, 3, 2, 1]"


738
# File 'lib/hyper_complex.rb', line 738

def to_s = "HyperComplex#{@arv}"

#zero?true or false

Returns true if all components are zero, otherwise returns false

Examples:

HyperComplex[6, 4, 4, 2].zero? #=> false


375
# File 'lib/hyper_complex.rb', line 375

def zero? = @arv.map(&:zero?).all?