# svdappend

Revise SVD after appending data

Since R2023b

## Syntax

``[U1,S1,V1] = svdappend(U,S,V,D)``
``[U1,S1,V1] = svdappend(U,S,V,D,Name=Value)``

## Description

example

````[U1,S1,V1] = svdappend(U,S,V,D)`, where `A = U*S*V'` is an existing singular value decomposition (SVD), calculates the SVD of `[A D]` without explicitly forming `A` or `[A D]`. The results are equivalent, up to round-off error, to `[U1,S1,V1] = svd([A D],"econ","vector")`.```

example

````[U1,S1,V1] = svdappend(U,S,V,D,Name=Value)` additionally specifies options using one or more name-value arguments. For example, `svdappend(U,S,V,D,Shape="rows")` specifies that `D` contains new rows to append, and the revised SVD is for `[A; D]`.```

## Examples

collapse all

Calculate the SVD of a 5-by-5 random matrix, and then calculate the revised SVD with three additional columns.

Create a 5-by-5 random matrix and calculate the SVD.

```A = rand(5); [U,S,V] = svd(A)```
```U = 5×5 -0.2475 -0.5600 0.4131 0.5759 0.3504 -0.3542 -0.5207 -0.7577 -0.0111 -0.1707 -0.4641 0.6013 -0.1679 0.6063 -0.1652 -0.5475 -0.1183 0.4755 -0.3314 -0.5919 -0.5460 0.1992 -0.0298 -0.4369 0.6859 ```
```S = 5×5 3.3129 0 0 0 0 0 0.9431 0 0 0 0 0 0.8358 0 0 0 0 0 0.4837 0 0 0 0 0 0.0198 ```
```V = 5×5 -0.4307 -0.8839 0.0530 -0.0884 0.1503 -0.4309 0.2207 0.1961 -0.7322 -0.4370 -0.4617 0.0890 -0.7467 0.3098 -0.3539 -0.4730 0.3701 -0.0798 -0.1023 0.7890 -0.4380 0.1585 0.6283 0.5913 -0.1968 ```

Create a 5-by-3 matrix containing three new columns of data, and then calculate the revised SVD.

```D = rand(5,3); [U1,S1,V1] = svdappend(U,S,V,D)```
```U1 = 5×5 0.3616 0.6757 -0.4056 0.3016 0.3966 0.4066 0.2922 0.8635 0.0546 -0.0270 0.4272 -0.3990 -0.1227 0.7092 -0.3745 0.5707 0.0815 -0.2734 -0.6000 -0.4826 0.4424 -0.5406 0.0091 -0.2075 0.6848 ```
```S1 = 5×1 3.7334 1.3862 0.8863 0.6852 0.4189 ```
```V1 = 8×5 0.4066 0.3586 0.2168 -0.4290 0.5809 0.3631 -0.3711 -0.1345 -0.4995 0.0597 0.3995 -0.2777 0.5995 0.4701 -0.0200 0.3993 -0.4331 -0.0153 0.0597 -0.0557 0.3878 -0.1270 -0.6640 0.1470 -0.1071 0.3197 0.3849 0.1225 0.1730 -0.1565 0.1221 0.2360 -0.3436 0.5301 0.5243 0.3410 0.4990 -0.0366 -0.0964 -0.5870 ```

Calculate the SVD of a 6-by-6 random matrix, and then calculate the revised SVD with four additional rows. Use the `MaxRank` and `WindowSize` name-value arguments to control the calculation and size of the output.

Create a 6-by-6 random matrix and calculate the SVD.

```A = rand(6); [U,S,V] = svd(A)```
```U = 6×6 -0.4758 -0.0015 -0.4257 0.6098 -0.4496 -0.1358 -0.4440 -0.4208 -0.1279 -0.2969 0.3761 -0.6163 -0.4229 0.2502 0.2709 -0.5781 -0.5923 -0.0053 -0.2832 -0.4610 0.7395 0.3449 0.0073 0.2035 -0.3375 -0.2843 -0.3978 -0.2476 0.1740 0.7453 -0.4510 0.6834 0.1544 0.1598 0.5247 0.0695 ```
```S = 6×6 3.5693 0 0 0 0 0 0 1.2230 0 0 0 0 0 0 1.0101 0 0 0 0 0 0 0.6166 0 0 0 0 0 0 0.4062 0 0 0 0 0 0 0.0390 ```
```V = 6×6 -0.3809 -0.7234 0.0105 0.5327 0.1649 -0.1430 -0.4327 0.1494 0.8629 -0.1576 0.1404 0.0352 -0.4497 0.3557 -0.1725 0.1099 -0.4108 -0.6787 -0.5038 0.1141 -0.4450 -0.3723 0.6261 0.0674 -0.3875 -0.3141 -0.1275 -0.3898 -0.6244 0.4394 -0.2478 0.4650 -0.1059 0.6235 -0.0496 0.5657 ```

Create a 4-by-6 matrix containing four new rows of data, and then calculate the revised SVD. Specify `Shape="rows"` to append the data in `D` as rows.

```D = rand(4,6); [U1,S1,V1] = svdappend(U,S,V,D,Shape="rows")```
```U1 = 10×6 0.3909 0.0593 0.3501 0.2543 0.2971 0.6734 0.3588 0.2925 0.2515 -0.3982 0.1097 -0.3212 0.3429 -0.3027 -0.1746 -0.3867 -0.2745 0.3894 0.2353 0.4938 -0.5672 -0.2279 -0.0616 0.0268 0.2715 0.1703 0.4510 -0.2314 0.0597 -0.1402 0.3767 -0.5450 -0.2275 0.2637 0.1615 -0.2770 0.3299 0.1748 0.1556 0.4787 -0.7600 -0.1485 0.2389 -0.1394 0.1109 0.0742 0.2814 -0.4153 0.2908 0.3004 -0.3953 0.3542 0.3391 0.0045 0.2818 -0.3305 -0.1186 -0.3035 -0.1384 0.0052 ```
```S1 = 6×1 4.3460 1.3335 1.1287 1.0049 0.5681 0.4734 ```
```V1 = 6×6 0.3915 0.8486 -0.0006 0.1502 0.3210 -0.0307 0.4490 -0.1113 -0.8111 -0.2481 -0.1583 -0.2038 0.4156 -0.3870 0.0439 -0.0599 0.5980 0.5608 0.4960 -0.2554 0.4951 -0.1048 0.0576 -0.6552 0.3582 0.1589 0.3070 -0.3938 -0.6290 0.4489 0.3132 -0.1649 -0.0298 0.8638 -0.3396 0.1108 ```

Specify `MaxRank=5` to impose a limit on the number of singular values in `S2` and the number of singular vectors in `U2` and `V2`. After calculating the revised SVD, `svdappend` truncates the smallest singular values and associated singular vectors until the limit is satisfied. These results are similar to `U1`, `S1`, and `V1`, but the smallest singular value and associated singular vectors are truncated.

`[U2,S2,V2] = svdappend(U,S,V,D,Shape="rows",MaxRank=5)`
```U2 = 10×5 0.3909 0.0593 0.3501 0.2543 0.2971 0.3588 0.2925 0.2515 -0.3982 0.1097 0.3429 -0.3027 -0.1746 -0.3867 -0.2745 0.2353 0.4938 -0.5672 -0.2279 -0.0616 0.2715 0.1703 0.4510 -0.2314 0.0597 0.3767 -0.5450 -0.2275 0.2637 0.1615 0.3299 0.1748 0.1556 0.4787 -0.7600 0.2389 -0.1394 0.1109 0.0742 0.2814 0.2908 0.3004 -0.3953 0.3542 0.3391 0.2818 -0.3305 -0.1186 -0.3035 -0.1384 ```
```S2 = 5×1 4.3460 1.3335 1.1287 1.0049 0.5681 ```
```V2 = 6×5 0.3915 0.8486 -0.0006 0.1502 0.3210 0.4490 -0.1113 -0.8111 -0.2481 -0.1583 0.4156 -0.3870 0.0439 -0.0599 0.5980 0.4960 -0.2554 0.4951 -0.1048 0.0576 0.3582 0.1589 0.3070 -0.3938 -0.6290 0.3132 -0.1649 -0.0298 0.8638 -0.3396 ```

Specify `WindowSize=5` to instead discard some of the old rows of data before calculating the revised SVD. Because you specified four new rows of data, this calculation uses those rows and one old row to calculate the revised SVD. Therefore, the results are different than `U2`, `S2`, and `V2`, even though both calculations return five singular values.

`[U3,S3,V3] = svdappend(U,S,V,D,Shape="rows",WindowSize=5)`
```U3 = 5×5 0.5744 0.4555 -0.1212 -0.5750 -0.3424 0.4696 -0.5545 0.6641 -0.0052 -0.1761 0.3423 0.1068 0.0897 -0.1393 0.9187 0.4155 -0.5223 -0.7285 0.1546 0.0005 0.3997 0.4482 0.0745 0.7912 -0.0883 ```
```S3 = 5×1 3.0549 1.0150 0.6496 0.4210 0.3188 ```
```V3 = 6×5 0.2944 -0.7761 -0.3257 0.1669 0.4170 0.5009 0.1933 -0.4472 0.3182 -0.4043 0.4010 0.4166 -0.3378 -0.0369 0.1463 0.4957 0.2692 0.4236 -0.1555 0.5918 0.2325 -0.1051 0.5839 0.6846 -0.2150 0.4494 -0.3212 0.2439 -0.6138 -0.4948 ```

Calculate the SVD of a 6-by-6 test matrix, and then calculate the revised SVD with two additional columns. Use the `AbsoluteTolerance` and `RelativeTolerance` name-value arguments to filter out small singular values and their associated singular vectors.

Create a 6-by-6 test matrix that has only one large singular value using the `gallery` function. Calculate the SVD.

```rng default A = gallery("randsvd",6,[],1); [U,S,V] = svd(A,"vector")```
```U = 6×6 -0.5231 -0.1899 -0.2361 0.0567 -0.2799 0.7437 -0.1183 0.6928 -0.1603 -0.0699 0.6281 0.2845 0.2745 0.2712 0.6555 -0.4224 -0.3032 0.3886 -0.4983 -0.4162 0.4993 -0.2595 0.5040 -0.0888 -0.6224 0.4741 0.0895 -0.0644 -0.4238 -0.4428 0.0372 -0.1118 -0.4812 -0.8614 -0.0408 -0.1048 ```
```S = 6×1 1.0000 0.0000 0.0000 0.0000 0.0000 0.0000 ```
```V = 6×6 -0.2745 0.1637 -0.0633 -0.4598 -0.6460 0.5149 0.0787 0.2018 -0.5393 0.6965 -0.4208 0.0055 -0.0477 0.8161 0.2069 -0.1312 -0.1064 -0.5102 0.5721 -0.2629 -0.3486 -0.4419 -0.3094 -0.4371 -0.5411 -0.4425 0.2591 0.1449 -0.4121 -0.5035 0.5442 -0.0387 0.6883 0.2645 -0.3587 0.1731 ```

Create a 6-by-2 matrix containing two new columns of data, and then calculate the revised SVD. The vector of singular values `S1` now contains three large singular values.

```D = rand(6,2); [U1,S1,V1] = svdappend(U,S,V,D)```
```U1 = 6×6 0.5419 -0.0980 -0.2440 0.0682 0.1162 -0.7868 0.4939 0.4285 0.2632 -0.4816 -0.5134 0.0876 0.0935 0.4736 0.6259 0.2592 0.5484 -0.0852 0.4448 -0.2781 0.1769 0.7060 -0.3247 0.2993 0.4456 -0.4660 0.0556 -0.4059 0.5153 0.3885 0.2395 0.5366 -0.6672 0.1816 0.2263 0.3541 ```
```S1 = 6×1 2.1458 0.6808 0.3284 0.0000 0.0000 0.0000 ```
```V1 = 8×6 0.1031 -0.2335 -0.1009 0.0002 0.7153 -0.3832 -0.0296 0.0670 0.0289 -0.7244 0.0747 -0.4418 0.0179 -0.0406 -0.0175 -0.5634 0.3176 0.6452 -0.2149 0.4866 0.2103 0.1295 0.3610 0.3651 0.2033 -0.4603 -0.1989 0.3035 0.3566 0.1858 -0.2045 0.4630 0.2001 0.2211 0.3528 -0.2718 0.6506 0.5247 -0.5490 -0.0000 -0.0000 -0.0000 0.6599 -0.0330 0.7506 0.0000 -0.0000 -0.0000 ```

Now, perform the same calculation but specify `AbsoluteTolerance=1e-6` to filter out any singular values smaller than that threshold.

`[U2,S2,V2] = svdappend(U,S,V,D,AbsoluteTolerance=1e-6)`
```U2 = 6×3 0.5419 -0.0980 -0.2440 0.4939 0.4285 0.2632 0.0935 0.4736 0.6259 0.4448 -0.2781 0.1769 0.4456 -0.4660 0.0556 0.2395 0.5366 -0.6672 ```
```S2 = 3×1 2.1458 0.6808 0.3284 ```
```V2 = 8×3 0.1031 -0.2335 -0.1009 -0.0296 0.0670 0.0289 0.0179 -0.0406 -0.0175 -0.2149 0.4866 0.2103 0.2033 -0.4603 -0.1989 -0.2045 0.4630 0.2001 0.6506 0.5247 -0.5490 0.6599 -0.0330 0.7506 ```

Alternatively, specify `RelativeTolerance=0.3` to filter out singular values smaller than 30% of the largest singular value. While the absolute tolerance can be any number, the relative tolerance is a value from 0 to 1 indicating how small a singular value can be relative to the largest singular value.

`[U3,S3,V3] = svdappend(U,S,V,D,RelativeTolerance=0.3)`
```U3 = 6×2 0.5419 -0.0980 0.4939 0.4285 0.0935 0.4736 0.4448 -0.2781 0.4456 -0.4660 0.2395 0.5366 ```
```S3 = 2×1 2.1458 0.6808 ```
```V3 = 8×2 0.1031 -0.2335 -0.0296 0.0670 0.0179 -0.0406 -0.2149 0.4866 0.2033 -0.4603 -0.2045 0.4630 0.6506 0.5247 0.6599 -0.0330 ```

## Input Arguments

collapse all

Existing SVD factors, specified as matrices. `U`, `S`, and `V` can be SVD factors of any shape calculated by one of these functions:

How you should recombine the SVD factors differs depending on whether the singular values are returned as a vector or matrix, and whether the decomposition is complete, economy size, or truncated. For example, if `S` is a vector returned as part of a complete decomposition of a square matrix `A`, then `A = (U.*S')*V'`.

Example: `[U,S,V] = svd(A)`

Example: `[U,S,V] = svd(A,"vector")`

Example: `[U,S,V] = svd(A,"econ")`

Example: `[U,S,V] = svd(A,"econ","vector")`

Example: `[U,S,V] = svds(A,5)`

Example: `[U,S,V] = svdsketch(A,1e-5)`

Data Types: `single` | `double`
Complex Number Support: Yes

New columns or rows to append, specified as a vector or matrix. Use the `Shape` name-value argument to specify whether `D` contains columns or rows of data to append. By default, `svdappend` appends `D` as new columns of data.

When `U`, `S`, and `V` are nonempty and `D` has a different data type than those factors, `svdappend` casts `D` to be the same data type.

Data Types: `single` | `double`
Complex Number Support: Yes

### Name-Value Arguments

Specify optional pairs of arguments as `Name1=Value1,...,NameN=ValueN`, where `Name` is the argument name and `Value` is the corresponding value. Name-value arguments must appear after other arguments, but the order of the pairs does not matter.

Example: ```[U1,S1,V1] = svdappend(U,S,V,D,Shape="rows",WindowSize=10)```

Shape of data in `D`, specified as `"columns"` or `"rows"`. If the value is `"columns"`, the revised SVD is for `[A D]`. If the value is `"rows"`, the revised SVD is for `[A; D]`. Neither `[A D]` nor `[A; D]` are explicitly formed.

Example: ```[U1,S1,V1] = svdappend(U,S,V,D,Shape="rows")```

Maximum number of columns or rows to compute the SVD, specified as a positive integer scalar. `WindowSize` controls the memory consumption of the algorithm. The function appends new data and discards the oldest data (starting with the first column or row) to satisfy `WindowSize` before computing the revised SVD. By default, `svdappend` does not discard data.

Example: ```[U1,S1,V1] = svdappend(U,S,V,D,WindowSize=50)```

Absolute tolerance for singular values and vectors, specified as a nonnegative real scalar. The function truncates singular values in `S1` less than or equal to `AbsoluteTolerance`. Corresponding singular vectors in `U1` and `V1` are also truncated. By default, `svdappend` does not truncate the outputs.

Each of the name-value arguments `AbsoluteTolerance`, `RelativeTolerance`, and `MaxRank` result in a specific rank for the revised SVD. `svdappend` truncates the revised SVD based on the minimum rank from all specified arguments.

Example: ```[U1,S1,V1] = svdappend(U,S,V,D,AbsoluteTolerance=1e-6)```

Data Types: `single` | `double`

Relative tolerance for singular values and vectors, specified as a real scalar in the range `[0 1]`. The function truncates singular values in `S1` less than or equal to `RelativeTolerance*S1(1)`. Corresponding singular vectors in `U1` and `V1` are also truncated. By default, `svdappend` does not truncate the outputs.

Each of the name-value arguments `AbsoluteTolerance`, `RelativeTolerance`, and `MaxRank` result in a specific rank for the revised SVD. `svdappend` truncates the revised SVD based on the minimum rank from all specified arguments.

Example: ```[U1,S1,V1] = svdappend(U,S,V,D,RelativeTolerance=0.3)```

Data Types: `single` | `double`

Maximum rank of the revised SVD, specified as a positive integer scalar. `MaxRank` imposes a limit on the number of singular values in `S1` and the number of singular vectors in `U1` and `V1`. By default, there is no limit to the rank.

Each of the name-value arguments `AbsoluteTolerance`, `RelativeTolerance`, and `MaxRank` result in a specific rank for the revised SVD. `svdappend` truncates the revised SVD based on the minimum rank from all specified arguments.

Example: ```[U1,S1,V1] = svdappend(U,S,V,D,MaxRank=25)```

Data Types: `single` | `double`

## Output Arguments

collapse all

Revised singular vectors, returned as matrices.

• If `Shape="columns"`, then `(U1.*S1')*V1'` is equivalent to `[U*S*V' D]` up to round-off error, ignoring truncation.

• If `Shape="rows"`, then `(U1.*S1')*V1'` is equivalent to `[U*S*V'; D]` up to round-off error, ignoring truncation.

• Each of the name-value arguments `AbsoluteTolerance`, `RelativeTolerance`, and `MaxRank` result in a specific rank for the revised SVD. Use these arguments to truncate singular values and vectors to control the rank of `U1*diag(S1)*V1'`.

Different machines and releases of MATLAB® can produce different singular vectors that are still numerically accurate. Corresponding columns in `U1` and `V1` can flip their signs, since this change does not affect the value of the expression `U1*S1*V1'`.

Revised singular values, returned as a column vector. Use `diag(S1)` to create a diagonal matrix of singular values from `S1`.

## Version History

Introduced in R2023b