Array adalah struktur data utama dalam Fortran, sehingga cara mendeklarasikannya menentukan bentuk hampir semua program numerik. Topik ini membahas sintaks deklarasi array, yakni kumpulan nilai bertipe sama yang diakses melalui indeks, mulai dari batas bawah dan atas setiap dimensi, deklarasi dimensi banyak, konstanta array, hingga urutan penyimpanan elemen di memori yang dikenal sebagai kolom utama. Setelah membaca topik ini, deklarasi array dengan rentang indeks yang benar dapat ditulis, dan urutan pengisian elemen oleh reshape dapat diprediksi.
Deklarasi dengan batas bawah dan atas#
Deklarasi array menyatakan tipe elemen, jumlah dimensi, dan rentang indeks setiap dimensinya dalam satu pernyataan. Bentuk umumnya adalah tipe :: nama(batas_bawah : batas_atas), dan apabila batas bawah tidak ditulis, nilainya satu. Deklarasi integer :: suhu(24) karenanya menyiapkan 24 elemen dengan indeks 1 sampai 24, sedangkan integer :: tahun(1990:2030) menyiapkan 41 elemen dengan indeks mulai dari 1990. Batas bawah yang bukan satu membuat indeks mengikuti makna datanya, misalnya indeks yang sama dengan tahun kalender, tanpa penyesuaian manual saat elemen diakses.
Fungsi intrinsik lbound dan ubound melaporkan batas bawah dan atas sebuah dimensi, sedangkan size melaporkan banyaknya elemen. Ketiganya menerima array sebagai argumen pertama dan nomor dimensi sebagai argumen kedua yang opsional. Nilai yang dilaporkan berguna untuk menulis perulangan yang mengikuti rentang array tanpa menghafal angkanya. Perlu dicatat bahwa deklarasi hanya menyediakan ruang penyimpanan, bukan nilai awal, sehingga elemen array lokal yang belum diisi berisi nilai yang tidak terdefinisi.
! tidak-dijalankan
integer :: suhu(24) ! satu dimensi, indeks 1 sampai 24
integer :: tahun(1990:2030) ! batas bawah ditentukan sendiri
real :: matriks(2, 3) ! dua dimensi, dua baris dan tiga kolomArray dimensi banyak#
Dimensi tambahan dinyatakan dengan menambahkan rentang pada deklarasi, dipisahkan tanda koma. Deklarasi real :: matriks(2, 3) menyiapkan array dua dimensi dengan dua baris dan tiga kolom, dan satu elemen diakses dengan dua indeks seperti matriks(2, 1). Jumlah dimensi disebut rank, yakni banyaknya indeks yang diperlukan untuk mencapai satu elemen. Array tiga dimensi seperti real :: kubus(2, 2, 2) menambah indeks ketiga, dan pola ini berlanjut sampai batas yang ditetapkan standar Fortran 2018, yaitu 15 dimensi.
Penulisan deklarasi Fortran menggunakan satu pasang kurung untuk semua dimensi, berbeda dari bahasa C yang menyarangkan kurung siku per dimensi. Pilihan ini membuat posisi setiap rentang terbaca sekaligus pada satu baris. Untuk data numerik seperti matriks dan tensor, notasi ini juga sejalan dengan cara matematika menulis indeks berlapis. Deklarasi tetap ringkas bahkan untuk array berdimensi tinggi karena setiap dimensi hanya berupa satu rentang.
Konstanta array#
Atribut parameter pada deklarasi array menetapkan isinya sebagai konstanta yang tidak dapat diubah sepanjang program. Pernyataan yang mencoba mengubahnya ditolak pada saat kompilasi, sehingga kesalahan penulisan nilai terdeteksi lebih awal. Nilainya diberikan melalui konstruktor array (array constructor), yakni ekspresi dalam tanda kurung siku yang menyebutkan elemen satu per satu.
! tidak-dijalankan
real, parameter :: skala(3) = [0.5, 1.5, 2.5]
real, parameter :: identitas(2, 2) = reshape([1.0, 0.0, 0.0, 1.0], [2, 2])Konstruktor array satu dimensi cukup untuk kebanyakan kebutuhan, sedangkan array dua dimensi memerlukan reshape karena konstruktor hanya menghasilkan satu dimensi. Konstanta array menghilangkan angka ajaib yang tersebar di badan program, karena nilai yang sama cukup dideklarasikan sekali pada bagian deklarasi. Kebiasaan ini menurunkan risiko ketidakkonsistenan antara deklarasi dan penggunaannya, sebab satu perubahan cukup dilakukan di satu tempat. Selain bilangan, elemen konstruktor boleh berupa ekspresi, misalnya [1.0, 2.0, skala(1)], asalkan semua elemennya bertipe sama.
Urutan penyimpanan kolom utama#
Fortran menyusun elemen array di memori dalam urutan kolom utama (column-major), yakni indeks pertama yang berubah paling cepat. Pada array matriks(2, 3), urutan penyimpanannya adalah matriks(1,1), matriks(2,1), matriks(1,2), matriks(2,2), matriks(1,3), lalu matriks(2,3). Urutan ini tampak jelas ketika array diisi melalui reshape, karena fungsi itu menyalin nilai-nilainya ke memori sesuai aturan yang sama. Diagram berikut memperlihatkan pemetaan tersebut untuk matriks dua kali tiga yang berisi nilai 1 sampai 6.
reshape mengisi array tanpa argumen order, kemudian pengisian diulang dengan order = [2, 1] agar indeks kedua yang berubah lebih dahulu. Perbedaan kedua hasil memperlihatkan aturan pengisian secara langsung.
program demo_deklarasi
implicit none
integer :: tahun(1990:2030) ! batas bawah 1990, bukan 1
real :: matriks(2, 3) ! dua baris, tiga kolom
real, parameter :: skala(3) = [0.5, 1.5, 2.5] ! konstanta array
integer :: i, j
print *, "lbound(tahun, 1) =", lbound(tahun, 1)
print *, "ubound(tahun, 1) =", ubound(tahun, 1)
print *, "size(skala) =", size(skala)
! reshape mengisi elemen kolom demi kolom
matriks = reshape([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], [2, 3])
print *, "isi matriks setelah reshape:"
do i = 1, 2
print "(A, I0, A, 3(F4.1, 1X))", " baris ", i, ":", (matriks(i, j), j = 1, 3)
end do
! argumen order = [2, 1] membalik urutan pengisian
matriks = reshape([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], [2, 3], order = [2, 1])
print *, "isi matriks dengan order = [2, 1]:"
do i = 1, 2
print "(A, I0, A, 3(F4.1, 1X))", " baris ", i, ":", (matriks(i, j), j = 1, 3)
end do
end program demo_deklarasi# kompilasi program contoh
gfortran demo-deklarasi.f90 -o demo-deklarasi
# jalankan program
./demo-deklarasi lbound(tahun, 1) = 1990
ubound(tahun, 1) = 2030
size(skala) = 3
isi matriks setelah reshape:
baris 1: 1.0 3.0 5.0
baris 2: 2.0 4.0 6.0
isi matriks dengan order = [2, 1]:
baris 1: 1.0 2.0 3.0
baris 2: 4.0 5.0 6.0Keluaran memperlihatkan bahwa baris pertama matriks berisi 1.0, 3.0, dan 5.0. Susunan ini muncul karena nilai kedua dari konstruktor, yaitu 2.0, jatuh ke baris kedua pada kolom yang sama. Dengan demikian, pengisian berlangsung ke bawah dalam satu kolom sebelum pindah ke kolom berikutnya. Pada percobaan kedua, order = [2, 1] membalik urutan tersebut sehingga baris pertama berisi 1.0, 2.0, dan 3.0, persis mengikuti urutan nilai pada konstruktor array.
Kesalahan umum#
Kesalahan pertama adalah mengakses indeks di luar rentang yang dideklarasikan. Untuk akses semacam ini, gfortran hanya memberi peringatan saat kompilasi dan tetap meneruskan prosesnya, sedangkan program yang berjalan membaca atau menimpa memori di luar array sehingga menimbulkan perilaku tak terduga, misalnya nilai yang tertukar atau kegagalan di tempat lain. gfortran menyediakan opsi -fcheck=bounds untuk memeriksa batas indeks saat program berjalan, dan opsi ini melaporkan pelanggaran sebagai error, berguna pada tahap pengembangan meskipun eksekusi menjadi lebih lambat.
Kesalahan kedua adalah menganggap deklarasi sekaligus memberi nilai awal. Elemen array lokal berisi nilai sisa memori sampai diisi, sehingga penjumlahan atas array yang belum diisi menghasilkan angka yang tidak dapat dipercaya. Berikan nilai awal melalui konstruktor pada deklarasi, assignment utuh array, atau argumen source= bila arraynya allocatable.
Kesalahan ketiga adalah menukar posisi indeks pada array dimensi banyak. Penukaran semacam ini tidak menimbulkan pesan error karena kedua bentuknya tetap sah, tetapi elemen yang terbaca berbeda dari yang dimaksud. Menulis matriks(3, 2) ketika yang dimaksud adalah matriks(2, 3) tetap lolos kompilasi, sehingga urutan indeks perlu diperiksa secara sengaja, terutama pada array yang dimensinya punya ukuran serupa.
Ringkasan#
- Deklarasi
nama(bawah : atas)menetapkan rentang indeks setiap dimensi, dan batas bawah diperbolehkan bukan satu, misalnyatahun(1990:2030). - Jumlah dimensi array bebas sampai 15 menurut standar Fortran 2018, dan satu elemen diakses dengan indeks sebanyak jumlah dimensinya.
- Atribut
parametermembuat konstanta array yang isinya diberikan melalui konstruktor[...]ataureshape. - Fortran menyimpan elemen dengan urutan kolom utama, sehingga
reshapemengisi array kolom demi kolom kecuali argumenordermenyatakan sebaliknya.
Referensi#
- Learn — fortran-lang.org — Kumpulan tutorial resmi komunitas Fortran yang mencontohkan deklarasi dan operasi array.
- GNU Fortran compiler manual — GNU Project — Dokumentasi resmi gfortran, termasuk referensi intrinsik reshape, lbound, ubound, dan size.