암호화프로그래밍/(Old)C-BIGINT

007. 증가(increse)

산을좋아한라쯔 2013. 7. 29. 13:34
반응형

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