サブ eigen.js   Last modified: Mar 25, 2004
// 固有値(e),固有ベクトル(v)を求める関数 eigen.js

function eigen(a, n, ne, eps, e, v)
{
  var sw, i, j, k, k1, m, nea, nm1, nm2, nv
  var nva, a1, ajk, d, ei, eps1 = 1e-8, eps2 = 1e-8, f, q
  var r, s, sr, t, wj1, w, lw
  var pass1 = 0, pass2 = 0
  lw = new Array(n)
  w = new Array(6)
  for (i = 0; i < 6; i++) {
    w[i] = new Array(n)
  }
  nv = nva = nea = Math.abs(ne)
  if (nea == 0 || nea > n) return 1
  nm1 = n-1; nm2 = n-2
  if (eps <= 0) {
    eps = 1e-16
  }
  if (n == 1) {
    e[0] = a[0][0]
    if (nv != 0) {
      v[0][0] = 1
    }
    return 0
  }
  if (n == 2) {
    w[0][0] = a[0][1]; t = 0.5*(a[0][0]+a[1][1])
    r = a[0][0]*a[1][1]-a[0][1]*a[0][1]
    d = t*t-r
    q = Math.abs(t)+Math.sqrt(d)
    if (t < 0) {
      q = -q
    }
    t *= ne
    if (t >= 0) {
      e[0] = q
      if (nea == 2) {
        e[1] = r/q
      }
    }
    else {
      e[0] = r/q
      if (nea == 2) {
        e[1] = q
      }
    }
  }
  else {
    for (k = 1; k <= nm2; k++) {
      k1 = k-1
      s = 0
      for (i = k; i < n; i++) {
        s += a[k1][i]*a[k1][i]
      }
      w[0][k1] = 0
      if (s != 0) {
        sr = Math.sqrt(s)
        a1 = a[k1][k]
        if (a1 < 0) {
          sr = -sr
        }
        w[0][k1] = -sr
        r = 1/(s+a1*sr)
        a[k1][k] = a1+sr
        for (i = k; i < n; i++) {
          s = 0
          for (j = k; j <= i; j++) {
            s += a[j][i]*a[k1][j]
          }
          if (i != nm1) {
            for (j = i+1; j < n; j++) {
              s += a[i][j]*a[k1][j]
            }
          }
          w[0][i] = s*r
        }
        s = 0
        for (i = k; i < n; i++) {
          s += a[k1][i]*w[0][i]
        }
        t = 0.5*s*r
        for (i = k; i < n; i++) {
          w[0][i] -= t*a[k1][i]
        }
        for (j = k; j < n; j++) {
          wj1 = w[0][j]
          ajk = a[k1][j]
          for (i = j; i < n; i++) {
            a[j][i] -= a[k1][i]*wj1+w[0][i]*ajk
          }
        }
      }
    }
    w[0][nm2] = a[nm2][nm1]
    for (i = 0; i < n; i++) {
      w[5][i] = a[i][i]
    }
    r = Math.abs(w[5][0])+Math.abs(w[0][0])
    f = Math.abs(w[0][nm2])+Math.abs(w[5][nm1])
    r = Math.max(r, f)
    for (i = 1; i < nm1; i++) {
      f = Math.abs(w[0][i-1])+Math.abs(w[5][i])+Math.abs(w[0][i])
      r = Math.max(r, f)
    }
    eps1 = r*1e-16
    eps2 = r*eps
    for (i = 0; i < nm1; i++) {
      w[1][i] = w[0][i]*w[0][i]
    }
    if (ne < 0) {
      r = -r
    }
    f = r
    for (i = 0; i < nea; i++) {
      e[i] = -r
    }
    pass2 = 0
    for (k = 1; k <= nea; k++) {
      if (!pass2) {
        k1 = k-1
        d = e[k1]
      }
      pass2 = 0
      t = 0.5*(d+f)
      if (Math.abs(d-f) > eps2 && t != d && t != f) {
        j = 0
        i = 1
        for (;;) {
          if (!pass1) {
            q = w[5][i-1]-t
          }
          pass1 = 0
          if (q >= 0) {
            j++
          }
          if (q != 0) {
            if (++i > n) {
              break
            }
            q = w[5][i-1]-t-w[1][i-2]/q
            pass1 = 1
            continue
          }
          else {
            i += 2
          }
          if (i > n) {
            break
          }
        }
        if (ne < 0) {
          j = n-j
        }
        if (j < k) {
          f = t
          pass2 = 1
          k--
          continue
        }
        d = t
        m = Math.min(j, nea)
        for (i = k-1; i < m; i++) {
          e[i] = t
        }
        pass2 = 1
        k--
        continue
      }
      e[k1] = t
    }
  }
  if (nv != 0) {
    if (n == 2) {
      w[5][0] = a[0][0]
      w[5][1] = a[1][1]
    }
    w[0][nm1] = 0
    for (i = 0; i < nva; i++) {
      ei = e[i]
      for (j = 0; j < n; j++) {
        w[1][j] = w[5][j]-ei
        w[2][j] = w[0][j]
        v[i][j] = 1
      }
      sw = 0
      for (j = 0; j < nm1; j++) {
        if (Math.abs(w[1][j]) >= Math.abs(w[0][j])) {
          if (w[1][j] == 0) {
            w[1][j] = 1e-30
          }
          w[4][j] = w[0][j]/w[1][j]
          lw[j] = 0
          w[1][j+1] -= w[4][j]*w[2][j]
          w[3][j] = 0
        }
        else {
          w[4][j] = w[1][j]/w[0][j]
          lw[j] = 1
          w[1][j] = w[0][j]
          t = w[2][j]
          w[2][j] = w[1][j+1]
          w[3][j] = w[2][j+1]
          w[1][j+1] = t-w[4][j]*w[2][j]
          w[2][j+1] = -w[4][j]*w[3][j]
        }
      }
      if (w[1][nm1] == 0) {
        w[1][nm1] = 1e-30
      }
      if (i > 0 && Math.abs(e[i]-e[i-1]) < eps1) {
        for (j = 0; j < n; j++) {
          v[i][j] = Math.random()
        }
      }
      for (;;) {
        t = v[i][nm1]
        r = v[i][nm2]
        v[i][nm1] = t/w[1][nm1]
        v[i][nm2] = (r-w[2][nm2]*v[i][nm1])/w[1][nm2]
        for (k = nm2-1; k >= 0; k--) {
          v[i][k] = (v[i][k]-w[2][k]*v[i][k+1]-w[3][k]*v[i][k+2])/w[1][k]
        }
        if (sw == 0) {
          sw = 1
          for (j = 0; j < nm1; j++) {
            if (lw[j] == 1) {
              t = v[i][j]
              v[i][j] = v[i][j+1]
              v[i][j+1] = t-w[4][j]*v[i][j+1]
            }
            else {
              v[i][j+1] -= w[4][j]*v[i][j]
            }
          }
          continue
        }
        else
        break
      }
    }
    if (n > 2) {
      for (i = 0; i < nm2; i++) {
        w[0][i] *= -a[i][i+1]
      }
      for (i = 0; i < nva; i++) {
        for (k = nm2-1; k >= 0; k--) {
          r = w[0][k]
          if (r != 0) {
            r = 1/r
            s = 0
            for (j = k+1; j < n; j++) {
              s += a[k][j]*v[i][j]
            }
            r *= s
            for (j = k+1; j < n; j++) {
              v[i][j] -= r*a[k][j]
            }
          }
        }
      }
    }
    for (i = 0; i < nva; i++) {
      if (i == 0) {
        m = 1
      }
      else {
        if (Math.abs(e[i]-e[i-1]) >= eps1) {
          m = i+1
        }
        else {
          for (j = m-1; j < i; j++) {
            s = 0
            for (k = 0; k < n; k++) {
              s += v[j][k]*v[i][k]
            }
            for (k = 0; k < n; k++) {
              v[i][k] -= s*v[j][k]
            }
          }
        }
      }
      t = s = 0
      for (j = 0; j < n; j++) {
        s += v[i][j]*v[i][j]
      }
      if (s != 0) {
        t = Math.sqrt(1/s)
      }
      for (j = 0; j < n; j++) {
        v[i][j] *= t
      }
    }
  }
  return 0
}


・ 直前のページへ戻る  ・ E-mail to Shigenobu AOKI

Made with Macintosh