概要
Fortranが標準で備えているビット演算やビット操作,比較,変換などをまとめました.
本記事で紹介している機能一覧は下記の通りです.
- 演算
- シフト
- 比較
- 変換・操作
- 特性値の取得
環境
- Windows 10 64 bit
- Windows 11 64 bit
- gfortran 10.3, 11.2
- Intel Fortran classic 2021.5.0
- NAG Fortran 7.1.0
Fortran 2023での拡張
本記事はFortran 2018規格に沿って記述していますが,Fortran 20203において,2進(および8進,16進)定数の取り扱いが拡張されることになりました.
本記事に関係するところでは,2進定数そのままでは代入演算子の右辺とすることができなかったのが,下記の場合にそのまま右辺とすることができるようになりました.
- 整数あるいは実数の名前付きオブジェクトの初期化
- 整数あるいは実数への組み込み代入演算
- 整数あるいは実数の配列構成子内
-
enumの整数値
表示
ビットに着目するからには,変数を2進数で表示できる必要があります.Fortranでは変数を2進数で表示することも,2進数で表現した数値リテラルを変数に代入することもできます.
数値リテラルとして取り扱う場合は,基数を表す記号の後ろに数値を文字列として記述します.
| 基数 | 基数を表す記号 | 表記例 |
|---|---|---|
| 2 | B |
B'1111100111' |
2進数表記では,それが表す数値の型が不明なので,型変換用の関数と併用する必要があります.
! これは許可されない
! print '(I4)', B'1111100111'
print *, int(B'1111100111') ! 999
print *, real(B'1111100111') ! 1.3998972E-42
変数に2進数リテラルを代入する場合も同様です.
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i
real(real32) :: r
! これは許可されないが,Fortran 2023からは許可される
! i = B'1111100111'
! r = B'1111100111'
i = int(B'1111100111')
r = real(B'1111100111')
print *, i, r ! 999 1.3998972E-42
end program main
2進数で表示する場合には,print文もしくはwrite文の書式で指定します.上位ビットが0の場合は表示が省略されます.その場合は,書式指定で.の後ろに表示する桁数を記述します.
| 基数 | 書式例 | 記述例 | 表示結果 |
|---|---|---|---|
| 2 | '(B8)' |
print '(B8)', 100_int8 |
1100100 |
| 2 | '(B8.8)' |
print '(B8.8)', 100_int8 |
01100100 |
ここでは2進数についてのみ述べましたが,8進数,16進数も同様に取り扱う事ができます.基数を表す記号は,8進数の場合はO,16進数の場合はZで,2, 8, 16進数をまとめてBOZリテラルとよばれます.
| 基数 | 基数を表す記号 | 表記例 |
|---|---|---|
| 2 | B |
B'1111100111' |
| 8 | O |
O'12345670' |
| 16 | Z |
Z'A1B2' |
演算
ここでは,2項もしくは単項演算を行う手続を紹介します.
iand
二つの整数型変数,整数リテラル,あるいはBOZリテラルのビットごとの論理積を計算し,結果を整数で返します.
書式
-
result = iand(i, j)-
i,jは整数(1, 2, 4, 8バイト)もしくはBOZリテラル.-
i,jのどちらもBOZリテラルであってはならない. -
i,jの整数kindは同じでなければならない. -
i,jは配列でもよい.
-
-
resultは整数.-
iが整数ならiと同じkind,そうでなければjと同じkind. -
i,jが配列の場合,resultはi,jと同じ次元,要素数の配列.
-
-
結果の値は,ビットごとに下記の真理値表に従って計算されます.
i |
j |
iand(i,j) |
|---|---|---|
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i, j
i = int(B'10101010', kind=int8)
j = int(B'01010101', kind=int8)
print '(B8.8)', iand(i, j) ! 00000000
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i, j
i = int(B'1111')
j = int(B'1111')
print '(B32.32)', iand(i, j) ! 00000000000000000000000000001111
end program main
program main
implicit none
print '(B32.32)', iand( B'11110000000000000000000000000000', &
int(B'11110000000000000000000000000000'))
! 11110000000000000000000000000000
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: i(:), j(:)
i = [integer(int8) :: 125, 126, 127]
j = [integer(int8) :: 15, 15, 15]
print '(*(B8.8:," "))', i ! 01111101 01111110 01111111
print '(*(B8.8:," "))', j ! 00001111 00001111 00001111
print '(*(B8.8:," "))', iand(i, j) ! 00001101 00001110 00001111
end program main
ior
二つの整数型変数,整数リテラル,あるいはBOZリテラルのビットごとの包含的論理和(1と1の論理和が1)を計算し,結果を整数で返します.
書式
-
result = ior(i, j)-
i,jは整数(1, 2, 4, 8バイト)もしくはBOZリテラル.-
i,jのどちらもBOZリテラルであってはならない. -
i,jの整数kindは同じでなければならない. -
i,jは配列でもよい.
-
-
resultは整数.-
iが整数ならiと同じkind,そうでなければjと同じkind. -
i,jが配列の場合,resultはi,jと同じ次元,要素数の配列.
-
-
結果の値は,ビットごとに下記の真理値表に従って計算されます.
i |
j |
ior(i,j) |
|---|---|---|
0 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i, j
i = int(B'10101011', kind=int8)
j = int(B'01010101', kind=int8)
print '(B8.8)', ior(i, j) ! 11111111
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i
i = int(B'1010')
print '(B32.32)', ior(i, B'1101') ! 00000000000000000000000000001111
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: i(:), j(:)
i = [integer(int8) :: 125, 126, 127]
j = [integer(int8) :: 15, 15, 15]
print '(*(B8.8:," "))', i ! 01111101 01111110 01111111
print '(*(B8.8:," "))', j ! 00001111 00001111 00001111
print '(*(B8.8:," "))', ior(i, j) ! 01111111 01111111 01111111
end program main
ieor
二つの整数型変数,整数リテラル,あるいはBOZリテラルのビットごとの排他的論理和(1と1の論理和が0)を計算し,結果を整数で返します.
書式
-
result = ieor(i, j)-
i,jは整数(1, 2, 4, 8バイト)もしくはBOZリテラル.-
i,jのどちらもBOZリテラルであってはならない. -
i,jの整数kindは同じでなければならない. -
i,jは配列でもよい.
-
-
resultは整数.-
iが整数ならiと同じkind,そうでなければjと同じkind. -
i,jが配列の場合,resultはi,jと同じ次元,要素数の配列.
-
-
結果の値は,ビットごとに下記の真理値表に従って計算されます.
i |
j |
ieor(i,j) |
|---|---|---|
0 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i, j
i = int(B'10101011', kind=int8)
j = int(B'01010101', kind=int8)
print '(B8.8)', ieor(i, j) ! 11111110
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i
i = int(B'1010')
print '(B32.32)', ieor(i, B'1101') ! 00000000000000000000000000000111
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: i(:), j(:)
i = [integer(int8) :: 125, 126, 127]
j = [integer(int8) :: 15, 15, 15]
print '(*(B8.8:," "))', i ! 01111101 01111110 01111111
print '(*(B8.8:," "))', j ! 00001111 00001111 00001111
print '(*(B8.8:," "))', ieor(i, j) ! 01110010 01110001 01110000
end program main
not
整数型変数,整数リテラルの論理否定を計算し,結果を整数で返します.
書式
-
result = not(i)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
resultは整数.-
iと同じkind. -
iが配列の場合,resultはiと同じ次元,要素数の配列.
-
-
結果の値は,ビットごとに下記の真理値表に従って計算されます.
i |
not(i) |
|---|---|
0 |
1 |
1 |
0 |
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'10101010', kind=int8)
print '(B8.8)', not(i) ! 01010101
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: i(:)
i = [integer(int8) :: 2, 4, 8]
print '(*(B8.8:," "))', i ! 00000010 00000100 00001000
print '(*(B8.8:," "))', not(i) ! 11111101 11111011 11110111
end program main
iall
整数型配列を構成する全要素について,ビットごとの論理積を計算し,結果を整数型配列で返します.
簡単に,全要素のiand,あるいは次元ごとのiandを計算すると考えてもらっても問題ありません.
書式
-
result = iall(array [, dim] [, mask])-
arrayは整数(1, 2, 4, 8バイト)型配列. -
dimは整数で,1以上arrayの配列次元数以下の値.- 省略された場合,
arrayを1次元配列として処理する.
- 省略された場合,
-
maskは論理型で,arrayと同じ形状の配列. -
resultは整数型配列あるいはスカラ.- kindは
arrayと同じ. - 配列次元は,
arrayの次元-1. -
arrayが1次元あるいはdimが省略された場合はスカラ.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: a(:)
a = [integer(int8) :: int(B'1110'), int(B'1101'), int(B'1011')]
print '(*(B4.4:, " "))', a ! 1110 1101 1011
print '(*(B4.4:, " "))', iall(a) ! 1000
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: a(:)
a = [integer(int8) :: int(B'1110'), int(B'1101'), int(B'1011')]
print '(*(B4.4:, " "))', a ! 1110 1101 1011
print '(*(B4.4:, " "))', iall(a, mask=[.true., .false., .true.]) ! 1010
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: a(:, :)
a = reshape([integer(int8) :: &
int(B'00001110'), int(B'00001101'), int(B'00001011'), &
int(B'01111011'), int(B'01111110'), int(B'01111101')], &
[3, 2])
print '(*(B8.8:, " "))', a ! 00001110 00001101 00001011 01111011 01111110 01111101
print '(*(B8.8:, " "))', iall(a) ! 00001000
! 全要素のiandを計算
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: a(:, :)
a = reshape([integer(int8) :: &
int(B'00001110'), int(B'00001101'), int(B'00001011'), &
int(B'01111011'), int(B'01111110'), int(B'01111101')], &
[3, 2])
print '(*(B8.8:, " "))', a ! 00001110 00001101 00001011 01111011 01111110 01111101
print '(*(B8.8:, " "))', iall(a, dim=1) ! 00001000 01111000
! iandを→方向に計算 int(B'00001110'), int(B'00001101'), int(B'00001011')
! iandを→方向に計算 int(B'01111011'), int(B'01111110'), int(B'01111101')
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: a(:, :)
a = reshape([integer(int8) :: &
int(B'00001110'), int(B'00001101'), int(B'00001011'), &
int(B'01111011'), int(B'01111110'), int(B'01111101')], &
[3, 2])
print '(*(B8.8:, " "))', a ! 00001110 00001101 00001011 01111011 01111110 01111101
print '(*(B8.8:, " "))', iall(a, dim=2) ! 00001010 00001100 00001001
! iandを↓方向に計算 iandを↓方向に計算 iandを↓方向に計算
! int(B'00001110'), int(B'00001101'), int(B'00001011')
! int(B'01111011'), int(B'01111110'), int(B'01111101')
end program main
iany
整数型配列を構成する全要素について,ビットごとの包含的論理和を計算し,結果を整数型配列で返します.
簡単に,全要素のior,あるいは次元ごとのiorを計算すると考えてもらっても問題ありません.
書式
-
result = iany(array [, dim] [, mask])-
arrayは整数(1, 2, 4, 8バイト)型配列. -
dimは整数で,1以上arrayの配列次元数以下の値.- 省略された場合,
arrayを1次元配列として処理する.
- 省略された場合,
-
maskは論理型で,arrayと同じ形状の配列. -
resultは整数型配列あるいはスカラ.- kindは
arrayと同じ. - 配列次元数は,
arrayの次元-1. -
arrayが1次元あるいはdimが省略された場合はスカラ.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32), allocatable :: a(:)
a = [int(B'1001'), int(B'0101'), int(B'0011')]
print '(*(B4.4:, " "))', a ! 1001 0101 0011
print '(*(B4.4:, " "))', iany(a) ! 1111
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32), allocatable :: a(:)
a = [int(B'1001'), int(B'0101'), int(B'0011')]
print '(*(B4.4:, " "))', a ! 1001 0101 0011
print '(*(B4.4))', iany(a, mask=[.true., .false., .true.]) ! 1011
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: a(:, :)
a = reshape([integer(int8) :: &
int(B'00001110'), int(B'00001101'), int(B'00001011'), &
int(B'01001011'), int(B'00011110'), int(B'00101101')], &
[3, 2])
print '(*(B8.8:, " "))', a ! 00001110 00001101 00001011 01001011 00011110 00101101
print '(*(B8.8:, " "))', iany(a) ! 01111111
! 全要素のiorを計算
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: a(:, :)
a = reshape([integer(int8) :: &
int(B'00001110'), int(B'00001101'), int(B'00001011'), &
int(B'01001011'), int(B'00011110'), int(B'00101101')], &
[3, 2])
print '(*(B8.8:, " "))', a ! 00001110 00001101 00001011 01001011 00011110 00101101
print '(*(B8.8:, " "))', iany(a, dim=1) ! 00001111 01111111
! ianyを→方向に計算 int(B'00001110'), int(B'00001101'), int(B'00001011')
! ianyを→方向に計算 int(B'01001011'), int(B'00011110'), int(B'00101101')
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: a(:, :)
a = reshape([integer(int8) :: &
int(B'00001110'), int(B'00001101'), int(B'00001011'), &
int(B'01001011'), int(B'00011110'), int(B'00101101')], &
[3, 2])
print '(*(B8.8:, " "))', a ! 00001110 00001101 00001011 01001011 00011110 00101101
print '(*(B8.8:, " "))', iany(a, dim=2) ! 01001111 00011111 00101111
! ianyを↓方向に計算 ianyを↓方向に計算 ianyを↓方向に計算
! int(B'00001110'), int(B'00001101'), int(B'00001011')
! int(B'01001011'), int(B'00011110'), int(B'00101101')
end program main
iparity
整数型配列を構成する全要素について,ビットごとの排他的論理和を計算し,結果を整数型配列で返します.
簡単に,全要素のieor,あるいは次元ごとのieorを計算すると考えてもらっても問題ありません.
書式
-
result = iparity(array [, dim] [, mask])-
arrayは整数(1, 2, 4, 8バイト)型配列. -
dimは整数で,1以上arrayの配列次元数以下の値.- 省略された場合,
arrayを1次元配列として処理する.
- 省略された場合,
-
maskは論理型で,arrayと同じ形状の配列. -
resultは整数型配列あるいはスカラ.- kindは
arrayと同じ. - 配列次元数は,
arrayの次元-1. -
arrayが1次元あるいはdimが省略された場合はスカラ.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32), allocatable :: a(:)
a = [int(B'1001'), int(B'0101'), int(B'0011')]
print '(*(B4.4:, " "))', a ! 1001 0101 0011
print '(*(B4.4))', iparity(a) ! 1111
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32), allocatable :: a(:)
a = [int(B'1001'), int(B'0101'), int(B'0011')]
print '(*(B4.4:, " "))', a ! 1001 0101 0011
print '(*(B4.4))', iparity(a, mask=[.true., .false., .true.]) ! 1010
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: a(:, :)
a = reshape([integer(int8) :: &
int(B'00001110'), int(B'00001101'), int(B'00001011'), &
int(B'01001011'), int(B'00011110'), int(B'00101101')], &
[3, 2])
print '(*(B8.8:, " "))', a ! 00001110 00001101 00001011 01001011 00011110 00101101
print '(*(B8.8:, " "))', iparity(a) ! 01110000
! 全要素のieorを計算
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: a(:, :)
a = reshape([integer(int8) :: &
int(B'00001110'), int(B'00001101'), int(B'00001011'), &
int(B'01001011'), int(B'00011110'), int(B'00101101')], &
[3, 2])
print '(*(B8.8:, " "))', a ! 00001110 00001101 00001011 01001011 00011110 00101101
print '(*(B8.8:, " "))', iparity(a, dim=1) ! 00001000 01111000
! iparityを→方向に計算 int(B'00001110'), int(B'00001101'), int(B'00001011')
! iparityを→方向に計算 int(B'01001011'), int(B'00011110'), int(B'00101101')
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8), allocatable :: a(:, :)
a = reshape([integer(int8) :: &
int(B'00001110'), int(B'00001101'), int(B'00001011'), &
int(B'01001011'), int(B'00011110'), int(B'00101101')], &
[3, 2])
print '(*(B8.8:, " "))', a ! 00001110 00001101 00001011 01001011 00011110 00101101
print '(*(B8.8:, " "))', iparity(a, dim=2) ! 01000101 00010011 00100110
! iparityを↓方向に計算 iparityを↓方向に計算 iparityを↓方向に計算
! int(B'00001110'), int(B'00001101'), int(B'00001011')
! int(B'01001011'), int(B'00011110'), int(B'00101101')
end program main
parity
論理型配列を構成する全要素の.neqv.,あるいは次元ごとの.neqv.を計算した結果を論理値で返します.
簡単に,論理型配列内の真の要素が奇数個の場合に真,偶数個の場合に偽を返すと考えてもらっても問題ありません.
書式
-
result = parity(array [, dim])-
arrayは論理型配列. -
dimは整数で,1以上arrayの配列次元数以下の値.- 省略された場合,
arrayを1次元配列として処理する.
- 省略された場合,
-
resultは論理型配列あるいはスカラ.- 配列次元数は,
arrayの次元-1. -
arrayが1次元あるいはdimが省略された場合はスカラ.
- 配列次元数は,
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
logical, allocatable :: a(:)
a = [.true., .false., .true.]
print '(*(L1:, " "))', a ! T F T
print '(*(L1:, " "))', parity(a) ! F
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
logical, allocatable :: a(:)
a = [.true., .false., .true.]
print '(*(L1:, " "))', a ! F T F
print '(*(L1:, " "))', parity(a) ! T
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
logical, allocatable :: a(:, :)
a = reshape([.true., .false., .true., &
.false., .true., .false.], &
[3, 2])
print '(*(L1:, " "))', a ! T F T F T F
print '(*(L1:, " "))', parity(a) ! T
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
logical, allocatable :: a(:, :)
a = reshape([.true., .false., .true., &
.false., .true., .false.], &
[3, 2])
print '(*(L1:, " "))', a ! T F T F T F
print '(*(L1:, " "))', parity(a, dim=1) ! F T
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
logical, allocatable :: a(:, :)
a = reshape([.true., .false., .true., &
.false., .true., .false.], &
[3, 2])
print '(*(L1:, " "))', a ! T F T F T F
print '(*(L1:, " "))', parity(a, dim=2) ! T T T
end program main
シフト
ここでは,ビットシフトを行う手続を紹介します.
ishft
整数型変数あるいは整数リテラルを,右あるいは左方向に指定の桁だけビットシフトした値を整数で返します.左端あるいは右端からはみ出したビットは破棄され,反対側には0が設定されます.
書式
-
result = ishft(i, shift)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
shiftは整数で,その絶対値は1以上iのビットサイズ以下の値.-
shift>0の場合,左方向にシフトが行われる. -
shift<0の場合,右方向にシフトが行われる. -
0の場合,シフトは行われない. -
shiftは配列でもよい. -
iとshiftの両方を配列とする場合,配列の形状は同じでなければならない.
-
-
resultは整数.- kindは
iと同じ. -
iが配列の場合,resultはiと同じ次元,要素数の配列. -
shiftが配列の場合,resultはshiftと同じ次元,要素数の配列.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'11100111', kind=int8)
print '(*(B8.8:, " "))', ishft(i, 2) ! 10011100
print '(*(B8.8:, " "))', ishft(i, 0) ! 11100111
print '(*(B8.8:, " "))', ishft(i, -2) ! 00111001
end program main
ishftc
整数型変数あるいは整数リテラルを,右あるいは左方向に指定の桁だけビットシフトした値を返します.ビットシフトは循環的に行われ,左端あるいは右端からはみ出したビットは反対側に設定されます.
書式
-
result = ishftc(i, shift)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
shiftは整数で,その絶対値は1以上iのビットサイズ以下の値.-
shift>0の場合,左方向に循環シフトが行われる. -
shift<0の場合,右方向に循環シフトが行われる. -
0の場合,シフトは行われない. -
shiftは配列でもよい. -
iとshiftの両方を配列とする場合,配列の形状は同じでなければならない.
-
-
resultは整数.- kindは
iと同じ. -
iが配列の場合,resultはiと同じ次元,要素数の配列.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'11100111', kind=int8)
print '(*(B8.8:, " "))', ishftc(i, 2) ! 10011111
print '(*(B8.8:, " "))', ishftc(i, 0) ! 11100111
print '(*(B8.8:, " "))', ishftc(i, -2) ! 11111001
end program main
shifta
整数型変数あるいは整数リテラルを,指定の桁だけ右方向にビットシフトした値を返します.左端からはみ出したビットは破棄され,右のシフトされたビット分には,シフトされる整数の最上位ビットの値が詰められます.
書式
-
result = shifta(i, shift)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
shiftは整数で,1以上iのビットサイズ以下の値.-
0の場合,シフトは行われない. -
shiftは配列でもよい. -
iとshiftの両方を配列とする場合,配列の形状は同じでなければならない.
-
-
resultは整数.- kindは
iと同じ. -
iが配列の場合,resultはiと同じ次元,要素数の配列. -
shiftが配列の場合,resultはshiftと同じ次元,要素数の配列.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'10000000', kind=int8)
print '(*(B8.8:, " "))', shifta(i, 2) ! 11100000
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'01111111', kind=int8)
print '(*(B8.8:, " "))', shifta(i, 2) ! 00011111
end program main
shiftl
整数型変数あるいは整数リテラルを,指定の桁だけ左方向にビットシフトした値を返します.左端からはみ出したビットは破棄され,右側には0が詰められます.
書式
-
result = shiftl(i, shift)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
shiftは整数で,1以上iのビットサイズ以下の値.-
0の場合,シフトは行われない. -
shiftは配列でもよい. -
iとshiftの両方を配列とする場合,配列の形状は同じでなければならない.
-
-
resultは整数.- kindは
iと同じ. -
iが配列の場合,resultはiと同じ次元,要素数の配列. -
shiftが配列の場合,resultはshiftと同じ次元,要素数の配列.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'11111111', kind=int8)
print '(*(B8.8:, " "))', shiftl(i, 2) ! 11111100
end program main
shiftr
整数型変数あるいは整数リテラルを,指定の桁だけ右方向にビットシフトした値を返します.右端からはみ出したビットは破棄され,左側には0が詰められます.
書式
-
result = shiftl(i, shift)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
shiftは整数で,1以上iのビットサイズ以下の値.-
0の場合,シフトは行われない. -
shiftは配列でもよい. -
iとshiftの両方を配列とする場合,配列の形状は同じでなければならない.
-
-
resultは整数.- kindは
iと同じ. -
iが配列の場合,resultはiと同じ次元,要素数の配列. -
shiftが配列の場合,resultはshiftと同じ次元,要素数の配列.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'11111111', kind=int8)
print '(*(B8.8:, " "))', shiftr(i, 2) ! 00111111
end program main
比較
ここでは,ビット単位の比較を行う組み込み手続を紹介します.
bge
二つの整数型変数,整数リテラルあるいはBOZリテラルをビットごとに比較し,ビット列が大きいか等しいかを判別した結果を論理値で返します.この比較において,最上位ビットは符号ビットとは解釈されません.
書式
-
result = bge(i, j)-
i,jは整数(1, 2, 4, 8バイト)もしくはBOZリテラル.-
i,jのどちらもBOZリテラルであってはならない. -
i,jの整数kindは同じでなければならない. -
i,jは配列でもよい.
-
-
resultは論理型.-
iのビット列がjのビット列より大きいか等しい場合に真,そうでない場合に偽となる. -
i,jが配列の場合,resultはi,jと同じ次元,要素数の配列.
-
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i, j
i = int(B'01111111111111111111111111111111')
j = int(B'01111111111111111111111111111110')
print *, bge(i, j) ! T
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i, j
i = int(B'01111111111111111111111111111111')
j = int(B'01111111111111111111111111111111')
print *, bge(i, j) ! T
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i, j
i = int(B'00000000000000000000000000000000')
j = int(B'11111111111111111111111111111111')
print *, bge(i, j) ! F
end program main
bgt
二つの整数型変数,整数リテラルあるいはBOZリテラルをビットごとに比較し,ビット列が大きいかを判別した結果を論理値で返します.この比較において,最上位ビットは符号ビットとして解釈されません.
書式
-
result = bgt(i, j)-
i,jは整数(1, 2, 4, 8バイト)もしくはBOZリテラル.-
i,jのどちらもBOZリテラルであってはならない. -
i,jの整数kindは同じでなければならない. -
i,jは配列でもよい.
-
-
resultは論理型.-
iのビット列がjのビット列より大きい場合に真,そうでない場合に偽となる. -
i,jが配列の場合,resultはi,jと同じ次元,要素数の配列.
-
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i, j
i = int(B'01111111111111111111111111111111')
j = int(B'01111111111111111111111111111110')
print *, bgt(i, j) ! T
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i, j
i = int(B'01111111111111111111111111111111')
j = int(B'01111111111111111111111111111111')
print *, bgt(i, j) ! F
end program main
ble
二つの整数型変数,整数リテラルあるいはBOZリテラルをビットごとに比較し,ビット列が小さいか等しいかを判別します.この比較において,最上位ビットは符号ビットとして解釈されません.
書式
-
result = ble(i, j)-
i,jは整数(1, 2, 4, 8バイト)もしくはBOZリテラル.-
i,jのどちらもBOZリテラルであってはならない. -
i,jの整数kindは同じでなければならない. -
i,jは配列でもよい.
-
-
resultは論理型.-
iのビット列がjのビット列より小さいか等しい場合に真,そうでない場合に偽となる. -
i,jが配列の場合,resultはi,jと同じ次元,要素数の配列.
-
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i, j
i = int(B'01111111111111111111111111111110')
j = int(B'01111111111111111111111111111111')
print *, ble(i, j) ! T
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i, j
i = int(B'01111111111111111111111111111111')
j = int(B'01111111111111111111111111111111')
print *, ble(i, j) ! T
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i, j
i = int(B'00000000000000000000000000000000')
j = int(B'11111111111111111111111111111111')
print *, ble(i, j) ! T
end program main
blt
二つの整数型変数,整数リテラルあるいはBOZリテラルをビットごとに比較し,ビット列が小さいかを判別した結果を論理値で返します.この比較において,最上位ビットは符号ビットとして解釈されません.
書式
-
result = ble(i, j)-
i,jは整数(1, 2, 4, 8バイト)もしくはBOZリテラル.-
i,jのどちらもBOZリテラルであってはならない. -
i,jの整数kindは同じでなければならない. -
i,jは配列でもよい.
-
-
resultは論理型.-
iのビット列がjのビット列より小さい場合に真,そうでない場合に偽となる. -
i,jが配列の場合,resultはi,jと同じ次元,要素数の配列.
-
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i, j
i = int(B'01111111111111111111111111111110')
j = int(B'01111111111111111111111111111111')
print *, blt(i, j) ! T
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i, j
i = int(B'01111111111111111111111111111111')
j = int(B'01111111111111111111111111111111')
print *, blt(i, j) ! F
end program main
変換・操作
整数をビット単位で操作する手続や,ビット列を他の表現として解釈するような手続を紹介します.
これらの手続きでビットの位置を指定する場合,最下位ビットの位置を0とします.
ibset
整数型変数あるいは整数リテラルの,指定された位置のビットを1に置き換えた値を整数で返します.
書式
-
result = ibset(i, pos)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
posは整数で,0以上iのビットサイズ未満の値.-
posは配列でもよい. -
iとposの両方を配列とする場合,配列の形状は同じでなければならない.
-
-
resultは整数.- kindは
iと同じ. -
iが配列の場合,resultはiと同じ次元,要素数の配列. -
posが配列の場合,resultはposと同じ次元,要素数の配列.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'00000000', kind=int8)
print '(*(B8.8:," "))', ibset(i, 0) ! 00000001
print '(*(B8.8:," "))', ibset(i, 7) ! 10000000
!
! ibset(i, 0)
!
! ビットを1にする位置
! v
! i 00000000 -> result 00000001
! pos 76543210
end program main
ibclr
整数型変数あるいは整数リテラルの,指定された位置のビットを0に置き換えた値を整数で返します.
書式
-
result = ibclr(i, pos)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
posは整数で,0以上iのビットサイズ未満の値.-
posは配列でもよい. -
iとposの両方を配列とする場合,配列の形状は同じでなければならない.
-
-
resultは整数.- kindは
iと同じ. -
iが配列の場合,resultはiと同じ次元,要素数の配列. -
posが配列の場合,resultはposと同じ次元,要素数の配列.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'11111111', kind=int8)
print '(*(B8.8:," "))', ibclr(i, 0) ! 11111110
print '(*(B8.8:," "))', ibclr(i, 7) ! 01111111
!
! ibclr(i, 7)
!
! ビットを0にする位置
! v
! i 11111111 -> result 01111111
! pos 76543210
end program main
ibits
整数型変数あるいは整数リテラルの,指定された範囲のビットを取り出して右詰し,残りのビットに0を設定した値を整数で返します.取り出す範囲は,ビットの位置と,その位置から上位桁方向の長さで指定します.
書式
-
result = ibits(i, pos, len)-
iは整数(1, 2, 4, 8バイト). -
posは整数で,0以上の値.-
pos+lenはiのビットサイズ以下.
-
-
lenは整数で,0以上の値.-
pos+lenはiのビットサイズ以下.
-
-
resultは整数.- kindは
iと同じ. -
posが配列の場合,resultも配列.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'11110000', kind=int8)
print '(*(B8.8:," "))', ibits(i, 2, 4) ! 00001100
!
! ibits(i, 2, 4)
!
! 抜き出すビット
! <--> len 抜き出されたビット
! v pos v--v
! i 11110000 -> result 00001100
! pos 76543210
! ^--^
! 0詰め
end program main
merge_bits
二つの整数変数,整数リテラルあるいはBOZリテラルを一つに併合し,結果を整数として返します.併合のする際にどちらのビットを採用するかは,追加の整数型引数に基づいて決定されます.
簡単に,第3引数のビットが1の位置は第1引数のビットが選ばれ,0の位置は第2引数のビットが選ばれると理解して問題ありません.
書式
-
result = merge_bits(i, j, mask)-
i,jは整数(1, 2, 4, 8バイト)もしくはBOZリテラル.-
i,jのどちらもBOZリテラルであってはならない. -
i,jの整数kindは同じでなければならない.
-
-
maskは整数(1, 2, 4, 8バイト).-
maskの整数kindは,i,jと同じでなければならない.
-
-
resultは整数.- kindは
iと同じ. -
maskのビットが1の桁ではiのビット,0の桁ではjのビットと同じ値.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i, j, mask
i = int(B'01001101', kind=int8)
j = int(B'10110010', kind=int8)
mask = int(B'11111111', kind=int8)
print '(*(B8.8:," "))', merge_bits(i, j, mask) ! 01001101
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i, j, mask
i = int(B'01001101', kind=int8)
j = int(B'10110010', kind=int8)
mask = int(B'00000000', kind=int8)
print '(*(B8.8:," "))', merge_bits(i, j, mask) ! 10110010
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i, j, mask
i = int(B'01001101', kind=int8)
j = int(B'10110010', kind=int8)
mask = int(B'11110000', kind=int8)
print '(*(B8.8:," "))', merge_bits(i, j, mask) ! 01000010
end program main
mvbits
整数型変数あるいは整数リテラル内の,指定した範囲のビットを他の整数型変数にコピーします.
書式
-
call mvbits(from, frompos, len, to, topos)-
fromは整数(1, 2, 4, 8バイト). -
fromposは整数で,0以上の値.-
frompos+lenはfromのビットサイズ以下.
-
-
lenは整数で,0以上の値-
frompos+lenはfromのビットサイズ以下.
-
-
toは整数型変数.- kindは
fromと同じ. -
toの値は,元々保持していたビット列に,fromのfrompos桁から上位ビットの方向に長さlenのビット列を,toposの位置に上書きした値となる.
- kindは
-
toposは整数で,0以上の値.-
topos+lenはtoのビットサイズ以下.
-
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: from, to
from = int(B'00001111', kind=int8)
to = int(B'11100001', kind=int8)
call mvbits(from, 2, 4, to, 3)
print '(*(B8.8:," "))', to ! 10011001
!
! call mvbits(from, frompos, len, to, topos)
!
! 抜き出されたビットが設定される
! <--> len 0011
! v frompos v topos
! from 00001111 to 11100001 -> 10011001
! pos 76543210 76543210
!
end program main
transfar
ビット列を他の表現として解釈します.
書式
-
result = transfer(source, mold[, size])-
sourceは任意の型の変数あるいはリテラル.-
sourceはスカラでも配列でもよい.
-
-
moldは任意の型の変数あるいはリテラル.-
moldはsourceを解釈するための手本として用いられる. -
moldはスカラでも配列でもよい.
-
-
sizeは整数型.-
sizeが省略され,moldがスカラの場合,resultはスカラ. -
sizeが省略され,moldが配列の場合,resultは1次元配列. -
sizeが指定されると,resultは大きさがsizeの1次元配列.
-
-
resultはmoldと同じ型で,sourceと同じビット列を持つ.- スカラか配列かは,
moldおよびsizeの指定で決まる.
- スカラか配列かは,
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int32) :: i
real(real32) :: r
r = 1.0
i = transfer(r, mold=i) ! 単精度浮動小数点の1.0を表現するビット列を整数に変換する.
print '(B32.32," ",B32.32)', i, r ! 00111111100000000000000000000000 00111111100000000000000000000000 ! NAG Fortranでは,実数に対してB型編集記述子が適用できないため,エラーが出る
print *, i, r ! 1065353216 1.00000000
! 1.0の一つ隣の単精度浮動小数点の値を計算する
r = transfer(i + 1, mold=r)
print *, r, spacing(1.0) ! 1.00000012 1.19209290E-07
end program main
特性値のしゅとく
ビット表現に関係する値を取得する手続を紹介します.
storage_size
引数の変数が占有するメモリサイズをビット単位で返します,
書式
-
result = storage_size(a[, kind])-
aは任意の型の実体. -
kindは整数kindを表す整数. -
resultは整数で,単位は[bit].- kindが省略された場合,
resultのkindはinteger型のkindと同じ.
- kindが省略された場合,
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
print *, storage_size(0_int8) ! 8
print *, storage_size(0_int16) ! 16
print *, storage_size(0_int32) ! 32
print *, storage_size(0_int64) ! 64
end program main
bit_size
整数型変数あるいは整数リテラルのビット数を返します.
書式
-
result = bit_size(i)-
iは整数(1, 2, 4, 8バイト). -
resultはiのビット数.-
resultのkindはiのkindと同じ.
-
-
例
use, intrinsic :: iso_fortran_env
implicit none
print *, bit_size(0_int8) ! 8
print *, bit_size(0_int16) ! 16
print *, bit_size(0_int32) ! 32
print *, bit_size(0_int64) ! 64
end program main
btest
整数型変数,整数リテラルにおいて,指定した桁のビットが1か否かを検査し,結果を論理型で返します.
書式
-
result = btest(i, pos)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
posは整数で,0以上iのビット数以下の値.-
posは配列でもよい. -
iとposの両方を配列とする場合,配列の形状は同じでなければならない.
-
-
resultは論理型.-
iのpos桁目のビットが1の場合は真,0の場合は偽. -
iが配列の場合,resultはiと同じ次元,要素数の配列. -
posが配列の場合,resultはposと同じ次元,要素数の配列.
-
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'01010101', kind=int8)
print *, btest(i, 0) ! T
print *, btest(i, 1) ! F
end program main
leadz
整数型変数,整数リテラルの中で,1になっている最も上位のピットよりも上位にある0の数を返します.
書式
-
result = leadz(i)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
resultは整数-
iのビットがすべて0の場合,0の個数が得られる(=ビットサイズと等しい). - kindは
integer型のkindと同じ. -
iが配列の場合,resultはiと同じ次元,要素数の配列.
-
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'00010100', kind=int8)
print *, leadz(i) ! 3
end program main
trailz
整数型変数あるいは整数リテラル内の,1になっている最も下位のビットよりも下位にある0の数を返します.
書式
-
result = trailz(i)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
resultは整数-
iのビットがすべて0の場合,0の個数が得られる(=ビットサイズと等しい). - kindは
integer型のkindと同じ. -
iが配列の場合,resultはiと同じ次元,要素数の配列.
-
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'00010100', kind=int8)
print *, trailz(i) ! 2
end program main
popcnt
整数型変数,整数リテラル内の1となっているビットの数を返します.
書式
-
result = popcnt(i)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
resultは整数- kindは
integer型のkindと同じ. -
iが配列の場合,resultはiと同じ次元,要素数の配列.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'0101010', kind=int8)
print *, popcnt(i) ! 3
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'0111010', kind=int8)
print *, popcnt(i) ! 4
end program main
poppar
整数型変数,整数リテラル内の1となっているビットの数が奇数の場合に1,偶数の場合に0を返します.
書式
-
result = poppar(i)-
iは整数(1, 2, 4, 8バイト).-
iは配列でもよい.
-
-
resultは整数で,0または1.- kindは
integer型のkindと同じ.
- kindは
-
例
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'0101010', kind=int8)
print *, poppar(i) ! 1
end program main
program main
use, intrinsic :: iso_fortran_env
implicit none
integer(int8) :: i
i = int(B'0111010', kind=int8)
print *, poppar(i) ! 0
end program main