/// <summary> /// An array with ones at and below the given diagonal and zeros elsewhere. /// </summary> /// <param name="N">Number of rows in the array.</param> /// <param name="M">Number of columns in the array.</param> /// <param name="k">The sub-diagonal at and below which the array is filled.'k' = 0 is the main diagonal, while 'k' LT 0 is below it, and 'k' GT 0 is above.The default is 0.</param> /// <param name="dtype">Data type of the returned array. The default is float.</param> /// <returns></returns> public static ndarray tri(int N, int?M = null, int k = 0, dtype dtype = null) { /* * An array with ones at and below the given diagonal and zeros elsewhere. * * Parameters * ---------- * N : int * Number of rows in the array. * M : int, optional * Number of columns in the array. * By default, `M` is taken equal to `N`. * k : int, optional * The sub-diagonal at and below which the array is filled. * `k` = 0 is the main diagonal, while `k` < 0 is below it, * and `k` > 0 is above. The default is 0. * dtype : dtype, optional * Data type of the returned array. The default is float. * * Returns * ------- * tri : ndarray of shape (N, M) * Array with its lower triangle filled with ones and zero elsewhere; * in other words ``T[i,j] == 1`` for ``i <= j + k``, 0 otherwise. * * Examples * -------- * >>> np.tri(3, 5, 2, dtype=int) * array([[1, 1, 1, 0, 0], * [1, 1, 1, 1, 0], * [1, 1, 1, 1, 1]]) * * >>> np.tri(3, 5, -1) * array([[ 0., 0., 0., 0., 0.], * [ 1., 0., 0., 0., 0.], * [ 1., 1., 0., 0., 0.]]) */ if (dtype == null) { dtype = np.Float32; } if (M == null) { M = N; } ndarray m = ufunc.outer(UFuncOperation.greater_equal, np.Bool, arange(N, dtype: _min_int(0, N)), arange(-k, M - k, dtype: _min_int(-k, (int)M - k))); // Avoid making a copy if the requested type is already bool m = m.astype(dtype, copy: false); return(m); }