public function __construct(Matrix $_matrix)
 {
     $this->l_matrix = $_matrix;
     $m = $_matrix->u_size;
     $n = $_matrix->u_stride;
     /*if($m < $n)
     		{
     			return;
     		}*/
     $a = clone $this->l_matrix->u_data;
     /*$nu = min($m, $n);*/
     $this->l_singular = new Vector($sl = min($m + 1, $n));
     $s = $this->l_singular->u_data;
     $this->l_left = new Matrix($um = $m, $un = $m);
     $u = $this->l_left->u_data;
     $this->l_right = new Matrix($vm = $n, $vn = $n);
     $v = $this->l_right->u_data;
     $e = arrayFill($n, 0.0);
     $work = arrayFill($m, 0.0);
     $wantu = true;
     $wantv = true;
     /* Reduce A to bidiagonal form, storing the diagonal elements in s and the super-diagonal elements in e. */
     $nct = min($m - 1, $n);
     $nrt = max(0, min($n - 2, $m));
     $kmax = max($nct, $nrt);
     for ($k = 0; $k < $kmax; $k++) {
         if ($k < $nct) {
             /*
             	Compute the transformation for the k-th column and place the k-th diagonal in s[k].
             	Compute 2-norm of k-th column without under/overflow.
             */
             $s[$k] = 0.0;
             for ($i = $k; $i < $m; $i++) {
                 $s[$k] = hypot($s[$k], $a[$i * $n + $k]);
             }
             if (compare($s[$k], 0)) {
                 if ($a[$pos = $k * $n + $k] < 0) {
                     $s[$k] = -$s[$k];
                 }
                 for ($i = $k; $i < $m; $i++) {
                     $a[$i * $n + $k] /= (double) $s[$k];
                     /* Division */
                 }
                 $a[$pos] += 1.0;
             }
             $s[$k] = -$s[$k];
         }
         for ($j = $k + 1; $j < $n; $j++) {
             if ($k < $nct && compare($s[$k], 0)) {
                 /* Apply the transformation. */
                 $t = 0.0;
                 for ($i = $k; $i < $m; $i++) {
                     $t += $a[$i * $n + $k] * $a[$i * $n + $j];
                 }
                 $t = -$t / (double) $a[$k * $n + $k];
                 /* Division */
                 for ($i = $k; $i < $m; $i++) {
                     $a[$i * $n + $j] += $t * $a[$i * $n + $k];
                 }
             }
             /* Place the k-th row of A into e for the subsequent calculation of the row transformation. */
             $e[$j] = $a[$k * $n + $j];
         }
         if ($wantu && $k < $nct) {
             /* Place the transformation in U for subsequent back multiplication. */
             for ($i = $k; $i < $m; $i++) {
                 $u[$i * $un + $k] = $a[$i * $n + $k];
             }
         }
         if ($k < $nrt) {
             /* Compute the k-th row transformation and place the k-th super-diagonal in e[k]. Compute 2-norm without under/overflow. */
             $e[$k] = 0.0;
             for ($i = $k + 1; $i < $n; $i++) {
                 $e[$k] = hypot($e[$k], $e[$i]);
             }
             if (compare($e[$k], 0)) {
                 if ($e[$k + 1] < 0) {
                     $e[$k] = -$e[$k];
                 }
                 for ($i = $k + 1; $i < $n; $i++) {
                     $e[$i] /= (double) $e[$k];
                     /* Division */
                 }
                 $e[$k + 1] += 1.0;
             }
             $e[$k] = -$e[$k];
             if ($k + 1 < $m && compare($e[$k], 0)) {
                 /* Apply the transformation. */
                 for ($i = $k + 1; $i < $m; $i++) {
                     $work[$i] = 0.0;
                 }
                 for ($j = $k + 1; $j < $n; $j++) {
                     for ($i = $k + 1; $i < $m; $i++) {
                         $work[$i] += $e[$j] * $a[$i * $n + $j];
                     }
                 }
                 for ($j = $k + 1; $j < $n; $j++) {
                     $t = -$e[$j] / (double) $e[$k + 1];
                     /* Division */
                     for ($i = $k + 1; $i < $m; $i++) {
                         $a[$i * $n + $j] += $t * $work[$i];
                     }
                 }
             }
             if ($wantv) {
                 /* Place the transformation in V for subsequent back multiplication. */
                 for ($i = $k + 1; $i < $n; $i++) {
                     $v[$i * $vn + $k] = $e[$i];
                 }
             }
         }
     }
     /* Set up the final bidiagonal matrix or order p. */
     $p = min($n, $m + 1);
     if ($nct < $n) {
         $s[$nct] = $a[$nct * $n + $nct];
     }
     if ($m < $p) {
         $s[$p - 1] = 0.0;
     }
     if ($nrt + 1 < $p) {
         $e[$nrt] = $a[$nrt * $n + $p - 1];
     }
     $e[$p - 1] = 0.0;
     /* If required, generate U. */
     if ($wantu) {
         for ($j = $nct; $j < $m; $j++) {
             for ($i = 0; $i < $m; $i++) {
                 $u[$i * $un + $j] = 0.0;
             }
             $u[$j * $un + $j] = 1.0;
         }
         for ($k = $nct - 1; $k >= 0; $k--) {
             if (compare($s[$k], 0)) {
                 for ($j = $k + 1; $j < $m; $j++) {
                     $t = 0.0;
                     for ($i = $k; $i < $m; $i++) {
                         $t += $u[$i * $un + $k] * $u[$i * $un + $j];
                     }
                     $t = -$t / (double) $u[$k * $un + $k];
                     /* Division */
                     for ($i = $k; $i < $m; $i++) {
                         $u[$i * $un + $j] += $t * $u[$i * $un + $k];
                     }
                 }
                 for ($i = $k; $i < $m; $i++) {
                     $u[$pos = $i * $un + $k] = -$u[$pos];
                 }
                 $u[$pos = $k * $un + $k] = 1.0 + $u[$pos];
                 for ($i = 0; $i < $k - 1; $i++) {
                     $u[$i * $un + $k] = 0.0;
                 }
             } else {
                 for ($i = 0; $i < $m; $i++) {
                     $u[$i * $un + $k] = 0.0;
                 }
                 $u[$k * $un + $k] = 1.0;
             }
         }
     }
     /* If required, generate V. */
     if ($wantv) {
         for ($k = $n - 1; $k >= 0; $k--) {
             if ($k < $nrt && compare($e[$k], 0)) {
                 for ($j = $k + 1; $j < $n; $j++) {
                     $t = 0.0;
                     for ($i = $k + 1; $i < $n; $i++) {
                         $t += $v[$i * $vn + $k] * $v[$i * $vn + $j];
                     }
                     $t = -$t / (double) $v[($k + 1) * $vn + $k];
                     /* Division */
                     for ($i = $k + 1; $i < $n; $i++) {
                         $v[$i * $vn + $j] += $t * $v[$i * $vn + $k];
                     }
                 }
             }
             for ($i = 0; $i < $n; $i++) {
                 $v[$i * $vn + $k] = 0.0;
             }
             $v[$k * $vn + $k] = 1.0;
         }
     }
     /* Main iteration loop for the singular values. */
     $pp = $p - 1;
     $iter = 0;
     $eps = pow(2, -52);
     $tiny = pow(2, -966);
     while ($p > 0) {
         $k = $kase = null;
         /*
         	Here is where a test for too many iterations would go.
          
         	This section of the program inspects for negligible elements in the s and e arrays.
         	On completion the variables kase and k are set as follows.
         	kase = 1	if s(p) and e[k - 1] are negligible and k < p
         	kase = 2	if s(k) is negligible and k < p
         	kase = 3	if e[k - 1] is negligible, k < p, and s(k), ..., s(p) are not negligible (qr step).
         	kase = 4	if e(p - 1) is negligible (convergence).
         */
         for ($k = $p - 2; $k >= -1; $k--) {
             if ($k == -1) {
                 break;
             }
             if (compare(abs($e[$k]), $tiny + $eps * (abs($s[$k]) + abs($s[$k + 1]))) <= 0) {
                 $e[$k] = 0.0;
                 break;
             }
         }
         if ($k == $p - 2) {
             $kase = 4;
         } else {
             $ks = null;
             for ($ks = $p - 1; $ks >= $k; $ks--) {
                 if ($ks == $k) {
                     break;
                 }
                 $t = ($ks != $p ? abs($e[$ks]) : 0) + ($ks != $k + 1 ? abs($e[$ks - 1]) : 0);
                 if (compare(abs($s[$ks]), $tiny + $eps * $t) <= 0) {
                     $s[$ks] = 0.0;
                     break;
                 }
             }
             if ($ks == $k) {
                 $kase = 3;
             } else {
                 if ($ks == $p - 1) {
                     $kase = 1;
                 } else {
                     $kase = 2;
                     $k = $ks;
                 }
             }
         }
         $k++;
         /* Perform the task indicated by kase. */
         switch ($kase) {
             /* Deflate negligible s(p). */
             case 1:
                 $f = $e[$p - 2];
                 $e[$p - 2] = 0.0;
                 for ($j = $p - 2; $j >= $k; $j--) {
                     $t = (double) hypot($s[$j], $f);
                     $cs = $s[$j] / $t;
                     /* Division */
                     $sn = $f / $t;
                     /* Division */
                     $s[$j] = $t;
                     if ($j != $k) {
                         $f = -$sn * $e[$j - 1];
                         $e[$j - 1] = $cs * $e[$j - 1];
                     }
                     if ($wantv) {
                         for ($i = 0; $i < $n; $i++) {
                             $t = $cs * $v[$ijpos = $i * $vn + $j] + $sn * $v[$ippos = $i * $vn + $p - 1];
                             $v[$ippos] = -$sn * $v[$ijpos] + $cs * $v[$ippos];
                             $v[$ijpos] = $t;
                         }
                     }
                 }
                 break;
                 /* Split at negligible s(k). */
             /* Split at negligible s(k). */
             case 2:
                 $f = $e[$k - 1];
                 $e[$k - 1] = 0.0;
                 for ($j = $k; $j < $p; $j++) {
                     $t = (double) hypot($s[$j], $f);
                     $cs = $s[$j] / $t;
                     /* Division */
                     $sn = $f / $t;
                     /* Division */
                     $s[$j] = $t;
                     $f = -$sn * $e[$j];
                     $e[$j] = $cs * $e[$j];
                     if ($wantu) {
                         for ($i = 0; $i < $m; $i++) {
                             $t = $cs * $u[$ijpos = $i * $un + $j] + $sn * $u[$ikpos = $i * $un + $k - 1];
                             $u[$ikpos] = -$sn * $u[$ijpos] + $cs * $u[$ikpos];
                             $u[$ijpos] = $t;
                         }
                     }
                 }
                 break;
                 /* Perform one qr step. */
             /* Perform one qr step. */
             case 3:
                 /* Calculate the shift. */
                 $scale = (double) max(max(max(max(abs($s[$p - 1]), abs($s[$p - 2])), abs($e[$p - 2])), abs($s[$k])), abs($e[$k]));
                 $sp = $s[$p - 1] / $scale;
                 /* Division */
                 $spm1 = $s[$p - 2] / $scale;
                 /* Division */
                 $epm1 = $e[$p - 2] / $scale;
                 /* Division */
                 $sk = $s[$k] / $scale;
                 /* Division */
                 $ek = $e[$k] / $scale;
                 /* Division */
                 $b = (($spm1 + $sp) * ($spm1 - $sp) + $epm1 * $epm1) / 2.0;
                 $c = $sp * $epm1 * ($sp * $epm1);
                 $shift = 0.0;
                 if (compare($b, 0) || compare($c, 0)) {
                     $shift = sqrt($b * $b + $c);
                     if ($b < 0) {
                         $shift = -$shift;
                     }
                     $shift = $c / (double) ($b + $shift);
                     /* Division */
                 }
                 $f = ($sk + $sp) * ($sk - $sp) + $shift;
                 $g = $sk * $ek;
                 /* Chase zeros. */
                 for ($j = $k; $j < $p - 1; $j++) {
                     $t = (double) hypot($f, $g);
                     $cs = $f / $t;
                     /* Division */
                     $sn = $g / $t;
                     /* Division */
                     if ($j != $k) {
                         $e[$j - 1] = $t;
                     }
                     $f = $cs * $s[$j] + $sn * $e[$j];
                     $e[$j] = $cs * $e[$j] - $sn * $s[$j];
                     $g = $sn * $s[$j + 1];
                     $s[$j + 1] = $cs * $s[$j + 1];
                     if ($wantv) {
                         for ($i = 0; $i < $n; $i++) {
                             $t = $cs * $v[$ijpos = $i * $vn + $j] + $sn * $v[$ij1pos = $i * $vn + $j + 1];
                             $v[$ij1pos] = -$sn * $v[$ijpos] + $cs * $v[$ij1pos];
                             $v[$ijpos] = $t;
                         }
                     }
                     $t = (double) hypot($f, $g);
                     $cs = $f / $t;
                     /* Division */
                     $sn = $g / $t;
                     /* Division */
                     $s[$j] = $t;
                     $f = $cs * $e[$j] + $sn * $s[$j + 1];
                     $s[$j + 1] = -$sn * $e[$j] + $cs * $s[$j + 1];
                     $g = $sn * $e[$j + 1];
                     $e[$j + 1] = $cs * $e[$j + 1];
                     if ($wantu && $j < $m - 1) {
                         for ($i = 0; $i < $m; $i++) {
                             $t = $cs * $u[$ijpos = $i * $un + $j] + $sn * $u[$ij1pos = $i * $un + $j + 1];
                             $u[$ij1pos] = -$sn * $u[$ijpos] + $cs * $u[$ij1pos];
                             $u[$ijpos] = $t;
                         }
                     }
                 }
                 $e[$p - 2] = $f;
                 $iter = $iter + 1;
                 break;
                 /* Convergence. */
             /* Convergence. */
             case 4:
                 /* Make the singular values positive. */
                 if (compare($s[$k], 0) <= 0) {
                     $s[$k] = $s[$k] < 0 ? -$s[$k] : 0.0;
                     if ($wantv) {
                         for ($i = 0; $i <= $pp; $i++) {
                             $v[$pos = $i * $vn + $k] = -$v[$pos];
                         }
                     }
                 }
                 /* Order the singular values. */
                 while ($k < $pp) {
                     if (compare($s[$k], $s[$k + 1]) >= 0) {
                         break;
                     }
                     $t = $s[$k];
                     $s[$k] = $s[$k + 1];
                     $s[$k + 1] = $t;
                     if ($wantv && $k < $n - 1) {
                         for ($i = 0; $i < $n; $i++) {
                             $t = $v[$ik1pos = $i * $vn + $k + 1];
                             $v[$ik1pos] = $v[$ikpos = $i * $vn + $k];
                             $v[$ikpos] = $t;
                         }
                     }
                     if ($wantu && $k < $m - 1) {
                         for ($i = 0; $i < $m; $i++) {
                             $t = $u[$ik1pos = $i * $un + $k + 1];
                             $u[$ik1pos] = $u[$ikpos = $i * $un + $k];
                             $u[$ikpos] = $t;
                         }
                     }
                     $k++;
                 }
                 $iter = 0;
                 $p--;
                 break;
         }
     }
     if ($sl > $m) {
         $this->l_singular->u_stride = $m;
         $s->setSize($m);
     }
 }
Exemplo n.º 2
0
 public function __construct($_size, $_stride = 1, $_offset = 0, $_access = ACCESS_ROWS, \SplFixedArray $_data = null)
 {
     $this->l_position = 0;
     switch ($_access) {
         case ACCESS_ROWS:
             $this->l_count =& $this->u_size;
             break;
         case ACCESS_COLUMNS:
             $this->l_count =& $this->u_stride;
             break;
         default:
             $this->l_count = 0;
     }
     $this->u_size = max(0, (int) $_size);
     $this->u_stride = max(0, (int) $_stride);
     $this->u_offset = max(0, (int) $_offset);
     $this->u_data = $_data === null ? arrayFill($this->u_size * $this->u_stride, 0.0) : $_data;
 }
Exemplo n.º 3
0
 public function spearmanCorrelationColumns()
 {
     $result = new Matrix($this->u_stride, $this->u_stride);
     $combinations1 = $combinations2 = 0;
     $ranks1 = arrayFill($this->u_size, 0.0);
     $ranks2 = arrayFill($this->u_size, 0.0);
     for ($i = 0; $i < $result->u_size; $i++) {
         $offset = $i * $result->u_stride;
         $this->u_spearmanRanks($this->u_data, $this->u_size, $this->u_stride, $i, $ranks1, $combinations1);
         for ($j = $i; $j < $result->u_stride; $j++) {
             if ($i == $j) {
                 $result->u_data[$offset + $j] = $result->u_data[$j * $result->u_stride + $i] = 1;
             } else {
                 $this->u_spearmanRanks($this->u_data, $this->u_size, $this->u_stride, $j, $ranks2, $combinations2);
                 $result->u_data[$offset + $j] = $result->u_data[$j * $result->u_stride + $i] = $this->u_spearmanCorrelation($ranks1, $combinations1, $ranks2, $combinations2, $this->u_size);
             }
         }
     }
     return $result;
 }
Exemplo n.º 4
0
 public function spearmanCorrelation(AbstractVector $_vector)
 {
     if ($_vector->u_stride !== $this->u_stride) {
         return null;
     }
     $combinations1 = $combinations2 = 0;
     $ranks1 = arrayFill($this->u_stride, 0.0);
     $ranks2 = arrayFill($this->u_stride, 0.0);
     $this->u_spearmanRanks($this->u_data, $this->u_stride, 1, $this->u_offset, $ranks1, $combinations1);
     $this->u_spearmanRanks($_vector->u_data, $_vector->u_stride, 1, $_vector->u_offset, $ranks2, $combinations2);
     return $this->u_spearmanCorrelation($ranks1, $combinations1, $ranks2, $combinations2, $this->u_stride);
 }