부호 없는 정수
부호 없는 정수
Fortran을 쓰다 보면 부호 없는 정수(unsigned integer)가 없어서 아쉬운 순간이 있어요. C의 unsigned와 비슷한 타입이 필요한데 표준 Fortran에는 없는 거죠. GNU Fortran은 -funsigned 옵션으로 이 공백을 채워 줘요. 어떤 타입이고 어떻게 쓰는지 함께 살펴볼게요.
본문
-funsigned 옵션을 주면 GNU Fortran이 J3/24-116 규격에 따라 부호 없는 정수를 지원해요. 데이터 타입 이름은 UNSIGNED이에요. n비트 부호 없는 타입은 2**n을 법(modulo)으로 하는 정수 연산을 구현하며, C의 unsigned 타입에 비교할 수 있어요.
이 타입은 다른 Fortran 데이터 타입처럼 KIND 번호를 가지며, SELECTED_UNSIGNED_KIND 함수로 선택할 수 있어요.
UNSIGNED와 다른 타입 사이의 혼합 연산·비교·대입은 명시적 변환을 통해서만 가능해요. UNSIGNED에서 다른 타입으로의 변환은 INT나 REAL 같은 타입 변환 함수로 하고, 반대로 다른 타입에서 UNSIGNED로는 UINT로 변환해요. 부호 없는 변수는 DO 루프의 인덱스 변수나 배열 인덱스로는 쓸 수 없어요.
부호 없는 수는 접미사로 u를 붙이고, 선택적으로 밑줄로 구분된 KIND 번호가 뒤따라요. 입출력은 I, B, O, Z 설명자와 비포맷 I/O로 할 수 있어요. gfortran으로 구현된 부호 없는 정수는 flang과 호환돼요.
작고 다소 억지스러운 예제 하나를 볼게요.
program main
use iso_fortran_env, only : uint64
unsigned(kind=uint64) :: v
v = huge(v) - 32u_uint64
print *,v
end program main
이 코드는 18446744073709551583을 출력해요. uint64는 64비트 부호 없는 타입이니, 최댓값에서 32u_uint64를 뺀 값이 그대로 나오는 거예요.
산술 연산은 부호 없는 정수에 대해서도 동작하며, 지수 연산도 포함돼요. J3/24-116.txt의 확장으로서, -pedantic이 적용되지 않는 한 부호 없는 정수에 단항 마이너스와 지수 연산이 허용돼요.
내장 프로시저에서 부호 없는 인자는 보통 처리할 데이터 인자로 허용돼요. 이는 REAL 인자를 쓰는 방식과 유사해요. 그리고 부호 없는 값은 DO 루프의 인덱스 변수와 배열 인덱스로는 금지돼요.
부호 없는 수는 목록지정(list-directed), 포맷, 비포맷 I/O로 읽고 쓸 수 있어요. 포맷 I/O에서는 B, I, O, Z 설명자가 유효해요. -pedantic에서는 음수 값이나 오버플로가 되는 값은 거부돼요.
SELECT CASE는 부호 없는 정수를 지원해요.
UNSIGNED 인자를 받는 내장 함수로는 많은 비트 연산·배열 함수들이 있어요. 몇 가지를 꼽으면 BGE, BGT, BIT_SIZE, BLE, BLT, CMPLX, CSHIFT, DIGITS, DOT_PRODUCT, DSHIFTL, DSHIFTR, EOSHIFT, FINDLOC, HUGE, IALL, IAND, IANY, IBCLR, IBITS, IBSET, IEOR, INT, IOR, IPARITY, ISHFT, ISHFTC, MATMUL, MAX, MAXLOC, MAXVAL, MERGE, MERGE_BITS, MIN, MINLOC, MINVAL, MOD, MODULO, MVBITS, NOT, OUT_OF_RANGE, PRODUCT, RANDOM_NUMBER, RANGE, REAL, SHIFTA, SHIFTL, SHIFTR, SUM, TRANSPOSE, TRANSFER 등이 있어요.
-funsigned로 활성화되는 내장 함수는 UINT, UMASKL, UMASKR, SELECTED_UNSIGNED_KIND이에요. 그리고 ISO_C_BINDING 모듈에는 c_unsigned, c_unsigned_short, c_unsigned_char, c_unsigned_long, c_unsigned_long_long, c_uintmax_t, c_uint8_t, c_uint16_t, c_uint32_t, c_uint64_t, c_uint128_t, c_uint_fast8_t, c_uint_fast16_t, c_uint_fast32_t, c_uint_fast64_t, c_uint_fast128_t, c_uint_least8_t, c_uint_least16_t, c_uint_least32_t, c_uint_least64_t, c_uint_least128_t 상수가 추가돼요. ISO_FORTRAN_ENV 모듈에는 uint8, uint16, uint32, uint64 상수가 추가돼요.
더 알아보기
-funsigned는 gfortran의 비표준 확장이니, 꼭 필요한 경우에만 켜는 것이 좋아요.- 기본적으로 표준 Fortran에는 부호 없는 정수 타입이 없어요. 이 확장은 J3 표준화 제안(J3/24-116)을 반영한 구현이에요.
- C와의 상호 운용에서 부호 없는 타입이 필요하다면,
ISO_C_BINDING모듈의c_uint*상수를 활용하는 방법도 함께 보면 좋아요.