@@ -28623,6 +28623,44 @@ fn cmplx_whole_array_with_kind_keyword_returns_correct_kind_descriptor() { |
| 28623 | 28623 | let _ = std::fs::remove_file(&src); |
| 28624 | 28624 | } |
| 28625 | 28625 | |
| 28626 | +#[test] |
| 28627 | +fn random_number_on_array_fills_every_element() { |
| 28628 | + // F2018 §16.9.171: RANDOM_NUMBER(harvest) fills harvest with |
| 28629 | + // independent draws from [0,1). The intrinsic-subroutine lowering |
| 28630 | + // dispatched all real-kind harvests to the scalar runtime |
| 28631 | + // (afs_random_number_f64), which fills exactly one slot — so for |
| 28632 | + // an array harvest, elements 2..N stayed at uninit-stack-garbage |
| 28633 | + // values (typically tiny denormals or NaN). Surfaced in stdlib |
| 28634 | + // sparse_spmv: `random_number(A); count(abs(A) > tiny(...))` |
| 28635 | + // returned 1 instead of size(A), nnz=1, COO%index allocated as |
| 28636 | + // (2,1), then COO%index(2, idx) walked past dim 0 extent and |
| 28637 | + // tripped "Bounds check failed: index 2 outside [1, 1]". |
| 28638 | + let src = write_program( |
| 28639 | + "program p\n implicit none\n integer, parameter :: dp = kind(0.0d0)\n real(dp) :: a(8)\n real :: b(8)\n integer :: i\n call random_number(a)\n call random_number(b)\n do i = 1, 8\n if (.not. (a(i) >= 0.0_dp .and. a(i) < 1.0_dp)) error stop 1\n if (.not. (b(i) >= 0.0 .and. b(i) < 1.0 )) error stop 2\n end do\n if (count(a > 0.0_dp) /= 8) error stop 3\n if (count(b > 0.0 ) /= 8) error stop 4\n print *, 'ok'\nend program\n", |
| 28640 | + "f90", |
| 28641 | + ); |
| 28642 | + let out = unique_path("random_number_array_fill", "bin"); |
| 28643 | + let compile = Command::new(compiler("armfortas")) |
| 28644 | + .args([src.to_str().unwrap(), "-o", out.to_str().unwrap()]) |
| 28645 | + .output() |
| 28646 | + .expect("random_number array compile failed to spawn"); |
| 28647 | + assert!( |
| 28648 | + compile.status.success(), |
| 28649 | + "random_number array compile failed: {}", |
| 28650 | + String::from_utf8_lossy(&compile.stderr) |
| 28651 | + ); |
| 28652 | + let run = Command::new(&out).output().expect("run failed"); |
| 28653 | + assert!( |
| 28654 | + run.status.success() && String::from_utf8_lossy(&run.stdout).contains("ok"), |
| 28655 | + "random_number array run failed: status={:?} stdout={} stderr={}", |
| 28656 | + run.status, |
| 28657 | + String::from_utf8_lossy(&run.stdout), |
| 28658 | + String::from_utf8_lossy(&run.stderr) |
| 28659 | + ); |
| 28660 | + let _ = std::fs::remove_file(&out); |
| 28661 | + let _ = std::fs::remove_file(&src); |
| 28662 | +} |
| 28663 | + |
| 28626 | 28664 | #[test] |
| 28627 | 28665 | fn allocatable_array_component_passed_to_assumed_size_unwraps_descriptor() { |
| 28628 | 28666 | // F2018 §15.5.2.4: when an allocatable rank-N array component |