Skip to content
Open
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
23 changes: 23 additions & 0 deletions flang-rt/lib/runtime/extensions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,29 @@ std::int64_t RTNAME(time)() { return time(nullptr); }
// MCLOCK: returns accumulated CPU time in ticks
std::int32_t FORTRAN_PROCEDURE_NAME(mclock)() { return std::clock(); }

// IRAND(I)
int FORTRAN_PROCEDURE_NAME(irand)(int i) {
switch (i) {
case 0:
break;
case 1:
FORTRAN_PROCEDURE_NAME(srand)(0);
break;
default:
FORTRAN_PROCEDURE_NAME(srand)(i);
break;
}
return rand();
}

// RAND(I)
float FORTRAN_PROCEDURE_NAME(rand)(int i) {
return (float)(FORTRAN_PROCEDURE_NAME(irand)(i));
}

// SRAND(SEED)
void FORTRAN_PROCEDURE_NAME(srand)(int seed) { srand(seed); }

// Extension procedures related to I/O

namespace io {
Expand Down
43 changes: 43 additions & 0 deletions flang/docs/Intrinsics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1379,3 +1379,46 @@ This is prefixed by `STRING`, a colon and a space.
- **Standard:** GNU extension
- **Class:** subroutine
- **Syntax:** `CALL PERROR(STRING)`


### Non-Standard Intrinsics: SRAND

#### Description
`SAND` reinitializes the pseudo-random number generator called by `RAND` and `IRAND`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo, should be SRAND

The new seed used by the generator is specified by the required argument `SEED`.

#### Usage and Info

- **Standard:** GNU extension
- **Class:** Subroutine
- **Syntax:** `CALL SRAND(SEED)`

### Non-Standard Intrinsics: IRAND

#### Description
`IRAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and 1.
If `FLAG` is 0, the next number in the current sequence is returned;
If `FLAG` is 1, the generator is restarted by `CALL SRAND(0)`;
If `FLAG` has any other value, it is used as a new seed with `SRAND`.
The return value is of `INTEGER` type of kind 4.

#### Usage and Info

- **Standard:** GNU extension
- **Class:** function
- **Syntax:** `RESULT = IRAND(I)`

### Non-Standard Intrinsics: RAND

#### Description
`RAND(FLAG)` returns a pseudo-random number from a uniform distribution between 0 and 1.
If `FLAG` is 0, the next number in the current sequence is returned;
If `FLAG` is 1, the generator is restarted by `CALL SRAND(0)`;
If `FLAG` has any other value, it is used as a new seed with `SRAND`.
The return value is of `REAL` type with the default kind.

#### Usage and Info

- **Standard:** GNU extension
- **Class:** function
- **Syntax:** `RESULT = RAND(I)`
9 changes: 9 additions & 0 deletions flang/include/flang/Runtime/extensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,14 @@ int FORTRAN_PROCEDURE_NAME(mclock)();
float FORTRAN_PROCEDURE_NAME(secnds)(float *refTime);
float RTNAME(Secnds)(float *refTime, const char *sourceFile, int line);

// GNU extension function IRAND(I)
int FORTRAN_PROCEDURE_NAME(irand)(int i = 0);

// GNU extension function RAND(I)
float FORTRAN_PROCEDURE_NAME(rand)(int i = 0);

// GNU extension subroutine SRAND(SEED)
void FORTRAN_PROCEDURE_NAME(srand)(int seed);

} // extern "C"
#endif // FORTRAN_RUNTIME_EXTENSIONS_H_
41 changes: 41 additions & 0 deletions flang/test/Lower/Intrinsics/rand.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
! RUN: bbc -emit-hlfir %s -o - | FileCheck --check-prefixes=CHECK %s
! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck --check-prefixes=CHECK %s

! CHECK-LABEL: func @_QPtest_srand(
subroutine test_srand()
integer :: seed = 0
call srand(seed)
! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFtest_srandEseed) : !fir.ref<i32>
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_srandEseed"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: fir.call @_QPsrand(%[[VAL_1]]#0) fastmath<contract> : (!fir.ref<i32>) -> ()
! CHECK: return
end subroutine test_srand

! CHECK-LABEL: func @_QPtest_irand(
subroutine test_irand()
integer :: seed = 0
integer :: result
result = irand(seed)
! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "result", uniq_name = "_QFtest_irandEresult"}
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_irandEresult"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFtest_irandEseed) : !fir.ref<i32>
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest_irandEseed"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_4:.*]] = fir.call @_QPirand(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<i32>) -> i32
! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_1]]#0 : i32, !fir.ref<i32>
! CHECK: return
end subroutine test_irand

! CHECK-LABEL: func @_QPtest_rand(
subroutine test_rand()
integer :: seed = 0
real :: result
result = rand(seed)
! CHECK: %[[VAL_0:.*]] = fir.alloca f32 {bindc_name = "result", uniq_name = "_QFtest_randEresult"}
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_randEresult"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFtest_randEseed) : !fir.ref<i32>
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFtest_randEseed"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_4:.*]] = fir.call @_QPrand(%[[VAL_3]]#0) fastmath<contract> : (!fir.ref<i32>) -> f32
! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_1]]#0 : f32, !fir.ref<f32>
! CHECK: return
end subroutine test_rand