Module: MyMathGem::LinearAlgebra

Defined in:
lib/my_math_gem/linear_algebra.rb

Class Method Summary collapse

Class Method Details

.cross(v1, v2) ⇒ Object

Cross product dua vektor 3D

Raises:

  • (ArgumentError)


29
30
31
32
33
34
35
36
# File 'lib/my_math_gem/linear_algebra.rb', line 29

def self.cross(v1, v2)
  raise ArgumentError, "Cross product hanya untuk vektor 3 dimensi" unless v1.length == 3 && v2.length == 3
  [
    v1[1]*v2[2] - v1[2]*v2[1],
    v1[2]*v2[0] - v1[0]*v2[2],
    v1[0]*v2[1] - v1[1]*v2[0]
  ]
end

.determinant_2x2(m) ⇒ Object

Determinan matriks 2x2

Raises:

  • (ArgumentError)


71
72
73
74
# File 'lib/my_math_gem/linear_algebra.rb', line 71

def self.determinant_2x2(m)
  raise ArgumentError, "Matriks harus 2x2" unless m.length == 2 && m.all? { |row| row.length == 2 }
  m[0][0]*m[1][1] - m[0][1]*m[1][0]
end

.determinant_3x3(m) ⇒ Object

Determinan matriks 3x3

Raises:

  • (ArgumentError)


77
78
79
80
81
82
83
# File 'lib/my_math_gem/linear_algebra.rb', line 77

def self.determinant_3x3(m)
  raise ArgumentError, "Matriks harus 3x3" unless m.length == 3 && m.all? { |row| row.length == 3 }
  a, b, c = m[0]
  d, e, f = m[1]
  g, h, i = m[2]
  a*(e*i - f*h) - b*(d*i - f*g) + c*(d*h - e*g)
end

.dot(v1, v2) ⇒ Object

Dot product dua vektor (array angka)

Raises:

  • (ArgumentError)


11
12
13
14
# File 'lib/my_math_gem/linear_algebra.rb', line 11

def self.dot(v1, v2)
  raise ArgumentError, "Vektor harus sama panjang" unless v1.length == v2.length
  v1.zip(v2).map { |a, b| a * b }.sum
end

.inverse_2x2(m) ⇒ Object

Invers matriks 2x2

Raises:

  • (ArgumentError)


86
87
88
89
90
91
92
93
94
# File 'lib/my_math_gem/linear_algebra.rb', line 86

def self.inverse_2x2(m)
  det = determinant_2x2(m)
  raise ArgumentError, "Matriks singular, determinan = 0" if det == 0
  inv_det = 1.0 / det
  [
    [ m[1][1]*inv_det, -m[0][1]*inv_det ],
    [ -m[1][0]*inv_det, m[0][0]*inv_det ]
  ]
end

.inverse_3x3(m) ⇒ Object

Invers matriks 3x3 (menggunakan metode kofaktor)

Raises:

  • (ArgumentError)


97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/my_math_gem/linear_algebra.rb', line 97

def self.inverse_3x3(m)
  det = determinant_3x3(m)
  raise ArgumentError, "Matriks singular, determinan = 0" if det == 0
  inv_det = 1.0 / det

  cofactors = Array.new(3) { Array.new(3, 0) }

  # Hitung kofaktor untuk tiap elemen
  (0..2).each do |row|
    (0..2).each do |col|
      minor = minor_2x2(m, row, col)
      cofactors[row][col] = ((row + col).even? ? 1 : -1) * determinant_2x2(minor)
    end
  end

  # Transpose kofaktor untuk dapat adjoin matrix
  adjugate = transpose(cofactors)

  # Kalikan dengan 1/det
  adjugate.map { |row| row.map { |val| val * inv_det } }
end

.matrix_multiply(m1, m2) ⇒ Object

Perkalian matriks (mxn) dengan matriks (nxp) atau vektor (n)



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/my_math_gem/linear_algebra.rb', line 39

def self.matrix_multiply(m1, m2)
  # Jika m2 adalah vektor
  if m2.is_a?(Array) && !m2.empty? && !m2[0].is_a?(Array)
    raise ArgumentError, "Jumlah kolom m1 harus sama dengan panjang vektor m2" unless m1[0].length == m2.length

    m1.map do |row|
      dot(row, m2)
    end
  else
    raise ArgumentError, "Jumlah kolom m1 harus sama dengan jumlah baris m2" unless m1[0].length == m2.length

    result = Array.new(m1.length) { Array.new(m2[0].length, 0) }
    m1.length.times do |i|
      m2[0].length.times do |j|
        sum = 0
        m2.length.times do |k|
          sum += m1[i][k] * m2[k][j]
        end
        result[i][j] = sum
      end
    end
    result
  end
end

.minor_2x2(m, row_to_remove, col_to_remove) ⇒ Object

Helper: matriks minor 2x2 dengan menghilangkan baris row_to_remove dan kolom col_to_remove



120
121
122
123
124
# File 'lib/my_math_gem/linear_algebra.rb', line 120

def self.minor_2x2(m, row_to_remove, col_to_remove)
  m.each_with_index
   .reject { |_, r| r == row_to_remove }
   .map { |row, _| row.each_with_index.reject { |_, c| c == col_to_remove }.map(&:first) }
end

.norm(v) ⇒ Object

Norm (magnitude) vektor



17
18
19
# File 'lib/my_math_gem/linear_algebra.rb', line 17

def self.norm(v)
  Math.sqrt(v.map { |x| x**2 }.sum)
end

.normalize(v) ⇒ Object

Normalisasi vektor (unit vector)

Raises:

  • (ArgumentError)


22
23
24
25
26
# File 'lib/my_math_gem/linear_algebra.rb', line 22

def self.normalize(v)
  n = norm(v)
  raise ArgumentError, "Vektor nol tidak dapat dinormalisasi" if n == 0
  v.map { |x| x.to_f / n }
end

.square_matrix?(m) ⇒ Boolean

Validasi matriks (array of arrays) persegi

Returns:

  • (Boolean)


4
5
6
7
8
# File 'lib/my_math_gem/linear_algebra.rb', line 4

def self.square_matrix?(m)
  return false unless m.is_a?(Array) && !m.empty?
  n = m.length
  m.all? { |row| row.is_a?(Array) && row.length == n }
end

.transpose(m) ⇒ Object

Transpose matriks

Raises:

  • (ArgumentError)


65
66
67
68
# File 'lib/my_math_gem/linear_algebra.rb', line 65

def self.transpose(m)
  raise ArgumentError, "Input harus matriks (array of arrays)" unless m.is_a?(Array) && m.all? { |row| row.is_a?(Array) }
  m[0].length.times.map { |i| m.map { |row| row[i] } }
end