You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
docuseal/vendor/bundle/ruby/4.0.0/gems/bigdecimal-4.1.0/sample/linear.rb

111 lines
2.3 KiB

#
# linear.rb
#
# Solves linear equation system(A*x = b) by LU decomposition method.
# where A is a coefficient matrix,x is an answer vector,b is a constant vector.
#
# USAGE:
# ruby linear.rb [input file solved]
#
# :stopdoc:
require "bigdecimal"
# Requires gem matrix
require "matrix"
class PrecisionSpecifiedValue
# NOTE:
# Change following PREC if needed.
attr_reader :value
def initialize(value, prec)
@value = BigDecimal(value)
@prec = prec
end
def unwrap(value)
PrecisionSpecifiedValue === value ? value.value : value
end
def coerce(other)
[self.class.new(unwrap(other), @prec), self]
end
def abs
self.class.new(@value.abs, @prec)
end
def >(other)
@value > unwrap(other)
end
def <(other)
@value < unwrap(other)
end
def -(other)
self.class.new(@value.sub(unwrap(other), @prec), @prec)
end
def +(other)
self.class.new(@value.add(unwrap(other), @prec), @prec)
end
def *(other)
self.class.new(@value.mult(unwrap(other), @prec), @prec)
end
def quo(other)
self.class.new(@value.div(unwrap(other), @prec), @prec)
end
end
return if __FILE__ != $0
def rd_order(na)
printf("Number of equations ?") if(na <= 0)
ARGF.gets().to_i
end
na = ARGV.size
while (n=rd_order(na))>0
a = []
b = []
if na <= 0
# Read data from console.
printf("\nEnter coefficient matrix element A[i,j]\n")
for i in 0...n do
a << n.times.map do |j|
printf("A[%d,%d]? ",i,j); s = ARGF.gets
BigDecimal(s)
end
printf("Contatant vector element b[%d] ? ",i)
b << BigDecimal(ARGF.gets)
end
else
# Read data from specified file.
printf("Coefficient matrix and constant vector.\n")
for i in 0...n do
s = ARGF.gets
printf("%d) %s",i,s)
s = s.split
a << n.times.map {|j| BigDecimal(s[j]) }
b << BigDecimal(s[n])
end
end
prec = 100
matrix = Matrix[*a.map {|row| row.map {|v| PrecisionSpecifiedValue.new(v, prec) } }]
vector = b.map {|v| PrecisionSpecifiedValue.new(v, prec) }
x = matrix.lup.solve(vector).map(&:value)
printf("Answer(x[i] & (A*x-b)[i]) follows\n")
for i in 0...n do
printf("x[%d]=%s ",i,x[i].to_s)
diff = a[i].zip(x).sum {|aij, xj| aij*xj }.sub(b[i], 10)
printf(" & %s\n", diff.to_s)
end
end