# Path: hftools/dataset/dim.py
# class _DimMatrix(DiagAxis):
#     sortprio = 1000
# 
# Path: hftools/dataset/arrayobj.py
# class hfarray(_hfarray):
#     def __new__(subtype, data, dims=None, dtype=None, copy=True, order=None,
#                 subok=False, ndmin=0, unit=None, outputformat=None, info=None):
#         if hasattr(data, "__hfarray__"):
#             data, dims = data.__hfarray__()
#             if unit is None and len(dims) == 1:
#                 unit = dims[0].unit
#             if outputformat is None and len(dims) == 1:
#                 outputformat = dims[0].outputformat
#         return _hfarray.__new__(subtype, data, dims=dims, dtype=dtype,
#                                 copy=copy, order=order, subok=subok,
#                                 ndmin=ndmin, unit=unit,
#                                 outputformat=outputformat, info=info)
# 
# def make_same_dims(A, B):
#     u"""Anropas med lista med *Arrays*. Returnerar arrayer som har samma *dims*
#     dvs vi har anropat change_shape med en *newinfo* som innehaller unionen
#     av de Axis objekt som finns i *dims* av *Arrayerna*.
# 
#     """
#     if not isinstance(B, _hfarray):
#         B = A.__class__(B.view(), dims=A.dims, copy=False)
#     return make_same_dims_list((A, B))
# 
# Path: hftools/math.py
# def det(A):
#     det = linalg.det
#     result = det(A)
#     result = hfarray(result, dims=A.dims[:-2])
#     return result
# 
# def inv(A):
#     inv = linalg.inv
#     result = inv(A)
#     result = hfarray(result, dims=A.dims)
#     return result
# 
# def matrix_multiply(a, b):
#     """Multiply arrays of matrices.
# 
#     a and b are hfarrays containing dimensions DimMatrix_i and DimMatrix_j.
#     Matrix multiplication is done by broadcasting the other dimensions first.
#     """
#     A, B = make_same_dims(a, b)
#     res = np.einsum("...ij,...jk->...ik", A, B)
#     return hfarray(res, dims=A.dims)


import numpy as np
from hftools.dataset import make_same_dims, _DimMatrix, hfarray
from hftools.math import det, inv, matrix_multiply
    Frequency is first index, measurement sweep is second index and port
    indices are third and fourth index. Assuming same shape of all inputs
    """
    return deembedright(deembedleft(e1, S), e2)


def switch_correct(b, a):
    Sm = matrix_multiply(b, inv(a))
    return Sm


def make_passive_svd(S, delta=1e-6):
    """Force S-parameters in S to be passive.

    The S-parameters of S are scaled such that the highest eigenvalue of S'
    becomes |lambda|max < 1 - delta. The scaling is done using SVD.


    Doshi, et.al, DesignCon 2012, "Fast and Optimal Algorithms for Enforcing
    Reciprocity, Passivity and Causality in S-parameters"
    """

    svd = np.linalg.svd
    out = []
    for ss in S:
        ss = np.array(ss, copy=False)
        u, s, v = svd(ss)
        s = abs(s) - 1
        s[s < 0] = 0
        s = np.diag(s)

# Path: hftools/dataset/dim.py
# class _DimMatrix(DiagAxis):
#     sortprio = 1000
# 
# Path: hftools/dataset/arrayobj.py
# class hfarray(_hfarray):
#     def __new__(subtype, data, dims=None, dtype=None, copy=True, order=None,
#                 subok=False, ndmin=0, unit=None, outputformat=None, info=None):
#         if hasattr(data, "__hfarray__"):
#             data, dims = data.__hfarray__()
#             if unit is None and len(dims) == 1:
#                 unit = dims[0].unit
#             if outputformat is None and len(dims) == 1:
#                 outputformat = dims[0].outputformat
#         return _hfarray.__new__(subtype, data, dims=dims, dtype=dtype,
#                                 copy=copy, order=order, subok=subok,
#                                 ndmin=ndmin, unit=unit,
#                                 outputformat=outputformat, info=info)
# 
# def make_same_dims(A, B):
#     u"""Anropas med lista med *Arrays*. Returnerar arrayer som har samma *dims*
#     dvs vi har anropat change_shape med en *newinfo* som innehaller unionen
#     av de Axis objekt som finns i *dims* av *Arrayerna*.
# 
#     """
#     if not isinstance(B, _hfarray):
#         B = A.__class__(B.view(), dims=A.dims, copy=False)
#     return make_same_dims_list((A, B))
# 
# Path: hftools/math.py
# def det(A):
#     det = linalg.det
#     result = det(A)
#     result = hfarray(result, dims=A.dims[:-2])
#     return result
# 
# def inv(A):
#     inv = linalg.inv
#     result = inv(A)
#     result = hfarray(result, dims=A.dims)
#     return result
# 
# def matrix_multiply(a, b):
#     """Multiply arrays of matrices.
# 
#     a and b are hfarrays containing dimensions DimMatrix_i and DimMatrix_j.
#     Matrix multiplication is done by broadcasting the other dimensions first.
#     """
#     A, B = make_same_dims(a, b)
#     res = np.einsum("...ij,...jk->...ik", A, B)
#     return hfarray(res, dims=A.dims)


# Path: hftools/networks/spar_functions.py
import numpy as np
from hftools.dataset import make_same_dims, _DimMatrix, hfarray
from hftools.math import det, inv, matrix_multiply

    Frequency is first index, measurement sweep is second index and port
    indices are third and fourth index. Assuming same shape of all inputs
    """
    return deembedright(deembedleft(e1, S), e2)


def switch_correct(b, a):
    Sm = matrix_multiply(b, inv(a))
    return Sm


def make_passive_svd(S, delta=1e-6):
    """Force S-parameters in S to be passive.

    The S-parameters of S are scaled such that the highest eigenvalue of S'
    becomes |lambda|max < 1 - delta. The scaling is done using SVD.


    Doshi, et.al, DesignCon 2012, "Fast and Optimal Algorithms for Enforcing
    Reciprocity, Passivity and Causality in S-parameters"
    """

    svd = np.linalg.svd
    out = []
    for ss in S:
        ss = np.array(ss, copy=False)
        u, s, v = svd(ss)
        s = abs(s) - 1
        s[s < 0] = 0
        s = np.diag(s)

        delta = matrix_multiply(matrix_multiply(u, s), v)