Skip to content

[stdlib_linalg] Add zeros, ones function. #478

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions doc/specs/stdlib_linalg.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,78 @@ program demo_outer_product
!A = reshape([3., 6., 9., 4., 8., 12.], [3,2])
end program demo_outer_product
```

## `zeros/ones`

### Description

`zeros` creates a rank-1 or rank-2 `array` of the given shape, filled completely with `0` `integer` type values.
`ones` creates a rank-1 or rank-2 `array` of the given shape, filled completely with `1` `integer` type values.

### Status

Experimental

### Class

Pure function.

### Syntax

For rank-1 array:
`result = [[stdlib_linalg(module):zeros(interface)]](dim)`
`result = [[stdlib_linalg(module):ones(interface)]](dim)`

For rank-2 array:
`result = [[stdlib_linalg(module):zeros(interface)]](dim1, dim2)`
`result = [[stdlib_linalg(module):ones(interface)]](dim1, dim2)`


### Arguments

`dim/dim1`: Shall be an `integer` type.
This is an `intent(in)` argument.

`dim2`: Shall be an `integer` type.
This is an `intent(in)` argument.

### Return value

Returns a rank-1 or rank-2 `array` of the given shape, filled completely with either `0` or `1` `integer` type values.

#### Warning

Since the result of `ones` is of `integer` type, one should be careful about using it in arithmetic expressions. For example:
```fortran
real :: A(:,:)

!> Be careful
A = ones(2,2)/2 !! A = 1/2 = 0.0

!> Recommend
A = ones(2,2)/2.0 !! A = 1/2.0 = 0.5
```

### Example

```fortran
program demo
use stdlib_linalg, only: zeros, ones
implicit none
real, allocatable :: A(:,:)
integer :: iA(2)
complex :: cA(2), cB(2,3)

A = zeros(2,2) !! [0.0,0.0; 0.0,0.0] (Same as `reshape(spread(0,1,2*2),[2,2])`)
A = ones(4,4) !! [1.0,1.0,1.0,1.0; 1.0,1.0,1.0,1.0; 1.0,1.0,1.0,1.0; 1.0,1.0,1.0 1.0]
A = 2.0*ones(2,2) !! [2.0,2.0; 2.0,2.0]

print *, reshape(ones(2*3*4),[2,3,4]) !! Same as `reshape(spread(1,1,2*3*4),[2,3,4])`

iA = ones(2) !! [1,1] (Same as `spread(1,1,2)`)
cA = ones(2) !! [(1.0,0.0),(1.0,0.0)]
cA = (1.0,1.0)*ones(2) !! [(1.0,1.0),(1.0,1.0)]
cB = ones(2,3) !! [(1.0,0.0),(1.0,0.0),(1.0,0.0); (1.0,0.0),(1.0,0.0),(1.0,0.0)]

end program demo
```
3 changes: 2 additions & 1 deletion src/Makefile.manual
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ stdlib_io.o: \
stdlib_optval.o \
stdlib_kinds.o
stdlib_linalg.o: \
stdlib_kinds.o
stdlib_kinds.o \
stdlib_string_type.o
Copy link
Contributor Author

@zoziha zoziha Aug 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, later I will remove this dependency stdlib_string_type.o (There is no need here, it is a wrong).

stdlib_linalg_diag.o: \
stdlib_linalg.o \
stdlib_kinds.o
Expand Down
63 changes: 61 additions & 2 deletions src/stdlib_linalg.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ module stdlib_linalg
!!Provides a support for various linear algebra procedures
!! ([Specification](../page/specs/stdlib_linalg.html))
use stdlib_kinds, only: sp, dp, qp, &
int8, int16, int32, int64
int8, int16, int32, int64, lk, c_bool
use stdlib_string_type, only: string_type
Comment on lines +7 to +8
Copy link
Contributor Author

@zoziha zoziha Aug 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto (lk, c_bool, string_type)

implicit none
private

public :: diag
public :: eye
public :: trace
public :: outer_product
public :: zeros, ones

interface diag
!! version: experimental
Expand Down Expand Up @@ -80,6 +82,26 @@ module stdlib_linalg
#:endfor
end interface outer_product

!> Version: experimental
!>
!> `ones` creates a rank-1 or rank-2 array of the given shape,
!> filled completely with `1` `integer` type values.
!> ([Specification](../page/specs/stdlib_linalg.html#zerosones))
interface ones
procedure :: ones_1_default
procedure :: ones_2_default
end interface ones

!> Version: experimental
!>
!> `zeros` creates a rank-1 or rank-2 array of the given shape,
!> filled completely with `0` `integer` type values.
!> ([Specification](../page/specs/stdlib_linalg.html#zerosones))
interface zeros
procedure :: zeros_1_default
procedure :: zeros_2_default
end interface zeros

contains

function eye(n) result(res)
Expand Down Expand Up @@ -108,4 +130,41 @@ contains
end do
end function trace_${t1[0]}$${k1}$
#:endfor
end module

!> `ones` creates a rank-1 array, filled completely with `1` `integer` type values.
pure function ones_1_default(dim) result(result)
integer, intent(in) :: dim
integer, allocatable :: result(:)

allocate(result(dim), source=1)

end function ones_1_default

!> `ones` creates a rank-2 array, filled completely with `1` `integer` type values.
pure function ones_2_default(dim1, dim2) result(result)
integer, intent(in) :: dim1, dim2
integer, allocatable :: result(:, :)

allocate(result(dim1, dim2), source=1)

end function ones_2_default

!> `zeros` creates a rank-1 array, filled completely with `0` `integer` type values.
pure function zeros_1_default(dim) result(result)
integer, intent(in) :: dim
integer, allocatable :: result(:)

allocate(result(dim), source=0)

end function zeros_1_default

!> `zeros` creates a rank-2 array, filled completely with `0` `integer` type values.
pure function zeros_2_default(dim1, dim2) result(result)
integer, intent(in) :: dim1, dim2
integer, allocatable :: result(:, :)

allocate(result(dim1, dim2), source=0)

end function zeros_2_default

end module stdlib_linalg
1 change: 1 addition & 0 deletions src/tests/Makefile.manual
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ all test clean:
$(MAKE) -f Makefile.manual --directory=stats $@
$(MAKE) -f Makefile.manual --directory=string $@
$(MAKE) -f Makefile.manual --directory=math $@
$(MAKE) -f Makefile.manual --directory=linalg $@
1 change: 1 addition & 0 deletions src/tests/linalg/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
ADDTEST(linalg)
ADDTEST(linalg_ones_zeros)

4 changes: 4 additions & 0 deletions src/tests/linalg/Makefile.manual
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
PROGS_SRC = test_linalg_ones_zeros.f90


include ../Makefile.manual.test.mk
81 changes: 81 additions & 0 deletions src/tests/linalg/test_linalg_ones_zeros.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
!> SPDX-Identifier: MIT
module test_linalg_ones_zeros

use stdlib_linalg, only: zeros, ones
use stdlib_error, only: check
use stdlib_string_type
implicit none

logical, parameter :: warn = .false.

contains

!> `zeros` tests
subroutine test_linalg_zeros_integer
call check(all(zeros(2) == [0, 0]), msg="all(zeros(2)==[0, 0] failed", warn=warn)
call check(all(zeros(2, 2) == reshape([0, 0, 0, 0], [2, 2])), &
msg="all(zeros(2,2)==reshape([0, 0, 0, 0],[2,2]) failed", warn=warn)
end subroutine test_linalg_zeros_integer

subroutine test_linalg_zeros_real
real, allocatable :: rA(:), rB(:, :)
rA = zeros(2)
call check(all(rA == spread(0.0_4, 1, 2)), msg="all(rA == spread(0.0_4,1,2)) failed", warn=warn)
rB = zeros(2, 2)
call check(all(rB == reshape(spread(0.0_4, 1, 2*2), [2, 2])), &
msg="all(rB == reshape(spread(0.0_4, 1,2*2),[2,2])) failed", warn=warn)
end subroutine test_linalg_zeros_real

subroutine test_linalg_zeros_complex
complex, allocatable :: cA(:), cB(:, :)
cA = zeros(2)
call check(all(cA == spread((0.0_4, 0.0_4), 1, 2)), msg="all(cA == spread((0.0_4,0.0_4),1,2)) failed", warn=warn)
cB = zeros(2, 2)
call check(all(cB == reshape(spread((0.0_4, 0.0_4), 1, 2*2), [2, 2])), &
msg="all(cB == reshape(spread((0.0_4,0.0_4), 1, 2*2), [2, 2])) failed", warn=warn)
end subroutine test_linalg_zeros_complex

!> `ones` tests
subroutine test_linalg_ones_integer
call check(all(ones(2) == [1, 1]), msg="all(ones(2)==[1, 1] failed", warn=warn)
call check(all(ones(2, 2) == reshape([1, 1, 1, 1], [2, 2])), &
msg="all(ones(2,2)==reshape([1, 1, 1, 1],[2,2])) failed", warn=warn)
end subroutine test_linalg_ones_integer

subroutine test_linalg_ones_real
real, allocatable :: rA(:), rB(:, :)
rA = ones(2)
call check(all(rA == spread(1.0_4, 1, 2)), msg="all(rA == spread(1.0_4,1,2)) failed", warn=warn)
rB = ones(2, 2)
call check(all(rB == reshape(spread(1.0_4, 1, 2*2), [2, 2])), &
msg="all(rB == reshape(spread(1.0_4, 1, 2*2), [2, 2])) failed", warn=warn)
end subroutine test_linalg_ones_real

subroutine test_linalg_ones_complex
complex, allocatable :: cA(:), cB(:, :)
cA = ones(2)
call check(all(cA == spread((1.0_4, 0.0_4), 1, 2)), msg="all(cA == spread((1.0_4,0.0_4),1,2)) failed", warn=warn)
cB = ones(2, 2)
call check(all(cB == reshape(spread((1.0_4, 0.0_4), 1, 2*2), [2, 2])), &
msg="all(cB == reshape(spread((1.0_4, 0.0_4), 1, 2*2), [2, 2])) failed", warn=warn)
end subroutine test_linalg_ones_complex

end module test_linalg_ones_zeros

program tester

use test_linalg_ones_zeros

print *, "`zeros` tests"
call test_linalg_zeros_integer
call test_linalg_zeros_real
call test_linalg_zeros_complex

print *, "`ones` tests"
call test_linalg_ones_integer
call test_linalg_ones_real
call test_linalg_ones_complex

print *, "All tests in `test_linalg_ones_zeros` passed"

end program tester