diff --git a/ReleaseNotes/03_18_2024.txt b/ReleaseNotes/03_18_2024.txt new file mode 100644 index 00000000000..9580fd2e497 --- /dev/null +++ b/ReleaseNotes/03_18_2024.txt @@ -0,0 +1,47 @@ + +Features: + + - C1 Matrix Util Product #1 (1, 2, 3) + - C1 Matrix Util Product #2 (4, 5, 6) + - C1 Matrix Util Product #3 (7, 8, 9) + - C1 Matrix Util Product #4 (10, 11, 12) + - C1 Matrix Util Product #5 (13, 14, 15) + - C1 Matrix Util Product #6 (16, 17, 18) + - C1 Matrix Util Product #7 (19, 20, 21) + - C1 Matrix Util Product #8 (22, 23, 24) + - C1 Cartesian Phi Alpha Beta Theta Standard (25, 26, 27) + - C1 Cartesian Phi Psi Theta Delta Standard #1 (28, 29, 30) + - C1 Cartesian Phi Psi Theta Delta Standard #2 (31, 32, 33) + - C1 Cartesian Phi Psi Theta Delta Alpha (34, 35, 36) + - C1 Cartesian Phi Psi Theta Delta Beta (37, 38, 39) + - C1 Cartesian Fuhr Rzeszotnik Shell (40, 41, 42) + - C1 Cartesian Fuhr Rzeszotnik Rho (43, 44) + - C1 Cartesian Fuhr Rzeszotnik Epsilon (45, 46) + - C1 Cartesian Fuhr Rzeszotnik Eta (47, 48) + - C1 Cartesian Fuhr Rzeszotnik Sigma (49, 50) + - C1 Cartesian Fuhr Rzeszotnik Constructor #1 (51, 52) + - C1 Cartesian Fuhr Rzeszotnik Constructor #2 (53, 54) + - C1 Cartesian Fuhr Rzeszotnik Jordan Normal Left (55, 56) + - C1 Cartesian Fuhr Rzeszotnik Jordan Normal Center (57, 58) + - C1 Cartesian Fuhr Rzeszotnik Jordan Normal Right (58, 60) + - C1 Cartesian Fuhr Rzeszotnik #1 (61, 62, 63) + - C1 Cartesian Fuhr Rzeszotnik #2 (64, 65) + - Numerical Common Unitary Matrix Shell (66, 67, 68) + - Numerical Common Unitary Matrix Constructor (69, 70) + - C1 Util Numerical Complex Unitary (71, 72) + - C1 Matrix Util Unsafe Determinant #1 (73, 74, 75) + - C1 Matrix Util Unsafe Determinant #2 (76, 77, 78) + - Standard Instance of the Unitary Matrix (79, 80, 81) + - Unitary Matrix Condition Number (82, 83, 84) + + +Bug Fixes/Re-organization: + +Samples: + +IdeaDRIP: + + - Matrix Norm (85-87) + - Matrix Norm Preliminaries (88-106) + - Matrix Norms Induced by Vector (107-117) + - Matrix Norms Induced by Vector p-Norms (118-120) diff --git a/src/main/java/org/drip/numerical/complex/C1CartesianFuhrRzeszotnik.java b/src/main/java/org/drip/numerical/complex/C1CartesianFuhrRzeszotnik.java new file mode 100644 index 00000000000..eef537fe7cb --- /dev/null +++ b/src/main/java/org/drip/numerical/complex/C1CartesianFuhrRzeszotnik.java @@ -0,0 +1,278 @@ + +package org.drip.numerical.complex; + +import org.drip.numerical.matrix.R1SquareRotation2x2; + +/* + * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + */ + +/*! + * Copyright (C) 2025 Lakshmi Krishnamurthy + * + * This file is part of DROP, an open-source library targeting analytics/risk, transaction cost analytics, + * asset liability management analytics, capital, exposure, and margin analytics, valuation adjustment + * analytics, and portfolio construction analytics within and across fixed income, credit, commodity, + * equity, FX, and structured products. It also includes auxiliary libraries for algorithm support, + * numerical analysis, numerical optimization, spline builder, model validation, statistical learning, + * graph builder/navigator, and computational support. + * + * https://lakshmidrip.github.io/DROP/ + * + * DROP is composed of three modules: + * + * - DROP Product Core - https://lakshmidrip.github.io/DROP-Product-Core/ + * - DROP Portfolio Core - https://lakshmidrip.github.io/DROP-Portfolio-Core/ + * - DROP Computational Core - https://lakshmidrip.github.io/DROP-Computational-Core/ + * + * DROP Product Core implements libraries for the following: + * - Fixed Income Analytics + * - Loan Analytics + * - Transaction Cost Analytics + * + * DROP Portfolio Core implements libraries for the following: + * - Asset Allocation Analytics + * - Asset Liability Management Analytics + * - Capital Estimation Analytics + * - Exposure Analytics + * - Margin Analytics + * - XVA Analytics + * + * DROP Computational Core implements libraries for the following: + * - Algorithm Support + * - Computation Support + * - Function Analysis + * - Graph Algorithm + * - Model Validation + * - Numerical Analysis + * - Numerical Optimizer + * - Spline Builder + * - Statistical Learning + * + * Documentation for DROP is Spread Over: + * + * - Main => https://lakshmidrip.github.io/DROP/ + * - Wiki => https://github.com/lakshmiDRIP/DROP/wiki + * - GitHub => https://github.com/lakshmiDRIP/DROP + * - Repo Layout Taxonomy => https://github.com/lakshmiDRIP/DROP/blob/master/Taxonomy.md + * - Javadoc => https://lakshmidrip.github.io/DROP/Javadoc/index.html + * - Technical Specifications => https://github.com/lakshmiDRIP/DROP/tree/master/Docs/Internal + * - Release Versions => https://lakshmidrip.github.io/DROP/version.html + * - Community Credits => https://lakshmidrip.github.io/DROP/credits.html + * - Issues Catalog => https://github.com/lakshmiDRIP/DROP/issues + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * C1CartesianFuhrRzeszotnik implements the type and Functionality associated with a C1 + * Square Matrix parameterized by the Fuhr-Rzeszotnik parameters rho, epsilon, + * eta, and sigma Fields. The References are: + * + *

+ * + * + *

+ * + *

+ * + * @author Lakshmi Krishnamurthy + */ + +public class C1CartesianFuhrRzeszotnik extends C1Square +{ + private double _eta = Double.NaN; + private double _rho = Double.NaN; + private double _sigma = Double.NaN; + private double _epsilon = Double.NaN; + private C1Square _jordanNormalCenter = null; + private R1SquareRotation2x2 _jordanNormalLeft = null; + private R1SquareRotation2x2 _jordanNormalRight = null; + + /** + * Construct a Standard Instance of C1CartesianFuhrRzeszotnik + * + * @param eta "Eta" + * @param rho "Rho" + * @param sigma "Sigma" + * @param epsilon "Epsilon" + * + * @return C1CartesianFuhrRzeszotnik Instance + */ + + public static C1CartesianFuhrRzeszotnik Standard ( + final double eta, + final double rho, + final double sigma, + final double epsilon) + { + R1SquareRotation2x2 jordanNormalLeft = R1SquareRotation2x2.Standard (rho); + + if (null == jordanNormalLeft) { + return null; + } + + C1Square jordanNormalCenter = C1Square.Rotation2x2 (epsilon, eta); + + if (null == jordanNormalCenter) { + return null; + } + + R1SquareRotation2x2 jordanNormalRight = R1SquareRotation2x2.Standard (sigma); + + if (null == jordanNormalRight) { + return null; + } + + C1Cartesian[][] c1Grid = C1MatrixUtil.Product ( + jordanNormalLeft.r1Grid(), + jordanNormalCenter.c1Grid() + ); + + return null == c1Grid || null == (c1Grid = C1MatrixUtil.Product (c1Grid, jordanNormalRight.r1Grid())) + ? null : new C1CartesianFuhrRzeszotnik ( + c1Grid, + eta, + rho, + sigma, + epsilon, + jordanNormalLeft, + jordanNormalCenter, + jordanNormalRight + ); + } + + private C1CartesianFuhrRzeszotnik ( + final C1Cartesian[][] c1Grid, + final double eta, + final double rho, + final double sigma, + final double epsilon, + final R1SquareRotation2x2 jordanNormalLeft, + final C1Square jordanNormalCenter, + final R1SquareRotation2x2 jordanNormalRight) + { + super (c1Grid); + + _eta = eta; + _rho = rho; + _sigma = sigma; + _epsilon = epsilon; + _jordanNormalLeft = jordanNormalLeft; + _jordanNormalRight = jordanNormalRight; + _jordanNormalCenter = jordanNormalCenter; + } + + /** + * Retrieve Rho + * + * @return Rho + */ + + public double rho() + { + return _rho; + } + + /** + * Retrieve Epsilon + * + * @return Epsilon + */ + + public double epsilon() + { + return _epsilon; + } + + /** + * Retrieve Eta + * + * @return Eta + */ + + public double eta() + { + return _eta; + } + + /** + * Retrieve Sigma + * + * @return Sigma + */ + + public double sigma() + { + return _sigma; + } + + /** + * Retrieve the Jordan Normal Left Part of C1CartesianPhiPsiThetaDelta + * + * @return Jordan Normal Left Part of C1CartesianPhiPsiThetaDelta + */ + + public R1SquareRotation2x2 jordanNormalLeft() + { + return _jordanNormalLeft; + } + + /** + * Retrieve the Jordan Normal Center Part of C1CartesianPhiPsiThetaDelta + * + * @return Jordan Normal Center Part of C1CartesianPhiPsiThetaDelta + */ + + public C1Square jordanNormalCenter() + { + return _jordanNormalCenter; + } + + /** + * Retrieve the Jordan Normal Right Part of C1CartesianPhiPsiThetaDelta + * + * @return Jordan Normal Right Part of C1CartesianPhiPsiThetaDelta + */ + + public R1SquareRotation2x2 jordanNormalRight() + { + return _jordanNormalRight; + } +} diff --git a/src/main/java/org/drip/numerical/complex/C1CartesianPhiAlphaBetaTheta.java b/src/main/java/org/drip/numerical/complex/C1CartesianPhiAlphaBetaTheta.java index 850bcdc812c..121c1f5c4fe 100644 --- a/src/main/java/org/drip/numerical/complex/C1CartesianPhiAlphaBetaTheta.java +++ b/src/main/java/org/drip/numerical/complex/C1CartesianPhiAlphaBetaTheta.java @@ -147,23 +147,43 @@ public static C1CartesianPhiAlphaBetaTheta Standard ( C1Cartesian ePowerIPhi = C1Cartesian.UnitImaginary().scale (0.5 * phi).exponentiate(); + if (null == ePowerIPhi) { + return null; + } + C1Cartesian ePowerIAlpha = C1Cartesian.UnitImaginary().scale (alpha).exponentiate(); + if (null == ePowerIAlpha) { + return null; + } + C1Cartesian ePowerIBeta = C1Cartesian.UnitImaginary().scale (beta).exponentiate(); - C1Cartesian[][] c1Grid = new C1Cartesian[2][2]; + if (null == ePowerIBeta) { + return null; + } double sinTheta = Math.sin (theta); double cosTheta = Math.cos (theta); - c1Grid[1][1] = ePowerIPhi.divide (ePowerIAlpha).scale (cosTheta); + C1Cartesian[][] c1Grid = new C1Cartesian[2][2]; - c1Grid[0][1] = ePowerIPhi.product (ePowerIBeta).scale (sinTheta); + if (null == (c1Grid[0][0] = ePowerIPhi.product (ePowerIAlpha).scale (cosTheta))) { + return null; + } - c1Grid[0][0] = ePowerIPhi.product (ePowerIAlpha).scale (cosTheta); + if (null == (c1Grid[0][1] = ePowerIPhi.product (ePowerIBeta).scale (sinTheta))) { + return null; + } - c1Grid[1][0] = ePowerIPhi.divide (ePowerIBeta).scale (-1. * sinTheta); + if (null == (c1Grid[1][0] = ePowerIPhi.divide (ePowerIBeta).scale (-1. * sinTheta))) { + return null; + } + + if (null == (c1Grid[1][1] = ePowerIPhi.divide (ePowerIAlpha).scale (cosTheta))) { + return null; + } return new C1CartesianPhiAlphaBetaTheta (c1Grid, alpha, beta, theta, phi); } diff --git a/src/main/java/org/drip/numerical/complex/C1CartesianPhiPsiThetaDelta.java b/src/main/java/org/drip/numerical/complex/C1CartesianPhiPsiThetaDelta.java index 3471048eb1c..a7410b45303 100644 --- a/src/main/java/org/drip/numerical/complex/C1CartesianPhiPsiThetaDelta.java +++ b/src/main/java/org/drip/numerical/complex/C1CartesianPhiPsiThetaDelta.java @@ -126,6 +126,17 @@ public class C1CartesianPhiPsiThetaDelta extends C1Square private C1Square _jordanNormalRight = null; private R1SquareRotation2x2 _jordanNormalCenter = null; + /** + * Construct a Standard Instance of C1CartesianPhiPsiThetaDelta + * + * @param phi "Phi" + * @param psi "Psi" + * @param theta "Theta" + * @param delta "Delta" + * + * @return C1CartesianPhiPsiThetaDelta Instance + */ + public static C1CartesianPhiPsiThetaDelta Standard ( final double phi, final double psi, @@ -138,24 +149,44 @@ public static C1CartesianPhiPsiThetaDelta Standard ( return null; } + C1Cartesian ePowerIPhi = C1Cartesian.UnitImaginary().scale (0.5 * phi).exponentiate(); + + if (null == ePowerIPhi) { + return null; + } + + C1Square jordanNormalLeft = C1Square.Rotation2x2 (psi); + + if (null == jordanNormalLeft || (null == (jordanNormalLeft = jordanNormalLeft.product (ePowerIPhi)))) + { + return null; + } + R1SquareRotation2x2 jordanNormalCenter = R1SquareRotation2x2.Standard (theta); + if (null == jordanNormalCenter) { + return null; + } + C1Square jordanNormalRight = C1Square.Rotation2x2 (delta); - C1Square jordanNormalLeft = C1Square.Rotation2x2 (psi); + if (null == jordanNormalRight) { + return null; + } - C1Cartesian[][] c1Grid = new C1Cartesian[2][2]; - - return new C1CartesianPhiPsiThetaDelta ( - c1Grid, - phi, - psi, - theta, - delta, - jordanNormalLeft, - jordanNormalCenter, - jordanNormalRight - ); + C1Square c1Square = jordanNormalLeft.product (jordanNormalCenter); + + return null == c1Square || null == (c1Square = c1Square.product (jordanNormalRight)) ? + null : new C1CartesianPhiPsiThetaDelta ( + c1Square.c1Grid(), + phi, + psi, + theta, + delta, + jordanNormalLeft, + jordanNormalCenter, + jordanNormalRight + ); } private C1CartesianPhiPsiThetaDelta ( @@ -255,4 +286,26 @@ public C1Square jordanNormalRight() { return _jordanNormalRight; } + + /** + * Calculate Alpha + * + * @return Alpha + */ + + public double alpha() + { + return _psi + _delta; + } + + /** + * Calculate Beta + * + * @return Beta + */ + + public double beta() + { + return _psi - _delta; + } } diff --git a/src/main/java/org/drip/numerical/complex/C1MatrixUtil.java b/src/main/java/org/drip/numerical/complex/C1MatrixUtil.java index 4af1199e6c3..05b771efe85 100644 --- a/src/main/java/org/drip/numerical/complex/C1MatrixUtil.java +++ b/src/main/java/org/drip/numerical/complex/C1MatrixUtil.java @@ -1,6 +1,8 @@ package org.drip.numerical.complex; +import org.drip.numerical.common.NumberUtil; + /* * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ @@ -213,6 +215,111 @@ public static final C1Cartesian[][] UnsafeProduct ( return product; } + /** + * Compute the Product of the Input Matrices. Unsafe Methods do not validate the Input Arguments, so + * use caution in applying these Methods + * + * @param r1GridA Grid of R1 + * @param c1GridB Grid of C1 + * + * @return The Product Matrix + */ + + public static final C1Cartesian[][] UnsafeProduct ( + final double[][] r1GridA, + final C1Cartesian[][] c1GridB) + { + C1Cartesian[][] product = new C1Cartesian[r1GridA.length][c1GridB[0].length]; + + for (int rowIndex = 0; rowIndex < r1GridA.length; ++rowIndex) { + for (int columnIndex = 0; columnIndex < c1GridB[0].length; ++columnIndex) { + product[rowIndex][columnIndex] = C1Cartesian.Zero(); + } + } + + for (int rowIndex = 0; rowIndex < r1GridA.length; ++rowIndex) { + for (int columnIndex = 0; columnIndex < c1GridB[0].length; ++columnIndex) { + for (int k = 0; k < r1GridA[0].length; ++k) { + if (null == product[rowIndex][columnIndex].scale ( + r1GridA[rowIndex][k] + ).add ( + c1GridB[k][columnIndex] + ) + ) + { + return null; + } + } + } + } + + return product; + } + + /** + * Compute the Product of the Input Matrix and the Complex Number. Unsafe Methods do not validate the + * Input Arguments, so use caution in applying these Methods + * + * @param c1Grid Grid of C1 + * @param c1 C1 + * + * @return The Product Matrix + */ + + public static final C1Cartesian[][] UnsafeProduct ( + final C1Cartesian[][] c1Grid, + final C1Cartesian c1) + { + C1Cartesian[][] product = new C1Cartesian[c1Grid.length][c1Grid[0].length]; + + for (int rowIndex = 0; rowIndex < c1Grid.length; ++rowIndex) { + for (int columnIndex = 0; columnIndex < c1Grid[0].length; ++columnIndex) { + if (null == (product[rowIndex][columnIndex] = c1Grid[rowIndex][columnIndex].product (c1))) { + return null; + } + } + } + + return product; + } + + /** + * Determinant of the Input Matrix. Unsafe Methods do not validate the Input Arguments, so use + * caution in applying these Methods + * + * @param c1Grid Grid of C1 Instances + * + * @return The Determinant + */ + + public static final double UnsafeDeterminant ( + final C1Cartesian[][] c1Grid) + { + if (1 == c1Grid.length) { + return Math.sqrt (c1Grid[0][0].modulus()); + } + + if (2 == c1Grid.length) { + return Math.sqrt ( + C1Util.UnsafeDotProduct (c1Grid[0][0], c1Grid[1][1]) - + C1Util.UnsafeDotProduct (c1Grid[0][1], c1Grid[1][0]) + ); + } + + int slimSize = c1Grid.length - 1; + + C1Cartesian[][] c1GridNew = new C1Cartesian[slimSize][slimSize]; + + for (int i = 0; i < slimSize; ++i) { + for (int j = 0; j < slimSize; ++j) { + c1GridNew[i][j] = c1Grid[i][j]; + } + } + + return UnsafeDeterminant (c1GridNew) * c1Grid[slimSize][slimSize].l2Norm() - + c1Grid[slimSize][slimSize].l2Norm() * c1Grid[slimSize][slimSize].l2Norm(); + } + /** * Indicate the C1 Vector is Valid * @@ -300,44 +407,96 @@ public static final C1Cartesian[][] Product ( /** * Compute the Product of the Input Matrices * - * @param c1GridA Grid of C1 - * @param r1GridB Grid of R1 + * @param c1Grid rid of C1 + * @param r1Grid Grid of R1 * * @return The Product Matrix */ public static final C1Cartesian[][] Product ( - final C1Cartesian[][] c1GridA, - final double[][] r1GridB) + final C1Cartesian[][] c1Grid, + final double[][] r1Grid) { - if (!IsGridValid (c1GridA) || - null == r1GridB || 0 == r1GridB.length || - null == r1GridB[0] || 0 == r1GridB[0].length) - { - return null; - }; + return !IsGridValid (c1Grid) || + null == r1Grid || 0 == r1Grid.length || + c1Grid[0].length != r1Grid.length || + !NumberUtil.IsValid (r1Grid) ? + null : UnsafeProduct (c1Grid, r1Grid); + } - C1Cartesian[][] product = new C1Cartesian[c1GridA.length][r1GridB[0].length]; + /** + * Compute the Product of the Input Matrices + * + * @param r1Grid Grid of R1 + * @param c1Grid Grid of C1 + * + * @return The Product Matrix + */ - for (int rowIndex = 0; rowIndex < c1GridA.length; ++rowIndex) { - for (int columnIndex = 0; columnIndex < r1GridB[0].length; ++columnIndex) { - product[rowIndex][columnIndex] = C1Cartesian.Zero(); - } + public static final C1Cartesian[][] Product ( + final double[][] r1Grid, + final C1Cartesian[][] c1Grid) + { + return null == r1Grid || 0 == r1Grid.length || null == r1Grid[0] || + !NumberUtil.IsValid (r1Grid) || !IsGridValid (c1Grid) || r1Grid[0].length != c1Grid.length ? + null : UnsafeProduct (r1Grid, c1Grid); + } + + /** + * Compute the Product of the Input Matrix and the Complex Number + * + * @param c1Grid Grid of C1 + * @param c1 C1 + * + * @return The Product Matrix + */ + + public static final C1Cartesian[][] Product ( + final C1Cartesian[][] c1Grid, + final C1Cartesian c1) + { + return !IsGridValid (c1Grid) || null == c1 ? null : UnsafeProduct (c1Grid, c1); + } + + /** + * Determinant of the Input Matrix + * + * @param c1Grid Grid of C1Cartesian Instances + * + * @return The Determinant + * + * @throws Exception Thrown if the Inputs are Invalid + */ + + public static final double Determinant ( + final C1Cartesian[][] c1Grid) + throws Exception + { + if (null == c1Grid || 0 == c1Grid.length || 0 == c1Grid[0].length) { + throw new Exception ("C1MatrixUtil::Determinant => Invalid Inputs"); } - for (int rowIndex = 0; rowIndex < c1GridA.length; ++rowIndex) { - for (int columnIndex = 0; columnIndex < r1GridB[0].length; ++columnIndex) { - for (int k = 0; k < c1GridA[0].length; ++k) { - if (null == product[rowIndex][columnIndex].add ( - c1GridA[rowIndex][k].scale (r1GridB[k][columnIndex]) - )) - { - return null; - } - } - } + return UnsafeDeterminant (c1Grid); + } + + /** + * Indicate if the Input Matrix is Unitary + * + * @param c1Grid Grid of C1Cartesian Instances + * + * @return TRUE - Input Matrix is Unitary + * + * @throws Exception Thrown if the Inputs are Invalid + */ + + public static final boolean IsUnitary ( + final C1Cartesian[][] c1Grid) + throws Exception + { + if (null == c1Grid || 0 == c1Grid.length || 0 == c1Grid[0].length) { + throw new Exception ("C1MatrixUtil::Determinant => Invalid Inputs"); } - return product; + return NumberUtil.WithinTolerance (UnsafeDeterminant (c1Grid), 0.); } } diff --git a/src/main/java/org/drip/numerical/complex/C1Square.java b/src/main/java/org/drip/numerical/complex/C1Square.java index d23aad3e1b6..bd772c8c913 100644 --- a/src/main/java/org/drip/numerical/complex/C1Square.java +++ b/src/main/java/org/drip/numerical/complex/C1Square.java @@ -2,6 +2,7 @@ package org.drip.numerical.complex; import org.drip.numerical.common.NumberUtil; +import org.drip.numerical.matrix.R1Square; /* * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- @@ -174,6 +175,38 @@ public static final C1Square Rotation2x2 ( return new C1Square (c1Grid); } + /** + * Construct a 2x2 Rotation C1 Matrix + * + * @param theta1 The Left Rotation Angle + * @param theta2 The Right Rotation Angle + * + * @return 2x2 Rotation C1 Matrix + */ + + public static final C1Square Rotation2x2 ( + final double theta1, + final double theta2) + { + if (!NumberUtil.IsValid (theta1) || !NumberUtil.IsValid (theta2)) { + return null; + } + + C1Cartesian c1Zero = C1Cartesian.Zero(); + + C1Cartesian c1UnitImaginary = C1Cartesian.UnitImaginary(); + + C1Cartesian[][] c1Grid = new C1Cartesian[2][2]; + c1Grid[1][0] = c1Zero; + c1Grid[0][1] = c1Zero; + + c1Grid[0][0] = c1UnitImaginary.scale (theta1).exponentiate(); + + c1Grid[1][1] = c1UnitImaginary.scale (theta2).exponentiate(); + + return new C1Square (c1Grid); + } + protected C1Square ( final C1Cartesian[][] c1Grid) { @@ -262,7 +295,7 @@ public C1Square slimContract() public double determinant() { - return C1Util.UnsafeDeterminant (c1Grid()); + return C1MatrixUtil.UnsafeDeterminant (c1Grid()); } /** @@ -286,4 +319,34 @@ public boolean isUnitary() { return isUnitDeterminant(); } + + /** + * Compute the Product with the other Square Matrix + * + * @param r1Square R1 Square Matrix + * + * @return Resulting Product + */ + + public C1Square product ( + final R1Square r1Square) + { + return null == r1Square ? null : new C1Square ( + C1MatrixUtil.UnsafeProduct (c1Grid(), r1Square.r1Grid()) + ); + } + + /** + * Compute the Product of the Input Matrix and the Complex Number + * + * @param c1 C1 + * + * @return The Product C1Square + */ + + public C1Square product ( + final C1Cartesian c1) + { + return null == c1 ? null : new C1Square (C1MatrixUtil.UnsafeProduct (c1Grid(), c1)); + } } diff --git a/src/main/java/org/drip/numerical/complex/C1Util.java b/src/main/java/org/drip/numerical/complex/C1Util.java index 050e2de75cc..1caf5cce70e 100644 --- a/src/main/java/org/drip/numerical/complex/C1Util.java +++ b/src/main/java/org/drip/numerical/complex/C1Util.java @@ -428,43 +428,6 @@ public static final double UnsafeDotProduct ( return a.real() * e.real() + a.imaginary() + a.imaginary(); } - /** - * Determinant of the Input Matrix. Unsafe Methods do not validate the Input Arguments, so use - * caution in applying these Methods - * - * @param c1Grid Grid of C1 Instances - * - * @return The Determinant - */ - - public static final double UnsafeDeterminant ( - final C1Cartesian[][] c1Grid) - { - if (1 == c1Grid.length) { - return Math.sqrt (c1Grid[0][0].modulus()); - } - - if (2 == c1Grid.length) { - return Math.sqrt ( - C1Util.UnsafeDotProduct (c1Grid[0][0], c1Grid[1][1]) - - C1Util.UnsafeDotProduct (c1Grid[0][1], c1Grid[1][0]) - ); - } - - int slimSize = c1Grid.length - 1; - - C1Cartesian[][] c1GridNew = new C1Cartesian[slimSize][slimSize]; - - for (int i = 0; i < slimSize; ++i) { - for (int j = 0; j < slimSize; ++j) { - c1GridNew[i][j] = c1Grid[i][j]; - } - } - - return UnsafeDeterminant (c1GridNew) * c1Grid[slimSize][slimSize].l2Norm() - - c1Grid[slimSize][slimSize].l2Norm() * c1Grid[slimSize][slimSize].l2Norm(); - } - /** * Add the 2 Complex Numbers * @@ -645,25 +608,4 @@ public static final double DotProduct ( return UnsafeDotProduct (a, e); } - - /** - * Determinant of the Input Matrix - * - * @param c1Grid Grid of C1Cartesian Instances - * - * @return The Determinant - * - * @throws Exception Thrown if the Inputs are Invalid - */ - - public static final double Determinant ( - final C1Cartesian[][] c1Grid) - throws Exception - { - if (null == c1Grid || 0 == c1Grid.length || 0 == c1Grid[0].length) { - throw new Exception ("C1MatrixUtil::Determinant => Invalid Inputs"); - } - - return UnsafeDeterminant (c1Grid); - } } diff --git a/src/main/java/org/drip/numerical/complex/UnitaryMatrix.java b/src/main/java/org/drip/numerical/complex/UnitaryMatrix.java new file mode 100644 index 00000000000..d166120ec2f --- /dev/null +++ b/src/main/java/org/drip/numerical/complex/UnitaryMatrix.java @@ -0,0 +1,153 @@ + +package org.drip.numerical.complex; + +/* + * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + */ + +/*! + * Copyright (C) 2025 Lakshmi Krishnamurthy + * + * This file is part of DROP, an open-source library targeting analytics/risk, transaction cost analytics, + * asset liability management analytics, capital, exposure, and margin analytics, valuation adjustment + * analytics, and portfolio construction analytics within and across fixed income, credit, commodity, + * equity, FX, and structured products. It also includes auxiliary libraries for algorithm support, + * numerical analysis, numerical optimization, spline builder, model validation, statistical learning, + * graph builder/navigator, and computational support. + * + * https://lakshmidrip.github.io/DROP/ + * + * DROP is composed of three modules: + * + * - DROP Product Core - https://lakshmidrip.github.io/DROP-Product-Core/ + * - DROP Portfolio Core - https://lakshmidrip.github.io/DROP-Portfolio-Core/ + * - DROP Computational Core - https://lakshmidrip.github.io/DROP-Computational-Core/ + * + * DROP Product Core implements libraries for the following: + * - Fixed Income Analytics + * - Loan Analytics + * - Transaction Cost Analytics + * + * DROP Portfolio Core implements libraries for the following: + * - Asset Allocation Analytics + * - Asset Liability Management Analytics + * - Capital Estimation Analytics + * - Exposure Analytics + * - Margin Analytics + * - XVA Analytics + * + * DROP Computational Core implements libraries for the following: + * - Algorithm Support + * - Computation Support + * - Function Analysis + * - Graph Algorithm + * - Model Validation + * - Numerical Analysis + * - Numerical Optimizer + * - Spline Builder + * - Statistical Learning + * + * Documentation for DROP is Spread Over: + * + * - Main => https://lakshmidrip.github.io/DROP/ + * - Wiki => https://github.com/lakshmiDRIP/DROP/wiki + * - GitHub => https://github.com/lakshmiDRIP/DROP + * - Repo Layout Taxonomy => https://github.com/lakshmiDRIP/DROP/blob/master/Taxonomy.md + * - Javadoc => https://lakshmidrip.github.io/DROP/Javadoc/index.html + * - Technical Specifications => https://github.com/lakshmiDRIP/DROP/tree/master/Docs/Internal + * - Release Versions => https://lakshmidrip.github.io/DROP/version.html + * - Community Credits => https://lakshmidrip.github.io/DROP/credits.html + * - Issues Catalog => https://github.com/lakshmiDRIP/DROP/issues + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * UnitaryMatrix implements the Unitary Matrix. The References are: + * + *

+ * + * + *

+ * + *

+ * + * @author Lakshmi Krishnamurthy + */ + +public class UnitaryMatrix extends C1Square +{ + + /** + * Construct a Standard Instance of the Unitary Matrix + * + * @param c1Grid Grid of C1 Elements + * + * @return Standard Instance of the Unitary Matrix + */ + + public static UnitaryMatrix Standard ( + final C1Cartesian[][] c1Grid) + { + try { + return C1MatrixUtil.IsUnitary (c1Grid) ? new UnitaryMatrix (c1Grid) : null; + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + protected UnitaryMatrix ( + final C1Cartesian[][] c1Grid) + { + super (c1Grid); + } + + /** + * Compute the Default Condition Number of the Matrix + * + * @return Default Condition Number of the Matrix + */ + + public double conditionNumber() + { + return 1.; + } +}