fortrangoingonforty/armfortas / c7a292f

Browse files

Test allocatable rank-2 = transpose(reshape(...)) honors column-major stride

Authored by espadonne
Committed by mfwolffe
SHA
c7a292fbe0c83a6efd51cfa8dd7cbc8aa0614999
Parents
b9cfaba
Tree
f73548f

1 changed file

StatusFile+-
M tests/cli_driver.rs 65 0
tests/cli_driver.rsmodified
@@ -4185,6 +4185,71 @@ end program
41854185
     let _ = std::fs::remove_file(&src);
41864186
 }
41874187
 
4188
+#[test]
4189
+fn allocatable_rank2_assign_from_transpose_uses_column_major_stride() {
4190
+    // F2018 §10.1.5: allocatable LHS = transpose(reshape(...)) reallocates
4191
+    // dest with source's shape and copies the data. afs_assign_allocatable
4192
+    // used to set dest.dims[i].stride = 1 across the board, but the
4193
+    // descriptor convention is that stride encodes per-dim *memory step*
4194
+    // in column-major order — see afs_create_section's matching note.
4195
+    // With stride=(1,1) on a 3x3 contiguous block, any subsequent path
4196
+    // that walked the descriptor (e.g. ALLOCATE(target, source=A) inside
4197
+    // a call where A is the assumed-shape dummy) produced overlapping
4198
+    // byte offsets and corrupted the copy. Surfaced as wrong eigenvalue
4199
+    // matrices in stdlib's eigvals/eig clusters.
4200
+    let src = write_program(
4201
+        r#"
4202
+program p
4203
+  implicit none
4204
+  real, allocatable :: A(:,:)
4205
+  A = transpose(reshape([2.0, 8.0, 4.0, 1.0, 3.0, 5.0, 9.0, 5.0, -2.0], [3,3]))
4206
+  call check(A)
4207
+contains
4208
+  subroutine check(a)
4209
+    real, intent(in), target :: a(:,:)
4210
+    real, allocatable :: amat(:,:)
4211
+    allocate(amat(3,3), source=a)
4212
+    if (abs(amat(1,1) - 2.0) > 1.0e-6) error stop 1
4213
+    if (abs(amat(2,1) - 1.0) > 1.0e-6) error stop 2
4214
+    if (abs(amat(3,1) - 9.0) > 1.0e-6) error stop 3
4215
+    if (abs(amat(1,2) - 8.0) > 1.0e-6) error stop 4
4216
+    if (abs(amat(2,2) - 3.0) > 1.0e-6) error stop 5
4217
+    if (abs(amat(3,2) - 5.0) > 1.0e-6) error stop 6
4218
+    if (abs(amat(1,3) - 4.0) > 1.0e-6) error stop 7
4219
+    if (abs(amat(2,3) - 5.0) > 1.0e-6) error stop 8
4220
+    if (abs(amat(3,3) - (-2.0)) > 1.0e-6) error stop 9
4221
+    print *, 'ok'
4222
+  end subroutine
4223
+end program
4224
+"#,
4225
+        "f90",
4226
+    );
4227
+    let out = unique_path("rank2_assign_transpose_stride", "bin");
4228
+    let compile = Command::new(compiler("armfortas"))
4229
+        .args([src.to_str().unwrap(), "-o", out.to_str().unwrap()])
4230
+        .output()
4231
+        .expect("rank2-stride compile failed");
4232
+    assert!(
4233
+        compile.status.success(),
4234
+        "should compile: {}",
4235
+        String::from_utf8_lossy(&compile.stderr)
4236
+    );
4237
+    let run = Command::new(&out).output().expect("run failed");
4238
+    assert!(
4239
+        run.status.success(),
4240
+        "rank-2 allocatable = transpose() produced wrong values: status={:?} stderr={}",
4241
+        run.status,
4242
+        String::from_utf8_lossy(&run.stderr)
4243
+    );
4244
+    assert!(
4245
+        String::from_utf8_lossy(&run.stdout).contains("ok"),
4246
+        "expected 'ok': {}",
4247
+        String::from_utf8_lossy(&run.stdout)
4248
+    );
4249
+    let _ = std::fs::remove_file(&out);
4250
+    let _ = std::fs::remove_file(&src);
4251
+}
4252
+
41884253
 #[test]
41894254
 fn runtime_shape_local_uses_column_major_stride_for_row_section_assign() {
41904255
     // F2018 §6.5.3.2: Fortran arrays are stored in column-major order.