Class: SyMath::Type

Inherits:
Object
  • Object
show all
Defined in:
lib/symath/type.rb

Constant Summary collapse

@@hierarchy =

Type hierarchy with generic types at the top level and more specific types further down.

{
  # Non numbers
  :nonfinite => 1,
  # Operators
  :operator => {
    # Linear operators
    :linop => {
      # Matrices
      :matrix => {
        :column => 1,
        :row => 1,
      },
      # Vector types (one dimension param)
      :tensor => {
        :nvector => {
          :vector => 1,
        },
        :nform => {
          :covector => {
            :dform => 1,
          },
        },
      },
      # Scalar types
      :quaternion => {
        :scalar => {
          :complex => {
            :real => {
              :rational => {
                :integer => {
                  :natural => 1
                }
              }
            },
            :imaginary => 1,
          }
        }
      }
    }
  }
}
@@subtype =

Create a transitively closed subtype hash for quicker subtype lookup

{}
@@types =

Hash of simple types, for faster instansiations.

{
  :natural    => SyMath::Type.new(:natural),
  :integer    => SyMath::Type.new(:integer),
  :rational   => SyMath::Type.new(:rational),
  :real       => SyMath::Type.new(:real),
  :complex    => SyMath::Type.new(:complex),
  :imaginary  => SyMath::Type.new(:imaginary),
  :quaternion => SyMath::Type.new(:quaternion),
  :vector     => SyMath::Type.new(:vector, indexes: ['u']),
  :covector   => SyMath::Type.new(:covector, indexes: ['l']),
  :dform      => SyMath::Type.new(:dform, indexes: ['l']),
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, dimn: nil, dimm: nil, indexes: nil) ⇒ Type

Returns a new instance of Type.



80
81
82
83
84
85
# File 'lib/symath/type.rb', line 80

def initialize(name, dimn: nil, dimm: nil, indexes: nil)
  @name = name.to_sym
  @dimn = dimn
  @dimm = dimm
  @indexes = indexes
end

Instance Attribute Details

#dimmObject (readonly)

Matrix dimensions



6
7
8
# File 'lib/symath/type.rb', line 6

def dimm
  @dimm
end

#dimnObject (readonly)

Matrix dimensions



6
7
8
# File 'lib/symath/type.rb', line 6

def dimn
  @dimn
end

#indexesObject (readonly)

Tensor indexes (array of ‘h’ amd ‘l’)



8
9
10
# File 'lib/symath/type.rb', line 8

def indexes
  @indexes
end

#nameObject (readonly)

Type name



4
5
6
# File 'lib/symath/type.rb', line 4

def name
  @name
end

Class Method Details

.fill_subtype_hash(hiera, bases = []) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/symath/type.rb', line 57

def self.fill_subtype_hash(hiera, bases = [])
  hiera.keys.each do |k|
    bases.each do |b|
      if !@@subtype.key?(k)
        @@subtype[k] = {}
      end
      @@subtype[k][b] = 1
    end
    
    next unless hiera[k].is_a?(Hash)

    fill_subtype_hash(hiera[k], bases + [k])
  end
end

.typesObject



76
77
78
# File 'lib/symath/type.rb', line 76

def self.types
  return @@types
end

Instance Method Details

#==(other) ⇒ Object



241
242
243
244
245
246
# File 'lib/symath/type.rb', line 241

def ==(other)
  return false if @dim1 != other.dimn
  return false if @dim2 != other.dimm
  return false if @indexes != other.indexes
  return @name == other.name
end

#common_parent(other) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/symath/type.rb', line 122

def common_parent(other)
  if other.is_subtype?(self)
    return self
  elsif is_subtype?(other)
    return other
  elsif is_subtype?(@@types[:complex]) and
       other.is_subtype?(@@types[:complex])
    return  @@types[:complex]
  else
    raise "No common type for #{self} and #{other}"
  end
end

#degreeObject

Return tensor degree (rank)



171
172
173
# File 'lib/symath/type.rb', line 171

def degree()
  return @indexes.length
end

#index_strObject

Return index list as a string coded with upper indices as ‘ and lower indices as .



231
232
233
234
235
236
237
238
239
# File 'lib/symath/type.rb', line 231

def index_str()
  return @indexes.map do |i|
    if i == 'u'
      '\''
    elsif i == 'l'
      '.'
    end
  end.join('')
end

#is_covector?Boolean

FIXME: What is the difference between a covector and a dform?

Returns:

  • (Boolean)


221
222
223
# File 'lib/symath/type.rb', line 221

def is_covector?()
  return is_subtype?('covector')
end

#is_dform?Boolean

Returns:

  • (Boolean)


225
226
227
# File 'lib/symath/type.rb', line 225

def is_dform?()
  return is_subtype?('dform')
end

#is_matrix?Boolean

Returns:

  • (Boolean)


189
190
191
# File 'lib/symath/type.rb', line 189

def is_matrix?()
  return ([:matrix, :colum, :row].include?(@name))
end

#is_nform?Boolean

True if type is the dual of an nvector

Returns:

  • (Boolean)


216
217
218
# File 'lib/symath/type.rb', line 216

def is_nform?()
  return is_subtype?('nform')
end

#is_nvector?Boolean

True if type is a linear combination of blades

Returns:

  • (Boolean)


185
186
187
# File 'lib/symath/type.rb', line 185

def is_nvector?()
  return is_subtype?('nvector')
end

#is_pseudoscalar?Boolean

True if type is a pseudoscalar. We use the notion of a pseudoscalar both for N dimensional nvectors and nforms (N being the dimensionality of the default vector space)

Returns:

  • (Boolean)


207
208
209
210
211
212
213
# File 'lib/symath/type.rb', line 207

def is_pseudoscalar?()
  if !is_subtype?('nvector') and !is_subtype?('nform')
    return false
  end

  return degree == SyMath.get_variable(:basis).ncols
end

#is_pseudovector?Boolean

True if type is a pseudovector. We use the notion of a pseudovector both for N-1 dimensional nvectors and nforms (N being the dimensionality of the default vector space)

Returns:

  • (Boolean)


196
197
198
199
200
201
202
# File 'lib/symath/type.rb', line 196

def is_pseudovector?()
  if !is_subtype?('nvector') and !is_subtype?('nform')
    return false
  end

  return degree == SyMath.get_variable(:basis).ncols - 1
end

#is_scalar?Boolean

True if type is a scalar value

Returns:

  • (Boolean)


176
177
178
# File 'lib/symath/type.rb', line 176

def is_scalar?()
  return is_subtype?('scalar')
end

#is_subtype?(other) ⇒ Boolean

Check if a type is a subtype of another

Returns:

  • (Boolean)


102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/symath/type.rb', line 102

def is_subtype?(other)
  # Allow input as type or as string
  other = other.to_t

  # Types are not compatible if they have different attributes.
  # FIXME: What is the correct way to define subtypes of matrices
  # with respect to dimensions?
  return false if @dim1 != other.dimn
  return false if @dim2 != other.dimm

  # Same types, 
  return true if @name == other.name

  # This is a subtype of other
  return true if @@subtype.key?(@name) and @@subtype[@name].key?(other.name)

  # Fallback to false
  return false
end

#is_vector?Boolean

Returns:

  • (Boolean)


180
181
182
# File 'lib/symath/type.rb', line 180

def is_vector?()
  return is_subtype?('vector')
end

#product(other) ⇒ Object

Determine the type of a product



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/symath/type.rb', line 151

def product(other)
  scalar = is_scalar?
  oscalar = other.is_scalar?
  
  if scalar and oscalar
    return common_parent(other)
  elsif scalar
    return other
  elsif oscalar
    return self
  elsif is_subtype?('matrix') and
       other.is_subtype?('matrix') and
       dimn == other.dimm
    return 'matrix'.to_t(dimm: dimm, dimn: other.dimn)
  else
    raise "Types #{self} and #{other} cannot be multiplied"
  end
end

#sum(other) ⇒ Object

Determine the type of a sum



136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/symath/type.rb', line 136

def sum(other)
  if is_subtype?('quaternion') and
    other.is_subtype?('quaternion')
    return common_parent(other)
  elsif self == other
    return self
  elsif self.is_subtype?('tensor') or other.is_subtype?('tensor')
    # FIXME: Hack. This is probably not true. 
    return self
  else
    raise "Types #{self} and #{other} cannot be summed."
  end
end

#to_sObject



248
249
250
251
252
253
254
255
256
# File 'lib/symath/type.rb', line 248

def to_s()
  if !@dimn.nil?
    return @name.to_s + '[' + @dimm.to_s + 'x' + @dimn.to_s + ']'
  elsif !@indexes.nil?
    return @name.to_s + '[' + @indexes.join('') + ']'
  else
    return @name.to_s
  end
end

#to_t(*args) ⇒ Object



258
259
260
# File 'lib/symath/type.rb', line 258

def to_t(*args)
  return self
end