# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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. # pylint: disable=invalid-name """MatrixSetDiag in Python""" import numpy as np def matrix_set_diag(input_np, diagonal, k=0, align="RIGHT_LEFT"): """matrix_set_diag operator implemented in numpy. Returns a numpy array with the diagonals of input array replaced with the provided diagonal values. Parameters ---------- input_np : numpy.ndarray Input Array. Shape = [D1, D2, D3, ... , Dn-1 , Dn] diagonal : numpy.ndarray Values to be filled in the diagonal. k : int or tuple of int Diagonal Offsets. align : string Some diagonals are shorter than max_diag_len and need to be padded. Possible Vales: ["RIGHT_LEFT" (default), "LEFT_RIGHT", "LEFT_LEFT", "RIGHT_RIGHT"] Returns ------- result : numpy.ndarray New Array with given diagonal values. Shape = [D1, D2, D3, ... , Dn-1 , Dn] """ out = np.array(input_np, copy=True) cols = input_np.shape[-1] rows = input_np.shape[-2] onlyOneDiagonal = True if isinstance(k, tuple | list): if len(k) < 2 or k[0] == k[1]: k = k[0] else: onlyOneDiagonal = False if onlyOneDiagonal: for i in range(diagonal.shape[-1]): if k >= 0: out[..., i, i + k] = diagonal[..., i] else: out[..., i - k, i] = diagonal[..., i] else: for ki in range(k[0], k[1] + 1): diag_len = min(cols - max(ki, 0), rows + min(ki, 0)) offset = 0 if ki >= 0: if align[:5] == "RIGHT": offset = diagonal.shape[-1] - diag_len else: if align[-5:] == "RIGHT": offset = diagonal.shape[-1] - diag_len for i in range(diag_len): if ki >= 0: out[..., i, i + ki] = diagonal[..., k[1] - ki, i + offset] else: out[..., i - ki, i] = diagonal[..., k[1] - ki, i + offset] return out