# Algebraic System Library
#
# by Shin-ichiro Hara
#
# Version 1.1 (2001.04.20)
require "algebra/numeric-supplement"
require "algebra/auto-require"
module Algebra
module AlgebraCreator
def create(ground)
klass = Class.new(self)
klass.sysvar :ground, ground
def klass.inspect
to_s
end
def klass.to_s
s = super
s = "(#{superclass.inspect}/#{ground.inspect})" if s =~ /^#/ #/
s.gsub(/Algebra::/ , '')
end
klass
end
# Needed in the type conversion of MatrixAlgebra
def wedge(otype) # =:= tensor
if superior?(otype)
self
elsif otype.respond_to?(:superior?) && otype.superior?(self)
otype
else
raise "wedge: unknown pair (#{self}) .wedge (#{otype})"
end
end
def superior?(otype)
if otype <= Numeric || self <= otype
true
elsif self.respond_to?(:ground) && self.ground.respond_to?(:superior?)
self.ground.superior?(otype)
else
false
end
end
def sysvar(var_name, value = nil, sw = false)
var_name = var_name.id2name if var_name.is_a?(Symbol)
class_eval <<__END_OF_CLASS_DEFINITION__
@@#{var_name} = nil
def self.#{var_name}; @@#{var_name}; end
def self.#{var_name}=(value); @@#{var_name} = value; end
__END_OF_CLASS_DEFINITION__
send(var_name + "=", value) if value
if sw
class_eval <<__END_OF_CLASS_DEFINITION__
def #{var_name}; @@#{var_name}; end
def #{var_name}=(value); @@#{var_name} = value; end
__END_OF_CLASS_DEFINITION__
end
end
end
module AlgebraBase
def zero; self.class.zero; end
def unity; self.class.unity; end
def zero?; zero == self; end
def unit?; unity == self or -unity == self; end
def unity?; unity == self; end
def ground; self.class.ground; end
def ground=(bf); self.class.ground = bf; end
def devide?(other)
if self.class.field?
true
elsif self.class.euclidian?
q, r = other.divmod(self)
r.zero?
else
raise "don't konw #{self} divides #{other}"
end
end
def regulate(x)
self.class.regulate(x)
end
# private :regulate
def self.append_features(klass)
def klass.field?
!method_defined?(:divmod) # may be overwrited
end
def klass.euclidian?
method_defined?(:divmod) # may be overwrited
end
def klass.ufd?
euclidian? # may be overwrited
end
def klass.zero; new(ground.zero); end
def klass.unity; new(ground.unity); end
def klass.regulate(x)
if x.is_a? self
x
elsif y = ground.regulate(x)
new(y)
else
nil
end
end
super
end
# Operations
def +@
self
end
def -@
zero - self
end
def ==(other)
if o = regulate(other)
yield o
else
x , y = other.coerce(self)
x == y
end
end
def +(other)
if o = regulate(other)
yield o
else
x , y = other.coerce(self)
x + y
end
end
def -(other)
if o = regulate(other)
yield o
else
x , y = other.coerce(self)
x - y
end
end
def *(other)
if o = regulate(other)
yield o
else
x , y = other.coerce(self)
x * y
end
end
def /(other)
if o = regulate(other)
yield o
else
x , y = other.coerce(self)
x / y
end
end
def **(n)
if ! n.is_a? Integer or n < 0
raise "index must be non negative integer"
elsif n == 0
return unity
elsif n == 1
self
else
q , r = n.divmod 2
x = self ** q
x = x * x
x = x * self if r > 0
x
end
end
alias ^ **
def coerce(other)
if x = regulate(other)
[x, self]
else
raise "(ALG.SYS) can't coerce: (#{self.class}).coerce(#{other.class}) : (#{self}).coerce(#{other})"
end
end
end
end
syntax highlighted by Code2HTML, v. 0.9.1