Fortran menyertakan prosedur bawaan (intrinsic) yang dirancang khusus untuk array, sehingga operasi numerik umum tidak perlu ditulis manual. Topik ini membahas intrinsik reduksi seperti sum dan product, perkalian matriks dengan matmul, pemilihan elemen dengan pack dan unpack, serta penyusunan ulang dengan reshape dan merge. Contoh pada topik ini memakai angka kecil agar setiap hasil pada keluaran dapat dihitung ulang tanpa kalkulator.
Intrinsik reduksi#
Fungsi reduksi (reduction) adalah fungsi yang meringkas banyak nilai menjadi satu nilai. Kelompok ini menjadi dasar perhitungan numerik pada array: sum(nilai) menjumlahkan seluruh elemen, product(nilai) mengalikannya, sedangkan maxval dan minval melaporkan nilai terbesar dan terkecil. Semuanya menerima argumen opsional dim yang membatasi reduksi pada satu dimensi tertentu. Tanpa dim, hasilnya berupa skalar, sedangkan dengan dim, hasilnya berupa array dengan satu dimensi lebih sedikit.
Perbedaan arah reduksi terlihat pada array dua dimensi. sum(m, dim=1) menjumlahkan sepanjang dimensi pertama sehingga menghasilkan jumlah tiap kolom, sedangkan sum(m, dim=2) menghasilkan jumlah tiap baris. Penyebutan dim yang tepat menghindarkan kesalahan arah reduksi, karena kedua bentuk pemanggilannya tetap sah dan beda arahnya sulit dikenali dari angka hasil sekilas. Program berikut mempraktikkan kelompok ini beserta intrinsik lain yang dibahas pada topik ini pada data yang sederhana.
program demo_intrinsik
implicit none
integer :: nilai(5) = [4, 8, 15, 16, 23]
integer :: m(2, 2) = reshape([1, 2, 3, 4], [2, 2]) ! kolom: (1,2) lalu (3,4)
integer :: n(2, 2) = reshape([5, 6, 7, 8], [2, 2])
integer :: hasil(2, 2)
integer :: pola(4)
integer :: terpilih(3)
print *, "sum(nilai) =", sum(nilai)
print *, "product(nilai) =", product(nilai)
print *, "maxval =", maxval(nilai)
print *, "minval =", minval(nilai)
print *, "sum(m, dim=1) =", sum(m, dim=1) ! penjumlahan tiap kolom
print *, "sum(m, dim=2) =", sum(m, dim=2) ! penjumlahan tiap baris
hasil = matmul(m, n)
print *, "matmul baris 1 =", hasil(1, :)
print *, "matmul baris 2 =", hasil(2, :)
terpilih = pack(nilai, nilai > 10)
print *, "pack =", terpilih
pola = unpack([7, 9], [.true., .false., .true., .false.], 0)
print *, "unpack =", pola
print *, "merge =", merge(1, 0, nilai > 10)
end program demo_intrinsik# kompilasi program contoh
gfortran demo-intrinsik.f90 -o demo-intrinsik
# jalankan program
./demo-intrinsik sum(nilai) = 66
product(nilai) = 176640
maxval = 23
minval = 4
sum(m, dim=1) = 3 7
sum(m, dim=2) = 4 6
matmul baris 1 = 23 31
matmul baris 2 = 34 46
pack = 15 16 23
unpack = 7 0 9 0
merge = 0 0 1 1 1Hasil sum(m, dim=1) berupa 3 dan 7, yaitu jumlah kolom pertama (1 + 2) dan kolom kedua (3 + 4), sedangkan sum(m, dim=2) menghasilkan 4 dan 6 dari kedua barisnya. Nilai 66 pada sum(nilai) dan 176640 pada product(nilai) berasal dari lima elemen yang sama, sehingga keduanya memperlihatkan bahwa reduksi tanpa dim mencakup seluruh elemen array.
Dua intrinsik pendamping melengkapi kelompok reduksi. Intrinsik count(mask) melaporkan banyaknya elemen yang lolos mask, yakni array logika yang berperan sebagai penyaring, sedangkan maxloc melaporkan posisi nilai terbesar dalam bentuk array satu elemen. Pada data yang sama, count(nilai > 10) menghasilkan 3, dan maxloc(nilai) menghasilkan 5 karena 23 berada pada posisi kelima.
! tidak-dijalankan
print *, count(nilai > 10) ! banyaknya elemen yang lolos mask, di sini 3
print *, maxloc(nilai) ! posisi nilai terbesar, di sini 5Perkalian matriks dengan matmul#
Intrinsik matmul mengalikan dua matriks dengan aturan perkalian matriks biasa. Argumennya harus cocok, yaitu banyaknya kolom matriks pertama sama dengan banyaknya baris matriks kedua, dan hasilnya dihitung dengan mengalikan setiap baris matriks pertama dengan setiap kolom matriks kedua. Pada program di atas, m berisi kolom (1, 2) dan (3, 4), sedangkan n berisi kolom (5, 6) dan (7, 8), sehingga baris pertama hasilnya adalah 23 dan 31, yaitu hasil dari 1×5 + 3×6 serta 1×7 + 3×8.
Cetakan dua baris pada keluaran memudahkan pemeriksaan manual, karena baris kedua memuat 34 dan 46 dari 2×5 + 4×6 serta 2×7 + 4×8. matmul menerima argumen bertipe integer, real, atau complex, dan tetap menuntut bentuk yang cocok antarkedua argumennya. Pada array yang bentuknya diketahui saat kompilasi, gfortran menolak bentuk yang tidak cocok dengan pesan error saat kompilasi, sehingga kesalahan ini jarang lolos tanpa terdeteksi. Argumen kedua boleh berupa vektor, sehingga matmul(m, v) menghasilkan perkalian matriks dengan vektor dalam satu pemanggilan. Untuk matriks kecil, matmul juga menggantikan perulangan tumpuk tiga lapis yang biasanya ditulis manual.
pack dan unpack#
Intrinsik pack memilih elemen array yang lolos mask dan mengumpulkannya menjadi array satu dimensi. Pada program di atas, pack(nilai, nilai > 10) menghasilkan 15, 16, dan 23, yaitu tiga elemen yang lebih besar dari 10. Banyaknya elemen hasil tidak perlu diketahui sebelumnya, sehingga pack menyaring data numerik tanpa perulangan penghitungan manual.
Kebalikannya, unpack(vector, mask, field) menyebarkan elemen vektor ke posisi yang lolos mask pada array hasilnya, sedangkan posisi yang gagal syarat diisi nilai field. Pemanggilan unpack([7, 9], [.true., .false., .true., .false.], 0) menghasilkan array berisi 7, 0, 9, lalu 0, sebagaimana tercetak pada keluaran. Kedua intrinsik ini biasanya digunakan berpasangan, misalnya memilih elemen dengan pack, mengolah nilainya, lalu mengembalikannya ke posisi yang ditandai mask dengan unpack.
reshape dan merge#
Intrinsik reshape membentuk ulang rangkaian nilai satu dimensi menjadi array dengan bentuk apa pun, dan pengisiannya mengikuti urutan kolom utama. Karena itu reshape([1, 2, 3, 4], [2, 2]) menghasilkan matriks dengan kolom pertama berisi 1 dan 2, sebagaimana tampak pada deklarasi m di program. Argumen order dapat membalik urutan pengisian bila data sumber tersusun baris demi baris, misalnya data yang dibaca dari berkas teks. Argumen opsional pad mengisi posisi yang tidak tercakup data sumber apabila banyaknya nilai sumber kurang dari banyaknya elemen hasil.
Intrinsik merge(tsource, fsource, mask) memilih nilai per elemen dari dua sumber, yaitu tsource bila mask bernilai true dan fsource bila false. Pada program di atas, merge(1, 0, nilai > 10) menghasilkan 0, 0, 1, 1, lalu 1, yang menandai posisi elemen bernilai lebih dari 10. merge cocok untuk menggabungkan dua array hasil perhitungan menurut kondisi per elemen, misalnya memilih nilai koreksi atau nilai pengganti pada posisi tertentu.
Ringkasan#
- Intrinsik reduksi
sum,product,maxval, danminvalmeringkas array menjadi skalar, atau menjadi array berdimensi lebih rendah biladimdisebutkan. matmulmengalikan dua matriks yang bentuknya cocok mengikuti aturan perkalian matriks.packmengumpulkan elemen yang lolos mask menjadi array satu dimensi, danunpackmenyebarkan nilainya kembali ke posisi yang lolos mask.reshapemembentuk array dengan urutan kolom utama, sedangkanmergememilih nilai per elemen dari dua sumber menurut mask.
Referensi#
- Fortran intrinsics — fortran-lang.org — Daftar intrinsik resmi komunitas Fortran berdasarkan draf standar 2018, termasuk sum, matmul, pack, reshape, dan merge.
- GNU Fortran compiler manual — GNU Project — Referensi prosedur intrinsik gfortran yang memuat rincian argumen setiap fungsi di atas.