2.2 증가(increse)
1만큼 증가 시키는 것을 구현해보자.
1 증가하는 것은, 앞에서 작성한 add함수를 써도 될 것이다. 즉, increse(A) = add(A,1,A)
(마찬가지로 1 감소하는 것은 decrese함수를 나중에 구현할 텐데, 이것도 subtract함수를 써도 되긴 한다.)
그러나, 1증가/감소는 빈번하게 일어나는 연산이고 이것을 add/subtract로 구현할 수 도 당연히 있으나, 단순히 1을 증가/감소 시키는 것이기에 전용함수를 만든다면 보다 효율적일 수 있겠다.
먼저 1 증가 시키는 함수를 만들어 보자. (1감소하는 decrese함수는 2.4에서 구현할 것임)
/**************************************************************************
1을 더함
Input: @A
Output: @A = 1을 더한 값. A = A + 1
Returns:
OK : no error
E_Overflow: Overflow. if larger than MAX_INT_LEN(=128. in case of INT is u32)
***************************************************************************/
int increse(BIGINT A){
INT *a, *ae;
DINT carry = BASE;
//01. A에 대한 포인터얻기
a = A + 1;
ae = A + SIZE(A);
add와 달리 1개 인자만 받아서, 그 BIGINT값을 1 증가 시킨다.
*a, *ae는 BIGINT A의 값을 따라가기 위한 포인터
carry는 add함수와 달리 DINT로 선언했음에 유의. add에서 계산 중간값을 저장하기 위해 사용되었던 역할까지 담당해야하므로 INT의 두 배의 DINT사용.
//02. if(A == zero) if(a > ae){ SET_SIZE(A,1); *a = (INT)1; return OK; }
만약 A가 zero이면, A[0]=0이다. 즉, SIZE(A)=0
따라서, a > ae 가 된다. (왜냐하면 a = A+1 = A의 주소 + 1 ae=A+SIZE(A)=A의 주소. 따라서, a>ae)
해서, (a <= ae) 일때 반복 수행되는 03번 루틴이 수행안된다. 그러므로, 이렇게 A가 zero인 경우에 따로 구현
zero를 1 증가시키면, 당연 1이다. 해서 A[0]=1 A[1]=1이 되게 해주고 함수 종료
//03. loop while((a <= ae) && (carry & BASE)){ *a = (INT)(carry = (DINT)*a + (DINT)1); a++; }
A가 zero가 아닌경우, 이 루틴으로 들어오게 되고, 처음에 가장 작은 자릿수값에 1을 증가시킨 후, 만약 carry가 발생했다면 (a <= ae)범위내에서 carry를 계속해서 위로 넘기면서 더한다.
*a의 값은 INT값이기에 (*a + 1)한 값이 carry가 발생하려면 *a의 값이 INT의 최대값일 때 뿐이다. 예를 들어 INT가 16비트의 경우라면 0xffff
0xffff에 1을 더하면 0x10000이 되고 이는 매크로로 정의한 BASE와 같다. 해서, carry가 발생했는지의 여부는 (carry & BASE)를 해보면 된다.
//04. if carry exist --> increse len if((a > ae) && (carry & BASE)){ if( (SIZE(A)+1) > MAX_INT_LEN){ *A = 0; //set zero }else{ *a = 1; SET_SIZE(A, (SIZE(A))+1); } }
A의 끝자리(가장 큰 자리)를 넘어서 carry가 발생한 경우이다. 이 경우에는 원래 A의 (최대자릿수+1)에 1을 넣고 A의 길이를 1 증가시켜 준다.
예를들어 A=Oxffff의 경우 A=0x01ffff가 된다.
//05. if(A == 양의 최대값) -> +1이면 overflow if((SIZE(A) == MAX_INT_LEN) && (A[MAX_INT_LEN] == ((INT)MAX_POSITIVE+1))){ ae = A+SIZE(A)-1; while((*ae == 0) && (--ae > A)); //모두 zero라면 if(ae == A) return E_Overflow; } return OK;
만약 A가 BIGINT가 표현할 수 있는 양의최대값이라면 +1을 더한 값을 표현할 수 없다. 이 경우는 overflow를 리턴한다.
전체 소스는 다음과 같다.
/************************************************************************** 1을 더함 Input: @A Output: (A+1) A에 1을 더한 값. A = A + 1 Returns: OK : no error E_Overflow: Overflow. if larger than MAX_INT_LEN(=128. in case of INT is u32) ***************************************************************************/ int increse(BIGINT A){ INT *a, *ae; DINT carry = BASE; //01. A에 대한 포인터얻기 a = A + 1; ae = A + SIZE(A); //02. if(A == zero) if(a > ae){ SET_SIZE(A,1); *a = (INT)1; return OK; } //03. loop while((a <= ae) && (carry & BASE)){ *a = (INT)(carry = (DINT)*a + (DINT)1); a++; } //04. if carry exist --> increse len if((a > ae) && (carry & BASE)){ if( (SIZE(A)+1) > MAX_INT_LEN){ *A = 0; //set zero }else{ *a = 1; SET_SIZE(A, (SIZE(A))+1); } } //05. if(A == 양의 최대값) -> +1이면 overflow if((SIZE(A) == MAX_INT_LEN) && (A[MAX_INT_LEN] == ((INT)MAX_POSITIVE+1))){ ae = A+SIZE(A)-1; while((*ae == 0) && (--ae > A)); //모두 zero라면 if(ae == A) return E_Overflow; } return OK; }
다음장에서는 이번 장에서 설명한 increse함수 및 앞 장에서 논의한 add에 대해 테스트하는 프로젝트를 만들 것인데, 앞으로 여러 함수들을 테스트할 때 계속해서 사용될 도우미 함수들도 다음 장에서 설명될 것이다.
'암호화프로그래밍 > (Old)C-BIGINT' 카테고리의 다른 글
009. 뺄셈(subtract) (0) | 2013.07.30 |
---|---|
008. 테스트: 덧셈, 증가 (0) | 2013.07.30 |
006. 덧셈(add) (0) | 2013.06.20 |
005. 큰 수에 대한 프로그래밍 (0) | 2013.06.19 |
004. 큰 수 (0) | 2013.06.19 |