quaternion_c2 0.1.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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +62 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/quaternion_c2.rb +10 -0
- data/lib/quaternion_c2/arithmetic.rb +75 -0
- data/lib/quaternion_c2/attributes.rb +25 -0
- data/lib/quaternion_c2/base.rb +18 -0
- data/lib/quaternion_c2/classification.rb +32 -0
- data/lib/quaternion_c2/conversion.rb +166 -0
- data/lib/quaternion_c2/equality.rb +30 -0
- data/lib/quaternion_c2/to_type.rb +108 -0
- data/lib/quaternion_c2/unary.rb +43 -0
- data/lib/quaternion_c2/units.rb +40 -0
- data/lib/quaternion_c2/utils.rb +71 -0
- data/quaternion_c2.gemspec +25 -0
- metadata +108 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: 11a23c8bee71f2eac9cdd28569ddbd060e1c78d6
         | 
| 4 | 
            +
              data.tar.gz: 2da47444cd5b3c7f50da7f9cb0dfc281dcd187a1
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: 3504d452e7841683a890fb01c8ca3a82ce44c9c334aa3309b50329dd17415a99d021c6d2b56cf0358a5c04d9d09b1aaf44508d030cc75072a32626d4c1a8d1eb
         | 
| 7 | 
            +
              data.tar.gz: 6348e89acb1f9a31923c03d9ea1fac21d10d2a849d55c198fd757021ad35243dce10c411502f4ea4b6e622d331e4e66dfd4b014e46c2774d290320a77507265b
         | 
    
        data/.gitignore
    ADDED
    
    
    
        data/.rspec
    ADDED
    
    
    
        data/.travis.yml
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE.txt
    ADDED
    
    | @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            The MIT License (MIT)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Copyright (c) 2017 Masahiro Nomoto
         | 
| 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
    ADDED
    
    | @@ -0,0 +1,62 @@ | |
| 1 | 
            +
            # Quaternion
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ## Installation
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Add this line to your application's Gemfile:
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            ```ruby
         | 
| 8 | 
            +
            gem 'quaternion_c2'
         | 
| 9 | 
            +
            ```
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            And then execute:
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                $ bundle
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            ## Usage
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            `Quaternion` is similar to a built-in class `Complex`.
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            There are several methods to create a quaternion.  `Kernel.#Quaternion` accepts many patterns of arguments.
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            ```ruby
         | 
| 22 | 
            +
            require 'quaternion_c2'
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            q1 = Quaternion.rect(Complex(1, 2), Complex(3, 4))  #=> (1+2i+3j+4k)
         | 
| 25 | 
            +
            q2 = Quaternion.hrect(1, -2, Rational(-3, 4), 0.56) #=> (1-2i-(3/4)*j+0.56k)
         | 
| 26 | 
            +
            vector = Vector[1, 1, 1].normalize
         | 
| 27 | 
            +
            q3 = Quaternion.polar(1, Math::PI / 3, vector)      #=> (0.5+0.5i+0.5j+0.5k)
         | 
| 28 | 
            +
            q4 = Quaternion(1, [2, 3, 4])                       #=> (1+2i+3j+4k)
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            q1.rect  #=> [(1+2i), (3+4i)]
         | 
| 31 | 
            +
            q2.hrect #=> [1, -2, (-3/4), 0.56]
         | 
| 32 | 
            +
            q3.polar #=> [1.0, Math::PI / 3, vector]
         | 
| 33 | 
            +
            q4.real  #=> 1
         | 
| 34 | 
            +
            q4.imag  #=> Vector[2, 3, 4]
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            Complex::I.to_q     #=> (0+1i+0j+0k)
         | 
| 37 | 
            +
            1 + 2.i + 3.j + 4.k #=> (1+2i+3j+4k)
         | 
| 38 | 
            +
            ```
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            `Quaternion` supports standard calculations between numeric instances.
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            ```ruby
         | 
| 43 | 
            +
            Complex::I * Quaternion::J  #=> (0+0i+0j+1k)
         | 
| 44 | 
            +
            1 / Quaternion::I           #=> ((0/1)-(1/1)*i+(0/0)*j+(0/0)*k)
         | 
| 45 | 
            +
            Quaternion(1, 1, 1, 1) ** 6 #=> (64+0i+0j+0k)
         | 
| 46 | 
            +
            ```
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            ## Development
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            ## Contributing
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            Bug reports and pull requests are welcome on GitHub at https://github.com/hmmnrst/quaternion_c2.
         | 
| 57 | 
            +
             | 
| 58 | 
            +
             | 
| 59 | 
            +
            ## License
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
         | 
| 62 | 
            +
             | 
    
        data/Rakefile
    ADDED
    
    
    
        data/bin/console
    ADDED
    
    | @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "bundler/setup"
         | 
| 4 | 
            +
            require "quaternion_c2"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # You can add fixtures and/or initialization code here to make experimenting
         | 
| 7 | 
            +
            # with your gem easier. You can also use a different console, if you like.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            # (If you use this, don't forget to add pry to your Gemfile!)
         | 
| 10 | 
            +
            # require "pry"
         | 
| 11 | 
            +
            # Pry.start
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            require "irb"
         | 
| 14 | 
            +
            IRB.start(__FILE__)
         | 
    
        data/bin/setup
    ADDED
    
    
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            require "quaternion_c2/base"
         | 
| 2 | 
            +
            require "quaternion_c2/classification"
         | 
| 3 | 
            +
            require "quaternion_c2/unary"
         | 
| 4 | 
            +
            require "quaternion_c2/units"
         | 
| 5 | 
            +
            require "quaternion_c2/equality"
         | 
| 6 | 
            +
            require "quaternion_c2/attributes"
         | 
| 7 | 
            +
            require "quaternion_c2/arithmetic"
         | 
| 8 | 
            +
            require "quaternion_c2/to_type"
         | 
| 9 | 
            +
            require "quaternion_c2/conversion"
         | 
| 10 | 
            +
            require "quaternion_c2/utils"
         | 
| @@ -0,0 +1,75 @@ | |
| 1 | 
            +
            require_relative 'base'
         | 
| 2 | 
            +
            require_relative 'classification'
         | 
| 3 | 
            +
            require_relative 'unary'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            #
         | 
| 6 | 
            +
            # Basic arithmetic operators (#+, #-, #*, #/)
         | 
| 7 | 
            +
            # and related methods
         | 
| 8 | 
            +
            #
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            class Quaternion
         | 
| 11 | 
            +
            	def +(other)
         | 
| 12 | 
            +
            		if other.kind_of?(Quaternion)
         | 
| 13 | 
            +
            			__new__(@a + other.a, @b + other.b)
         | 
| 14 | 
            +
            		elsif other.kind_of?(Numeric) && other.complex?
         | 
| 15 | 
            +
            			__new__(@a + other, @b)
         | 
| 16 | 
            +
            		else
         | 
| 17 | 
            +
            			n1, n2 = other.coerce(self)
         | 
| 18 | 
            +
            			n1 + n2
         | 
| 19 | 
            +
            		end
         | 
| 20 | 
            +
            	end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            	def -(other)
         | 
| 23 | 
            +
            		if other.kind_of?(Quaternion)
         | 
| 24 | 
            +
            			__new__(@a - other.a, @b - other.b)
         | 
| 25 | 
            +
            		elsif other.kind_of?(Numeric) && other.complex?
         | 
| 26 | 
            +
            			__new__(@a - other, @b)
         | 
| 27 | 
            +
            		else
         | 
| 28 | 
            +
            			n1, n2 = other.coerce(self)
         | 
| 29 | 
            +
            			n1 - n2
         | 
| 30 | 
            +
            		end
         | 
| 31 | 
            +
            	end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            	def *(other)
         | 
| 34 | 
            +
            		if other.kind_of?(Quaternion)
         | 
| 35 | 
            +
            			_a = other.a
         | 
| 36 | 
            +
            			_b = other.b
         | 
| 37 | 
            +
            			__new__(@a * _a - _b.conj * @b, _b * @a + @b * _a.conj)
         | 
| 38 | 
            +
            		elsif other.kind_of?(Numeric) && other.complex?
         | 
| 39 | 
            +
            			__new__(@a * other, @b * other.conj)
         | 
| 40 | 
            +
            		else
         | 
| 41 | 
            +
            			n1, n2 = other.coerce(self)
         | 
| 42 | 
            +
            			n1 * n2
         | 
| 43 | 
            +
            		end
         | 
| 44 | 
            +
            	end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            	[:quo, :fdiv].each do |sym|
         | 
| 47 | 
            +
            		define_method(sym) do |other|
         | 
| 48 | 
            +
            			if other.kind_of?(Quaternion)
         | 
| 49 | 
            +
            				self * other.conj.send(sym, other.abs2)
         | 
| 50 | 
            +
            			elsif other.kind_of?(Numeric) && other.complex?
         | 
| 51 | 
            +
            				__new__(@a.send(sym, other), @b.send(sym, other.conj))
         | 
| 52 | 
            +
            			else
         | 
| 53 | 
            +
            				n1, n2 = other.coerce(self)
         | 
| 54 | 
            +
            				n1.send(sym, n2)
         | 
| 55 | 
            +
            			end
         | 
| 56 | 
            +
            		end
         | 
| 57 | 
            +
            	end
         | 
| 58 | 
            +
            	alias / quo
         | 
| 59 | 
            +
            	undef div, %, modulo, remainder, divmod
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            	#
         | 
| 62 | 
            +
            	# Conversion
         | 
| 63 | 
            +
            	#
         | 
| 64 | 
            +
             | 
| 65 | 
            +
            	def coerce(other)
         | 
| 66 | 
            +
            		if other.kind_of?(Quaternion)
         | 
| 67 | 
            +
            			[other, self]
         | 
| 68 | 
            +
            		elsif other.kind_of?(Numeric) && other.complex?
         | 
| 69 | 
            +
            			[__new__(other, 0), self]
         | 
| 70 | 
            +
            		else
         | 
| 71 | 
            +
            			raise TypeError,
         | 
| 72 | 
            +
            			      "#{other.class} can't be coerced into #{self.class}"
         | 
| 73 | 
            +
            		end
         | 
| 74 | 
            +
            	end
         | 
| 75 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            require_relative 'unary'
         | 
| 2 | 
            +
            require_relative 'equality'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            class Quaternion
         | 
| 5 | 
            +
            	# defined by Numeric:
         | 
| 6 | 
            +
            	# * zero?    #=> self == 0
         | 
| 7 | 
            +
            	# * nonzero? #=> zero? ? nil : self
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            	defined_methods = public_instance_methods
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            	if defined_methods.include?(:finite?)
         | 
| 12 | 
            +
            		def finite?
         | 
| 13 | 
            +
            			abs.finite?
         | 
| 14 | 
            +
            		end
         | 
| 15 | 
            +
            	end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            	if defined_methods.include?(:infinite?)
         | 
| 18 | 
            +
            		def infinite?
         | 
| 19 | 
            +
            			abs.infinite?
         | 
| 20 | 
            +
            		end
         | 
| 21 | 
            +
            	end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            	undef positive? if defined_methods.include?(:positive?)
         | 
| 24 | 
            +
            	undef negative? if defined_methods.include?(:negative?)
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            require_relative 'base'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            #
         | 
| 4 | 
            +
            # Number system classification
         | 
| 5 | 
            +
            # (N <) Z < Q < R < C < H (< ...)
         | 
| 6 | 
            +
            #
         | 
| 7 | 
            +
            # * quaternion?  : [H] Quaternion (*undefined*)
         | 
| 8 | 
            +
            # * && complex?  : [C] Complex
         | 
| 9 | 
            +
            # * && real?     : [R] Float, BigDecimal, Numeric
         | 
| 10 | 
            +
            # * && rational? : [Q] Rational (*undefined*)
         | 
| 11 | 
            +
            # * && integer?  : [Z] Fixnum, Bignum, Integer
         | 
| 12 | 
            +
            #
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            class Numeric
         | 
| 15 | 
            +
            	# defined:
         | 
| 16 | 
            +
            	# * integer? #=> false
         | 
| 17 | 
            +
            	# * real?    #=> true
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            	def complex?
         | 
| 20 | 
            +
            		true
         | 
| 21 | 
            +
            	end
         | 
| 22 | 
            +
            end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            class Quaternion
         | 
| 25 | 
            +
            	def real?
         | 
| 26 | 
            +
            		false
         | 
| 27 | 
            +
            	end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            	def complex?
         | 
| 30 | 
            +
            		false
         | 
| 31 | 
            +
            	end
         | 
| 32 | 
            +
            end
         | 
| @@ -0,0 +1,166 @@ | |
| 1 | 
            +
            require_relative 'base'
         | 
| 2 | 
            +
            require_relative 'classification'
         | 
| 3 | 
            +
            require_relative 'unary'
         | 
| 4 | 
            +
            require_relative 'units'
         | 
| 5 | 
            +
            require_relative 'arithmetic'
         | 
| 6 | 
            +
            require_relative 'to_type'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            require 'matrix'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            class Quaternion
         | 
| 11 | 
            +
            	#
         | 
| 12 | 
            +
            	# Constructors
         | 
| 13 | 
            +
            	#
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            	class << self
         | 
| 16 | 
            +
            		def rect(a, b = 0)
         | 
| 17 | 
            +
            			unless [a, b].all? { |c| c.kind_of?(Numeric) && c.complex? }
         | 
| 18 | 
            +
            				raise TypeError, 'not a complex'
         | 
| 19 | 
            +
            			end
         | 
| 20 | 
            +
            			new(a, b)
         | 
| 21 | 
            +
            		end
         | 
| 22 | 
            +
            		alias rectangular rect
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            		def hrect(w, x = 0, y = 0, z = 0)
         | 
| 25 | 
            +
            			a = Complex.rect(w, x)
         | 
| 26 | 
            +
            			b = Complex.rect(y, z)
         | 
| 27 | 
            +
            			new(a, b)
         | 
| 28 | 
            +
            		end
         | 
| 29 | 
            +
            		alias hyperrectangular hrect
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            		# Quaternion.polar(r) == r
         | 
| 32 | 
            +
            		# Quaternion.polar(r, theta) == Complex.polar(r, theta)
         | 
| 33 | 
            +
            		def polar(r, theta = 0, vector = Vector[1, 0, 0])
         | 
| 34 | 
            +
            			unless vector.kind_of?(Enumerable) && vector.size == 3
         | 
| 35 | 
            +
            				raise TypeError, 'not a 3-D vector'
         | 
| 36 | 
            +
            			end
         | 
| 37 | 
            +
            			unless [r, theta, *vector].all? { |a| a.kind_of?(Numeric) && a.real? }
         | 
| 38 | 
            +
            				raise TypeError, 'not a real'
         | 
| 39 | 
            +
            			end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            			vector = Vector[*vector] unless vector.kind_of?(Vector)
         | 
| 42 | 
            +
            			norm = vector.norm
         | 
| 43 | 
            +
            			theta *= norm
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            			r_cos = r * Math.cos(theta)
         | 
| 46 | 
            +
            			r_sin = r * Math.sin(theta)
         | 
| 47 | 
            +
            			r_sin /= norm if norm > 0
         | 
| 48 | 
            +
            			hrect(r_cos, *(r_sin * vector))
         | 
| 49 | 
            +
            		end
         | 
| 50 | 
            +
            	end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            	#
         | 
| 53 | 
            +
            	# Accessors
         | 
| 54 | 
            +
            	#
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            	def rect
         | 
| 57 | 
            +
            		[@a, @b]
         | 
| 58 | 
            +
            	end
         | 
| 59 | 
            +
            	alias rectangular rect
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            	def hrect
         | 
| 62 | 
            +
            		rect.flat_map(&:rect)
         | 
| 63 | 
            +
            	end
         | 
| 64 | 
            +
            	alias hyperrectangular hrect
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            	def real
         | 
| 67 | 
            +
            		@a.real
         | 
| 68 | 
            +
            	end
         | 
| 69 | 
            +
            	alias scalar real
         | 
| 70 | 
            +
             | 
| 71 | 
            +
            	def imag
         | 
| 72 | 
            +
            		Vector[*hrect.drop(1)]
         | 
| 73 | 
            +
            	end
         | 
| 74 | 
            +
            	alias imaginary imag
         | 
| 75 | 
            +
            	alias vector imag
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            	# defined in unary.rb:
         | 
| 78 | 
            +
            	# * abs
         | 
| 79 | 
            +
            	# * magnitude
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            	def arg
         | 
| 82 | 
            +
            		r_cos = real
         | 
| 83 | 
            +
            		r_sin = imag.norm
         | 
| 84 | 
            +
            		Math.atan2(r_sin, r_cos)
         | 
| 85 | 
            +
            	end
         | 
| 86 | 
            +
            	alias angle arg
         | 
| 87 | 
            +
            	alias phase arg
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            	def axis
         | 
| 90 | 
            +
            		v = imag
         | 
| 91 | 
            +
            		norm = v.norm
         | 
| 92 | 
            +
            		if norm.zero?
         | 
| 93 | 
            +
            			# imag[0] == +0.0 -> q = r exp(+I PI)
         | 
| 94 | 
            +
            			# imag[0] ==  0/1 -> q = r exp(+I PI)
         | 
| 95 | 
            +
            			# imag[0] == -0.0 -> q = r exp(-I PI)
         | 
| 96 | 
            +
            			sign = (1.0 / imag[0] >= 0) ? 1 : -1
         | 
| 97 | 
            +
            			Vector[sign, 0, 0]
         | 
| 98 | 
            +
            		else
         | 
| 99 | 
            +
            			v / norm
         | 
| 100 | 
            +
            		end
         | 
| 101 | 
            +
            	end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            	def polar
         | 
| 104 | 
            +
            		[abs, arg, axis]
         | 
| 105 | 
            +
            	end
         | 
| 106 | 
            +
            end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
            #
         | 
| 109 | 
            +
            # Generic constructor
         | 
| 110 | 
            +
            #
         | 
| 111 | 
            +
            # This accepts various arguments:
         | 
| 112 | 
            +
            # * (Numeric)          -> real quaternion
         | 
| 113 | 
            +
            # * (Numeric, Numeric) -> a+bj
         | 
| 114 | 
            +
            # * (Numeric, Vector)  -> scalar and 3-D vector
         | 
| 115 | 
            +
            # * (Numeric, Numeric, Numeric[, Numeric]) -> w+xi+yj+zk
         | 
| 116 | 
            +
            # and String instead of Numeric.
         | 
| 117 | 
            +
            #
         | 
| 118 | 
            +
            module Kernel
         | 
| 119 | 
            +
            	module_function
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            	def Quaternion(*args)
         | 
| 122 | 
            +
            		argc = args.size
         | 
| 123 | 
            +
             | 
| 124 | 
            +
            		unless (1..4).cover?(argc)
         | 
| 125 | 
            +
            			raise ArgumentError,
         | 
| 126 | 
            +
            			      "wrong number of arguments (given #{argc}, expected 1..4)"
         | 
| 127 | 
            +
            		end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
            		if args.any?(&:nil?)
         | 
| 130 | 
            +
            			raise TypeError, "can't convert nil into Quaternion"
         | 
| 131 | 
            +
            		end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
            		# convert String into Numeric (strictly)
         | 
| 134 | 
            +
            		args.collect! do |arg|
         | 
| 135 | 
            +
            			case arg
         | 
| 136 | 
            +
            			when String
         | 
| 137 | 
            +
            				Quaternion.send(:parse, arg, true)
         | 
| 138 | 
            +
            			else
         | 
| 139 | 
            +
            				arg
         | 
| 140 | 
            +
            			end
         | 
| 141 | 
            +
            		end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
            		case argc
         | 
| 144 | 
            +
            		when 2
         | 
| 145 | 
            +
            			if args[1].kind_of?(Enumerable)
         | 
| 146 | 
            +
            				# scalar and 3-D vector
         | 
| 147 | 
            +
            				if args[1].size != 3
         | 
| 148 | 
            +
            					raise TypeError, "not a 3-D vector"
         | 
| 149 | 
            +
            				end
         | 
| 150 | 
            +
            				args = [args[0], *args[1]]
         | 
| 151 | 
            +
            			else
         | 
| 152 | 
            +
            				# a pair of complex numbers
         | 
| 153 | 
            +
            				return args[0] + args[1] * Quaternion::J
         | 
| 154 | 
            +
            			end
         | 
| 155 | 
            +
            		end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
            		# maximum four real numbers
         | 
| 158 | 
            +
            		i = Quaternion::I
         | 
| 159 | 
            +
            		j = Quaternion::J
         | 
| 160 | 
            +
            		k = Quaternion::K
         | 
| 161 | 
            +
            		zero = Quaternion.send(:new, 0, 0)
         | 
| 162 | 
            +
            		args.zip([1, i, j, k]).inject(zero) do |sum,(num,base)|
         | 
| 163 | 
            +
            			sum + num * base
         | 
| 164 | 
            +
            		end
         | 
| 165 | 
            +
            	end
         | 
| 166 | 
            +
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            require_relative 'base'
         | 
| 2 | 
            +
            require_relative 'classification'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            class Quaternion
         | 
| 5 | 
            +
            	undef <=>
         | 
| 6 | 
            +
            	undef_method(*Comparable.instance_methods)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            	def ==(other)
         | 
| 9 | 
            +
            		if other.kind_of?(Quaternion)
         | 
| 10 | 
            +
            			@a == other.a && @b == other.b
         | 
| 11 | 
            +
            		elsif other.kind_of?(Numeric) && other.complex?
         | 
| 12 | 
            +
            			@a == other && @b == 0
         | 
| 13 | 
            +
            		else
         | 
| 14 | 
            +
            			other == self
         | 
| 15 | 
            +
            		end
         | 
| 16 | 
            +
            	end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            	def eql?(other)
         | 
| 19 | 
            +
            		if other.kind_of?(Quaternion)
         | 
| 20 | 
            +
            			@a.eql?(other.a) && @b.eql?(other.b)
         | 
| 21 | 
            +
            		else
         | 
| 22 | 
            +
            			false
         | 
| 23 | 
            +
            		end
         | 
| 24 | 
            +
            	end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            	# q1.eql?(q2) => q1.hash == q2.hash
         | 
| 27 | 
            +
            	def hash
         | 
| 28 | 
            +
            		[@a, @b].hash
         | 
| 29 | 
            +
            	end
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,108 @@ | |
| 1 | 
            +
            require_relative 'base'
         | 
| 2 | 
            +
            require_relative 'unary'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            # to_xxx
         | 
| 6 | 
            +
            #
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            class Quaternion
         | 
| 9 | 
            +
            	# defined by Numeric:
         | 
| 10 | 
            +
            	# * to_int #=> to_i
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            	def to_q
         | 
| 13 | 
            +
            		self
         | 
| 14 | 
            +
            	end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            	def to_c
         | 
| 17 | 
            +
            		unless __exact_zero__(@b)
         | 
| 18 | 
            +
            			raise RangeError, "can't convert #{self} into Complex"
         | 
| 19 | 
            +
            		end
         | 
| 20 | 
            +
            		@a
         | 
| 21 | 
            +
            	end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            	[:to_f, :to_r, :to_i, :rationalize].each do |sym|
         | 
| 24 | 
            +
            		define_method(sym) { |*args| to_c.send(sym, *args) }
         | 
| 25 | 
            +
            	end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            	def to_s
         | 
| 28 | 
            +
            		__format__(:to_s)
         | 
| 29 | 
            +
            	end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            	def inspect
         | 
| 32 | 
            +
            		"(#{__format__(:inspect)})"
         | 
| 33 | 
            +
            	end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            	private
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            	def __format__(sym)
         | 
| 38 | 
            +
            		w, *xyz = [@a, @b].flat_map(&:rect)
         | 
| 39 | 
            +
            		sw = w.send(sym)
         | 
| 40 | 
            +
            		sx, sy, sz = xyz.zip(%w[i j k]).collect do |num,base|
         | 
| 41 | 
            +
            			if num.kind_of?(Float)
         | 
| 42 | 
            +
            				str = num.send(sym)
         | 
| 43 | 
            +
            				str[0,0] = '+' if str[0] != '-'
         | 
| 44 | 
            +
            			elsif num < 0
         | 
| 45 | 
            +
            				str = '-' + (-num).send(sym)
         | 
| 46 | 
            +
            			else
         | 
| 47 | 
            +
            				str = '+' + num.send(sym)
         | 
| 48 | 
            +
            			end
         | 
| 49 | 
            +
            			str << '*' if str[-1] !~ /\d/
         | 
| 50 | 
            +
            			str << base
         | 
| 51 | 
            +
            		end
         | 
| 52 | 
            +
            		[sw, sx, sy, sz].join
         | 
| 53 | 
            +
            	end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            	class << self
         | 
| 56 | 
            +
            		def parse(str, strict = false)
         | 
| 57 | 
            +
            			regexp = %r{
         | 
| 58 | 
            +
            				\A
         | 
| 59 | 
            +
            				\s*+
         | 
| 60 | 
            +
            				(?:(?'real'   [+-]?+           \g'rational'  ) (?![ijk]))?+
         | 
| 61 | 
            +
            				(?:(?'imag_i' \g'head_or_sign' \g'rational'?+) i        )?+
         | 
| 62 | 
            +
            				(?:(?'imag_j' \g'head_or_sign' \g'rational'?+) j        )?+
         | 
| 63 | 
            +
            				(?:(?'imag_k' \g'head_or_sign' \g'rational'?+) k        )?+
         | 
| 64 | 
            +
            				\s*+
         | 
| 65 | 
            +
            				|\z
         | 
| 66 | 
            +
            				(?'head_or_sign' (?<=^|\s) [+-]?+ | [+-])
         | 
| 67 | 
            +
            				(?'digits'       \d++ (?:#{strict ? "_" : "_++"} \d++)*+)
         | 
| 68 | 
            +
            				(?'int_or_float' (?:\g'digits')?+ (?:\. \g'digits')?+ (?<=\d) (?:e [+-]?+ \g'digits')?+)
         | 
| 69 | 
            +
            				(?'rational'     \g'int_or_float' (?:/ \g'digits')?+)
         | 
| 70 | 
            +
            			}xi
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            			match_data = regexp.match(str)
         | 
| 73 | 
            +
            			if strict && (!$'.empty? || match_data.captures[0,4].all?(&:nil?))
         | 
| 74 | 
            +
            				raise ArgumentError, "invalid value for convert(): #{str.inspect}"
         | 
| 75 | 
            +
            			end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            			w, x, y, z = match_data.captures[0,4].collect do |s|
         | 
| 78 | 
            +
            				case s
         | 
| 79 | 
            +
            				when %r{/}     then s.to_r
         | 
| 80 | 
            +
            				when %r{[.eE]} then s.to_f
         | 
| 81 | 
            +
            				when '+', ''   then 1
         | 
| 82 | 
            +
            				when '-'       then -1
         | 
| 83 | 
            +
            				else                s.to_i # Integer or nil
         | 
| 84 | 
            +
            				end
         | 
| 85 | 
            +
            			end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            			new(Complex.rect(w, x), Complex.rect(y, z))
         | 
| 88 | 
            +
            		end
         | 
| 89 | 
            +
            	end
         | 
| 90 | 
            +
            end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
            class Numeric
         | 
| 93 | 
            +
            	def to_q
         | 
| 94 | 
            +
            		Quaternion.send(:new, self, 0)
         | 
| 95 | 
            +
            	end
         | 
| 96 | 
            +
            end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            class String
         | 
| 99 | 
            +
            	def to_q
         | 
| 100 | 
            +
            		Quaternion.send(:parse, self, false)
         | 
| 101 | 
            +
            	end
         | 
| 102 | 
            +
            end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            class NilClass
         | 
| 105 | 
            +
            	def to_q
         | 
| 106 | 
            +
            		Quaternion.send(:new, 0, 0)
         | 
| 107 | 
            +
            	end
         | 
| 108 | 
            +
            end
         | 
| @@ -0,0 +1,43 @@ | |
| 1 | 
            +
            require_relative 'base'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            #
         | 
| 4 | 
            +
            # Unary operations
         | 
| 5 | 
            +
            #
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            class Quaternion
         | 
| 8 | 
            +
            	# defined by Numeric:
         | 
| 9 | 
            +
            	# * +@ #=> self
         | 
| 10 | 
            +
            	# * -@ #=> 0 - self
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            	def conj
         | 
| 13 | 
            +
            		__new__(@a.conj, -@b)
         | 
| 14 | 
            +
            	end
         | 
| 15 | 
            +
            	alias conjugate conj
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            	def abs2
         | 
| 18 | 
            +
            		@a.abs2 + @b.abs2
         | 
| 19 | 
            +
            	end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            	def abs
         | 
| 22 | 
            +
            		a_abs = @a.abs
         | 
| 23 | 
            +
            		b_abs = @b.abs
         | 
| 24 | 
            +
            		if    __exact_zero__(a_abs)
         | 
| 25 | 
            +
            			b_abs
         | 
| 26 | 
            +
            		elsif __exact_zero__(b_abs)
         | 
| 27 | 
            +
            			a_abs
         | 
| 28 | 
            +
            		else
         | 
| 29 | 
            +
            			Math.hypot(a_abs, b_abs)
         | 
| 30 | 
            +
            		end
         | 
| 31 | 
            +
            	end
         | 
| 32 | 
            +
            	alias magnitude abs
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            	private
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            	def __exact_zero__(x)
         | 
| 37 | 
            +
            		1 / x
         | 
| 38 | 
            +
            	rescue ZeroDivisionError
         | 
| 39 | 
            +
            		true
         | 
| 40 | 
            +
            	else
         | 
| 41 | 
            +
            		false
         | 
| 42 | 
            +
            	end
         | 
| 43 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            require_relative 'base'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            #
         | 
| 4 | 
            +
            # Fundamental quaternion units
         | 
| 5 | 
            +
            #
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            class Quaternion
         | 
| 8 | 
            +
            	i = Complex::I
         | 
| 9 | 
            +
            	I = new(i, 0)
         | 
| 10 | 
            +
            	J = new(0, 1)
         | 
| 11 | 
            +
            	K = new(0, i)
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            #
         | 
| 15 | 
            +
            # Convert to an imaginary part
         | 
| 16 | 
            +
            #
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            class Numeric
         | 
| 19 | 
            +
            	# defined:
         | 
| 20 | 
            +
            	# * #i #=> Complex.rect(0, self)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            	def j
         | 
| 23 | 
            +
            		Quaternion.send(:new, 0, self)
         | 
| 24 | 
            +
            	end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            	def k
         | 
| 27 | 
            +
            		Quaternion.send(:new, 0, self.i)
         | 
| 28 | 
            +
            	end
         | 
| 29 | 
            +
            end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            class Complex
         | 
| 32 | 
            +
            	# undefined:
         | 
| 33 | 
            +
            	# * #i
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            	undef k
         | 
| 36 | 
            +
            end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            class Quaternion
         | 
| 39 | 
            +
            	undef i, j, k
         | 
| 40 | 
            +
            end
         | 
| @@ -0,0 +1,71 @@ | |
| 1 | 
            +
            require_relative 'base'
         | 
| 2 | 
            +
            require_relative 'classification'
         | 
| 3 | 
            +
            require_relative 'unary'
         | 
| 4 | 
            +
            require_relative 'arithmetic'
         | 
| 5 | 
            +
            require_relative 'conversion'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            class Quaternion
         | 
| 8 | 
            +
            	def **(index)
         | 
| 9 | 
            +
            		if index.kind_of?(Numeric)
         | 
| 10 | 
            +
            			if __exact_zero__(index)
         | 
| 11 | 
            +
            				return __new__(1, 0)
         | 
| 12 | 
            +
            			end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            			# complex -> real
         | 
| 15 | 
            +
            			begin
         | 
| 16 | 
            +
            				index.to_f
         | 
| 17 | 
            +
            			rescue
         | 
| 18 | 
            +
            			else
         | 
| 19 | 
            +
            				index = index.real
         | 
| 20 | 
            +
            			end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            			# rational -> integer
         | 
| 23 | 
            +
            			if index.kind_of?(Rational) && index.denominator == 1
         | 
| 24 | 
            +
            				index = index.numerator
         | 
| 25 | 
            +
            			end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            			if index.integer?
         | 
| 28 | 
            +
            				# binary method
         | 
| 29 | 
            +
            				x = (index >= 0) ? self : 1 / self
         | 
| 30 | 
            +
            				n = index.abs
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            				z = __new__(1, 0)
         | 
| 33 | 
            +
            				while true
         | 
| 34 | 
            +
            					n, i = n.divmod(2)
         | 
| 35 | 
            +
            					z *= x if i == 1
         | 
| 36 | 
            +
            					return z if n == 0
         | 
| 37 | 
            +
            					x *= x
         | 
| 38 | 
            +
            				end
         | 
| 39 | 
            +
            			elsif index.real?
         | 
| 40 | 
            +
            				r, theta, vector = polar
         | 
| 41 | 
            +
            				return Quaternion.polar(r ** index, theta * index, vector)
         | 
| 42 | 
            +
            			elsif index.complex? || index.kind_of?(Quaternion)
         | 
| 43 | 
            +
            				r, theta, vector = polar
         | 
| 44 | 
            +
            				q = Math.log(r) + Quaternion.hrect(0, *(theta * vector))
         | 
| 45 | 
            +
            				q *= index
         | 
| 46 | 
            +
            				return Quaternion.polar(Math.exp(q.real), 1, q.imag)
         | 
| 47 | 
            +
            			end
         | 
| 48 | 
            +
            		end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            		num1, num2 = other.coerce(self)
         | 
| 51 | 
            +
            		num1 ** num2
         | 
| 52 | 
            +
            	end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            	def denominator
         | 
| 55 | 
            +
            		ad = @a.denominator
         | 
| 56 | 
            +
            		bd = @b.denominator
         | 
| 57 | 
            +
            		ad.lcm(bd)
         | 
| 58 | 
            +
            	end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            	def numerator
         | 
| 61 | 
            +
            		an = @a.numerator
         | 
| 62 | 
            +
            		bn = @b.numerator
         | 
| 63 | 
            +
            		ad = @a.denominator
         | 
| 64 | 
            +
            		bd = @b.denominator
         | 
| 65 | 
            +
            		abd = ad.lcm(bd)
         | 
| 66 | 
            +
            		__new__(an * (abd / ad), bn * (abd / bd))
         | 
| 67 | 
            +
            	end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            	undef step
         | 
| 70 | 
            +
            	undef ceil, floor, round, truncate
         | 
| 71 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            lib = File.expand_path('../lib', __FILE__)
         | 
| 2 | 
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            Gem::Specification.new do |spec|
         | 
| 5 | 
            +
              spec.name          = "quaternion_c2"
         | 
| 6 | 
            +
              spec.version       = "0.1.1"
         | 
| 7 | 
            +
              spec.authors       = ["Masahiro Nomoto"]
         | 
| 8 | 
            +
              spec.email         = ["hmmnrst@users.noreply.github.com"]
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              spec.summary       = %q{Quaternion class}
         | 
| 11 | 
            +
              spec.description   = %q{This provides a numeric class Quaternion which is similar to a built-in class Complex.}
         | 
| 12 | 
            +
              spec.homepage      = "https://github.com/hmmnrst/quaternion_c2"
         | 
| 13 | 
            +
              spec.license       = "MIT"
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              spec.files         = `git ls-files -z`.split("\x0").reject do |f|
         | 
| 16 | 
            +
                f.match(%r{^(test|spec|features)/})
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
              spec.bindir        = "exe"
         | 
| 19 | 
            +
              spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
         | 
| 20 | 
            +
              spec.require_paths = ["lib"]
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              spec.add_development_dependency "bundler", "~> 1.14"
         | 
| 23 | 
            +
              spec.add_development_dependency "rake", "~> 10.0"
         | 
| 24 | 
            +
              spec.add_development_dependency "rspec", "~> 3.0"
         | 
| 25 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,108 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: quaternion_c2
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.1.1
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Masahiro Nomoto
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: exe
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2017-03-31 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: bundler
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - ~>
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '1.14'
         | 
| 20 | 
            +
              type: :development
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - ~>
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '1.14'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: rake
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - ~>
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '10.0'
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - ~>
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '10.0'
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: rspec
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - ~>
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: '3.0'
         | 
| 48 | 
            +
              type: :development
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - ~>
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: '3.0'
         | 
| 55 | 
            +
            description: This provides a numeric class Quaternion which is similar to a built-in
         | 
| 56 | 
            +
              class Complex.
         | 
| 57 | 
            +
            email:
         | 
| 58 | 
            +
            - hmmnrst@users.noreply.github.com
         | 
| 59 | 
            +
            executables: []
         | 
| 60 | 
            +
            extensions: []
         | 
| 61 | 
            +
            extra_rdoc_files: []
         | 
| 62 | 
            +
            files:
         | 
| 63 | 
            +
            - .gitignore
         | 
| 64 | 
            +
            - .rspec
         | 
| 65 | 
            +
            - .travis.yml
         | 
| 66 | 
            +
            - Gemfile
         | 
| 67 | 
            +
            - LICENSE.txt
         | 
| 68 | 
            +
            - README.md
         | 
| 69 | 
            +
            - Rakefile
         | 
| 70 | 
            +
            - bin/console
         | 
| 71 | 
            +
            - bin/setup
         | 
| 72 | 
            +
            - lib/quaternion_c2.rb
         | 
| 73 | 
            +
            - lib/quaternion_c2/arithmetic.rb
         | 
| 74 | 
            +
            - lib/quaternion_c2/attributes.rb
         | 
| 75 | 
            +
            - lib/quaternion_c2/base.rb
         | 
| 76 | 
            +
            - lib/quaternion_c2/classification.rb
         | 
| 77 | 
            +
            - lib/quaternion_c2/conversion.rb
         | 
| 78 | 
            +
            - lib/quaternion_c2/equality.rb
         | 
| 79 | 
            +
            - lib/quaternion_c2/to_type.rb
         | 
| 80 | 
            +
            - lib/quaternion_c2/unary.rb
         | 
| 81 | 
            +
            - lib/quaternion_c2/units.rb
         | 
| 82 | 
            +
            - lib/quaternion_c2/utils.rb
         | 
| 83 | 
            +
            - quaternion_c2.gemspec
         | 
| 84 | 
            +
            homepage: https://github.com/hmmnrst/quaternion_c2
         | 
| 85 | 
            +
            licenses:
         | 
| 86 | 
            +
            - MIT
         | 
| 87 | 
            +
            metadata: {}
         | 
| 88 | 
            +
            post_install_message: 
         | 
| 89 | 
            +
            rdoc_options: []
         | 
| 90 | 
            +
            require_paths:
         | 
| 91 | 
            +
            - lib
         | 
| 92 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 93 | 
            +
              requirements:
         | 
| 94 | 
            +
              - - '>='
         | 
| 95 | 
            +
                - !ruby/object:Gem::Version
         | 
| 96 | 
            +
                  version: '0'
         | 
| 97 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 98 | 
            +
              requirements:
         | 
| 99 | 
            +
              - - '>='
         | 
| 100 | 
            +
                - !ruby/object:Gem::Version
         | 
| 101 | 
            +
                  version: '0'
         | 
| 102 | 
            +
            requirements: []
         | 
| 103 | 
            +
            rubyforge_project: 
         | 
| 104 | 
            +
            rubygems_version: 2.5.0
         | 
| 105 | 
            +
            signing_key: 
         | 
| 106 | 
            +
            specification_version: 4
         | 
| 107 | 
            +
            summary: Quaternion class
         | 
| 108 | 
            +
            test_files: []
         |