IDL/Programming

COMPILE_OPT 선언문의 이해 [2]

이상우_IDL 2025. 7. 24. 16:04
728x90

IDL에서 몇가지 기본적인 설정들을 인위적으로 변경 및 강제하는 역할을 하는데 사용되는 COMPILE_OPT 선언문에 관하여 소개하는 게시물을 지난번에 올린 바 있습니다. 이 게시물에서는 COMPILE_OPT에서 설정 가능한 인자들 중 사용 빈도가 비교적 많은 DEFINT32, STRICTARR 인자들에 관하여 중점적으로 살펴보았습니다. 물론 설정 가능한 인자들은 그 외에도 더 있습니다. 그래서 나머지 인자들 중에서 주목해볼만한 몇가지를 더 소개해보기로 합니다.

 

< FLOAT64 >

 

먼저 FLOAT64라는 인자부터 보겠습니다. 일단 이러한 인자를 사용하는 방식은 다음과 같습니다.

 

COMPILE_OPT FLOAT64

 

이러한 문구를 프로시저나 함수 프로그램의 맨 앞부분에 명시할 수도 있고 또는 그냥 IDL의 커맨드 입력창에서 사용할 수도 있습니다. 어쨌든 이러한 선언문이 명시된 이후부터는 실수형의 값을 무조건 8바이트(64비트)의 2배 정밀도 실수형(Double Precision)으로 인식합니다. 원래 IDL에서 실수형 값을 정의하면 일단은 4바이트(32비트)의 일반 실수형로 인식되는 것이 기본적인 설정인데, 이러한 기본 설정 자체를 아예 변경하는 것입니다. 예를 들어서 다음과 같은 프로그램을 봅시다.

 

PRO test_compile_opt

a = 7.3

b = 5.8d

HELP, a, b

END

 

이와 같은 프로그램을 실행하면 출력된 결과는 다음과 같을 것입니다.

 

A               FLOAT     =       7.30000
B               DOUBLE    =        5.8000000

 

즉 이와 같이 변수 a는 일반 실수형이 되고 b는 2배 정밀도 실수형이 됩니다. 원래는 이게 정상입니다. 그런데 다음과 같이 COMPILE_OPT FLOAT64 선언문을 서두에 명시하고 프로그램을 다시 실행해봅시다.

 

PRO test_compile_opt

COMPILE_OPT FLOAT64

a = 7.3

b = 5.8d

HELP, a, b

END

 

그러면 출력 결과는 다음과 같습니다.

 

A               DOUBLE    =        7.3000000
B               DOUBLE    =        5.8000000

 

이와 같이 변수 a 역시 무조건 2배 정밀도 실수형으로 정의됩니다. 따라서 프로그램 내에서 정의되는 실수형 값들이 무조건 2배 정밀도 실수형이 되도록 하고자 한다면 이와 같이 COMPILE_OPT FLOAT64 선언문을 사용하면 됩니다.

 

< LOGICAL_PREDICATE >

 

LOGICAL_PREDICATE 인자는 논리값을 인지하는 방식을 제어하는 역할을 합니다. 일단 이러한 인자를 사용하는 사용하는 방식은 다음과 같습니다.

 

COMPILE_OPT LOGICAL_PREDICATE

 

이와 같은 선언문이 실행된 이후부터는 논리값을 인지하는데 있어서 0 또는 null이 아닌 값을 무조건 참(True)으로 간주하고 0 또는 null 값을 무조건 거짓(False)로 간주합니다. 특히 정수의 경우로 한정하여 본다면, 그 값을 이진수로 변환했을 때 가장 낮은 비트(LSB, Least Significant Bit)의 값이 1이면 참 그리고 0이면 거짓으로 간주되는 것이 원래는 기본입니다. 하지만 LOGICAL_PREDICATE 설정을 하면 LSB 여부에 상관없이 그냥 0이 아니기만 하면 참 그리고 0이면 거짓으로 간주됩니다. 이해를 돕기 위하여 아래와 같은 예제 프로그램을 봅시다.

 

PRO test_compile_opt

IF 4 THEN PRINT, 'value 4'
IF 3 THEN PRINT, 'value 3'
IF 2 THEN PRINT, 'value 2'
IF 1 THEN PRINT, 'value 1'
IF 0 THEN PRINT, 'value 0'
IF -1 THEN PRINT, 'value -1'
IF -2 THEN PRINT, 'value -2'
IF -3 THEN PRINT, 'value -3'
IF -4 THEN PRINT, 'value -4'

END

 

이와 같이 IF 구문의 조건 부분에 다양한 정수형 값들을 투입하여 테스트하는 프로그램을 실행하면 결과는 다음과 같습니다.

 

value 3
value 1
value -1
value -3

 

위의 프로그램에서는 총 9개의 IF 구문들이 존재하는데 실제로 출력이 된 경우들은 총 4건에 불과합니다. 즉 4건만 참으로 인식되고 나머지 5건은 거짓으로 인식되었다는 의미입니다. 이것은 IF 바로 뒤에 명시된 정수형 값을 이진수로 변환했을 때 LSB가 1이냐 아니면 0이냐 여부에 따라서 IF 구문이 작동했기 때문입니다. 즉 LSB가 1이 되는 3, 1, -1, 3 케이스들은 참으로 인식되어서 THEN 뒤의 PRINT 명령이 실행된 반면, LSB가 0이 되는 나머지 케이스들은 거짓으로 인식되어서 THEN 뒤의 PRINT 명령이 실행되지 않은 것입니다. 그러면 이번에는 다음과 같이 COMPILE_OPT LOGICAL_PREDICATE 선언문을 추가하고 프로그램을 다시 실행해봅시다.

 

PRO test_compile_opt

COMPILE_OPT LOGICAL_PREDICATE
IF 4 THEN PRINT, 'value 4'
IF 3 THEN PRINT, 'value 3'
IF 2 THEN PRINT, 'value 2'
IF 1 THEN PRINT, 'value 1'
IF 0 THEN PRINT, 'value 0'
IF -1 THEN PRINT, 'value -1'
IF -2 THEN PRINT, 'value -2'
IF -3 THEN PRINT, 'value -3'
IF -4 THEN PRINT, 'value -4'
END

 

그러면 그 결과는 다음과 같습니다.

 

value 4
value 3
value 2
value 1
value -1
value -2
value -3
value -4

 

즉 이제는 IF 뒤에 명시된 정수형 값에 대하여 LSB를 따지지 않고 그냥 0이 아니면 참 그리고 0이면 거짓으로 판단하게 되기 때문에 이러한 결과가 나왔다고 보면 됩니다.

 

< STRICTARRSUBS >

 

STRICTARRSUBS 인자는 배열을 배열로 인덱싱하는데 있어서 허용되는 기본 설정인 인덱스 클리핑(Index Clipping)을 허용하지않도록 설정하는 역할을 합니다. 일단 이러한 인자를 사용하는 사용하는 방식은 다음과 같습니다.

COMPILE_OPT STRICTARRSUBS

우리가 배열의 값들에 접근하기 위하여 또 다른 배열을 사용하는 경우가 종종 있습니다. 예를 들면 a라는 배열에 접근하는데 있어서 접근용 인덱스들로 구성된 b라는 배열을 정의하고 a[b]와 같은 방식으로 인덱싱을 하는 경우입니다. 그런데 배열 b를 구성하는 인덱스 값들 중에서 배열 a의 인덱스 범위를 벗어나는 값이 있을 경우를 가정해보겠습다. 이러한 예제로서 다음과 같은 프로그램을 살펴봅시다.

 

PRO test_compile_opt

a = [82, 66, 77, 48, 51, 29]
b = [0, 3, 7, 4]
c = a[b]
PRINT, c

END

 

여기서 배열 a는 6개의 값들로 구성되어 있습니다. 그리고 배열 a의 값들에 접근하기 위하여 인덱스 값들로 구성된 배열 b를 정의하고 a[b]와 같은 방식으로 활용하였습니다. 그런데 배열 b를 구성하는 인덱스 값들을 잘 보면 7이라는 값이 보입니다. 사실 이 7이라는 값은 유효한 인덱스가 아닙니다. 왜냐하면 배열 a는 6개의 값들로 구성되어 있기 때문에 유효 인덱스의 범위는 0~5가 됩니다. 그런데 위와 같은 상태로 프로그램을 실행하면 에러가 발생하지 않고 그냥 진행이 됩니다. 실제로 IDL은 이러한 경우에는 유효하지 않은 인덱스 값을 유효한 인덱스 값으로 클리핑(Clipping) 처리를 하고 그냥 넘어가는 것이 기본입니다. 즉 실제로 이 프로그램을 실행한 결과는 다음과 같습니다.

 

      82      48      29      51

 

즉 여기서는 인덱스 7이 그냥 5로 간주되어 진행된 것입니다. 그런데 이와 같이 IDL이 알아서 인덱스 클리핑(Index Clipping)을 하는 것이 마음에 들지 않을 수 있습니다. 즉 이러한 상황에서 에러가 발생하도록 하는 것이 더 바람직하다고 판단되는 경우입니다. 그럴 때 바로 COMPILE_OPT STRICTARRSUBS 선언문이 필요합니다. 그러면 이번에는 다음과 같이 프로그램 내에 이러한 문구를 추가해봅시다.

 

PRO test_compile_opt
COMPILE_OPT STRICTARRSUBS
a = [82, 66, 77, 48, 51, 29]
b = [0, 3, 7, 4]
c = a[b]
PRINT, c
END

 

이러한 상태에서 프로그램을 다시 실행해보면 결과는 다음과 같습니다.

 

% Array used to subscript array contains out of range subscript: A.
% Execution halted at: TEST_COMPILE_OPT

 

이와 같이 유효하지 않은 인덱스가 사용된 것을 이제는 에러로 간주하게 됩니다. 따라서 인덱스 클리핑이라는 기본적인 설정을 무시하고 좀 더 깐깐하게 처리되도록 하려면 이러한 설정을 사용하는 것이 필요할 수도 있을 것입니다.

 

그리고 지난 회차에서도 언급했듯이 IDL2라는 인자를 사용하면 DEFINT32, STRICTARR 인자들을 함께 사용하는 것과 동일한 효력을 갖습니다. 즉

 

COMPILE_OPT IDL2

 

이 문구는 다음 문구와 동일한 효력을 갖습니다.

 

COMPILE_OPT DEFINT32, STRICTARR

 

그런데 IDL 8.9 버전에서 IDL3이라는 인자가 새로 추가되었습니다. 이 인자를 사용하면 DEFINT32, FLOAT64, LOGICAL_PREDICATE, STRICTARR 인자들을 한꺼번에 사용하는 것과 동일한 효력을 갖습니다. 즉

 

COMPILE_OPT IDL3

 

이 문구는 다음 문구와 동일한 효력을 갖습니다.

 

COMPILE_OPT DEFINT32, FLOAT64, LOGICAL_PREDICATE, STRICTARR

 

COMPILE_OPT 선언문에는 이외에도 지원되는 인자들이 더 있지만 일단 이 정도까지 정리해보기로 합니다. 더 자세한 내용은 IDL 도움말에서 이 명령에 관한 섹션을 참조하시면 됩니다.

 

 

* 이 글이 도움이 되었다면 게시물에 대하여 공감 버튼(하트 모양) 클릭 및 블로그 구독도 해주시면 더 큰 힘이 됩니다. 감사합니다.

LIST