⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lmul.c

📁 一款收款机C源代码!因为是几年前的代码了
💻 C
字号:
/*
 * Module: lmul.c
 * Modified by: X.C.Zheng WeiHua
 * Modified on: Date:  03-8-11 14:02
 * Copyright(c) WeiHua Tech Ltd.
 */


#include "ecrsys.h"
#include "sysdata.h"
#include "data.h"
#include "ftype.h"
#include "mathes.h"
#include "stdlib.h"
#include "string.h"

/*
 * Get a long value which is based on 10 for given input
 */
dword getLong(BYTE cnt)
{
   BYTE i;
   dword lltmp = 1L;

   if(cnt==0)
   	return(1L);
   for (i = 0; i < cnt; i++)
      lltmp *= 10;

   return(lltmp);
}

/* llx * lly -> llx */
/* return : NOTOK: Overflow, OK: normal */
byte DL_Mul(DoubleLong *llx, long lly, BYTE dots)
{
   BYTE	i;
   BYTE	sign;
   word	op[8] = {0, 0, 0, 0, 0, 0, 0, 0};
   word	*ip;
   dword	*lltmp, lm1, lm2;
   dword	dltmp;

	if(lly == MIN_SIGNED_LONG)
	{
		/* Remain */
	}
	if(lly == 0)							/* The result is 0 */
	{
		DL_Clr(llx);
		return (OK);
	}
   else if(lly < 0)
   {
      lly	=	-lly;
      sign	=	NEGATIVE;
   }
   else
      sign	=	POSITIVE;

   ip = (word *)llx;

   for (i = 0; i < 4; i++)
   {
      lltmp = (dword *)&op[i];
      lm1 = ((dword)ip[i]) & 0x0000FFFF;
      lm2 = lly & 0x0000FFFF;
      dltmp = lm1 * lm2 + (*lltmp);
      if((*lltmp) > dltmp)				/* When overflow, the next second cell add one */
      	op[i+2] ++;
      *lltmp = dltmp;
      lltmp = (dword *)&op[i+1];
      lm2 = (lly >> 16) & 0x0000FFFF;
      dltmp = lm1 * lm2 + (*lltmp);
      if((*lltmp) > dltmp)				/* When overflow, the next second cell add one */
      	op[i+3] ++;
      *lltmp = dltmp;
   }

   lltmp = (dword *)&op[0];
   llx->lowlong = *lltmp;
   lltmp = (dword *)&op[2];
   llx->highlong = *lltmp;
   llx->dots += dots;
   if(llx->sign==sign)
      llx->sign=POSITIVE;
   else
      llx->sign=NEGATIVE;

	lltmp = (dword *)&op[4];
	if((*lltmp) != 0)						/* This case only occur in the calculation mode,
													indicate the result is too big.
													When this case occur, adjust it to the right format */
	{
		if(DL_Mul_Adj(llx,(*lltmp)) == NG)
			return (NOTOK);
	}

	return (OK);
}

/* llx / lly -> llx */
/* if flag == 0, do not adujst it */
/* sysdots: decimal position */
byte DL_Div(DoubleLong *llx, long lly, BYTE dots, BYTE flag, BYTE sysdots)
{
   byte 	i,j;
   BYTE 	sign;
   dword ltmp1;
   dword ltmp2;
   dword ltmp3;

   ltmp1 = 0L;

	if(lly == MIN_SIGNED_LONG)
	{
		/* Remain */
	}
	if(lly == 0)
		return (NOTOK);
   else if(lly < 0)
   {
      lly=-lly;
      sign=NEGATIVE;
   }
   else
      sign=POSITIVE;

   if(flag)
   {
     	if((llx->dots - dots < sysdots+1 )||(llx->dots<dots))
      {
        	if(DL_Mul(llx, getLong(sysdots + 1 - llx->dots + dots),0) == NOTOK)
        		return (NOTOK);        
        	llx->dots += sysdots + 1 - llx->dots + dots;
      }
   }
   else
   {
   	if(llx->dots < dots)
   	if(DL_Mul(llx, getLong(dots - llx->dots), dots - llx->dots) == NOTOK)
   		return (NOTOK);
   }

   for(i = 0; i < 64; i++)
   {
      ltmp2 = 0L;     

      if(llx->lowlong & 0x80000000)  ltmp2 = 1L;
      llx->lowlong <<= 1;
lD1:
      ltmp3 = 0L;
      if(llx->highlong & 0x80000000) 
         ltmp3 = 1L;
      llx->highlong <<= 1;
      llx->highlong += ltmp2;
lD3:
      ltmp1 <<= 1;
      ltmp1 += ltmp3;
      if (ltmp1 >= lly)
      {
         ltmp1 -= lly;
         llx->lowlong += 1L;
      }
   }/* end for */

   llx->dots -= dots;
   if(llx->sign==sign)
      llx->sign=POSITIVE;
   else
      llx->sign=NEGATIVE;

   return (OK);
}

/* Translate Double long interger to long interger */
long DL2L(DoubleLong *dl, BYTE dots, BYTE round)
{
   dword  dltmp;
   DoubleLong ll;

   ll.highlong= dl->highlong ;
   ll.lowlong=dl->lowlong ;
   ll.dots=dl->dots ;

   while((ll.dots<dots+1))
   {
      DL_Mul(&ll, 10, 0);
      ll.dots++;
   }
   while((ll.dots>dots+1))
   {
      DL_Div(&ll, 10, 0, 0,sysflag->sysdots);
      ll.dots--;
   }
   if(round==0)    /** round==0 **/
      dltmp=5;
   else if(round==2)  /** round off==2 **/
      dltmp=0;
   else if(round==1)  /** round up==1 **/
      dltmp=9;
   else
   	return -1L;
   dltmp = dltmp + ll.lowlong;
   if(ll.lowlong>dltmp)
      ll.highlong++;
   ll.lowlong = dltmp;
   DL_Div(&ll,10,0, 0, sysflag->sysdots);
   ll.dots--;
   dl->highlong = ll.highlong ;
   dl->lowlong  = ll.lowlong  ;
   dl->dots     = ll.dots     ;

   if ((ll.highlong != 0 )|| (ll.lowlong&0x80000000))
   /* overflow occurs */
      return(-1L);
/*	if(ll.sign==NEGATIVE)
   	return(-ll.lowlong);
   else*/
   	return(ll.lowlong);
}

/* Translate long interger to double long interger */
void L2DL(long l, DoubleLong *ll, BYTE dots)
{
	if(l == MIN_SIGNED_LONG)
	{
		ll->highlong = 1;
		ll->lowlong = 0;
		ll->dots = dots;
		ll->sign = NEGATIVE;
		return;
	}
   ll->highlong = 0L;
   if(l<0)
   {
      ll->lowlong = (-1)*l;
      ll->sign=NEGATIVE;
   }
   else
   {
      ll->lowlong = l;
      ll->sign = POSITIVE;
   }
   ll->dots = dots;
}


/* llx(signed) + lly(signed) -> llx(signed) */
/* return: NOTOK: the result has overflow, OK: normal */
byte DL_Add(DoubleLong *llx, long lly, BYTE dots)
{
	DoubleLong ll;
	
	if(lly == MIN_SIGNED_LONG)
	{
		/* Remain */
	}
	L2DL(lly,&ll,dots);				/* Adjust it to the double long */
	if(DL_Add2(llx, ll) == NOTOK)
		return (NOTOK);
	return (OK);
}

/* llx(signed) + lly(signed) -> llx(signed) */
/* return: NOTOK: the result has overflow, OK: normal */
byte DL_Add2(DoubleLong *llx, DoubleLong ll)
{
	dword dltmp;
	
	DL_Add_Adj(llx, &ll);			/* Adjust to the same dots */

	if(llx->sign == ll.sign)		/* The same sign */
	{
		dltmp = llx->lowlong + ll.lowlong;
		if(ll.lowlong > dltmp)		/* Carry */
		{
			if(llx->highlong == 0xFFFFFFFF)
				return (NOTOK);		/* Overflow */
			else
				ll.highlong ++;
		}
		llx->lowlong = dltmp;
		dltmp = llx->highlong + ll.highlong;
		if(ll.highlong > dltmp)
			return (NOTOK);			/* Overflow */
		llx->highlong = dltmp;
	}
	else									/* The different sign */
	{
		dltmp = llx->lowlong - ll.lowlong;
		if(llx->lowlong < dltmp)	/* Borrow */
		{
			if(llx->highlong == 0)
			{
				llx->sign = (llx->sign == POSITIVE)?NEGATIVE:POSITIVE;		/* Reverse the sign */
				llx->highlong = 0xFFFFFFFF;
			}
			else
				llx->highlong --;
		}
		llx->lowlong = dltmp;
		dltmp = llx->highlong - ll.highlong;
		if(llx->highlong < dltmp)	/* Borrow */
			llx->sign = (llx->sign == POSITIVE)?NEGATIVE:POSITIVE;			/* Reverse the sign */
		llx->highlong = dltmp;

		if(llx->sign == ll.sign)		/* When the sign is changed, adjust to the right format */
		{
			llx->highlong ^= 0xFFFFFFFF;
			llx->lowlong  ^= 0xFFFFFFFF;
			DL_Add(llx, (llx->sign == POSITIVE)?1:-1, llx->dots);
		}
	}
	if((llx->highlong == 0) && (llx->lowlong == 0))
	{
//		llx->dots = 0;						/* Can't clear the dots, for the function DL_Exact_Div must remain the dots */
		llx->sign = POSITIVE;
	}

	return (OK);
}

/* llx <- lly */
void DL_Eva(DoubleLong *llx, DoubleLong *lly)
{
	llx->lowlong = lly->lowlong;
	llx->highlong = lly->highlong;
	llx->dots = lly->dots;
	llx->sign = lly->sign;
}


/* Adjust the too big data
	The adjust expressions:
		primal_data = highdata*2^64 + highlong|lowlong;
			 divisor = 10^(length(highdata));		// also can larger than it.
		adjust_data = primal_data / divisor;(Contain dots)
						= (highdata*2^64 + highlong|lowlong)/divisor;
						= (highlong|lowlong)/divisor + (highdata*2^64)/divisor;		// may be smaller than the formar expressions, but can ignore
						= (highlong|lowlong)/divisor + highdata*(2^64)/divisor;
																			 --------------
																					|___________________ new_data
			new_data = highdata*(0x10000000000000000/divisor + 0x10000000000000000%divisor/divisor);
										---------------------------	---------------------------
													 	|											|_________________residue;
													 	|__________________________________________________quotient;
			quotient = 0x10000000000000000/divisor;
						= 0xFFFFFFFFFFFFFFFF/divisor;
			residue	= 0x10000000000000000 - quotient*divisor;
						= 0xFFFFFFFFFFFFFFFF - quotient*divisor + 1;
						= 0xFFFFFFFF - (quotient*divisor).lowlong + 1;((quotieng*divisor).highlong = 0xFFFFFFFF)
		adjust_data = (highlong|lowlong)/divisor + highdata*quotient + highdata*residue/divisor;
*/
byte DL_Mul_Adj(DoubleLong *ll, dword highdata)
{
	BYTE i;
	dword tmp;
	dword divisor;
	dword residue;
	dword dltmp;
	DoubleLong dl;

	tmp = highdata;					/* Get this data */
	for(i = 0; tmp != 0; i ++)		/* Get this datas length */
		tmp /= 10;
	if(ll->dots < i)
		return (NG);
	divisor = getLong(i);							/* Get the divisor */

	dl.lowlong = 0xFFFFFFFF;
	dl.highlong = 0xFFFFFFFF;
	dl.sign = POSITIVE;
	dl.dots = 0;
	DL_Div(&dl, divisor, 0, 0, 0);				/* Get the quotient */
	DL_Mul(&dl, highdata, i);

	DL_Div(ll, divisor, i, 0, 0);

	dltmp = ll->lowlong + dl.lowlong;
	if(ll->lowlong > dltmp)
		ll->highlong ++;
	ll->lowlong = dltmp;
	ll->highlong += dl.highlong;

	dl.lowlong = 0xFFFFFFFF;
	dl.highlong = 0xFFFFFFFF;
	dl.sign = POSITIVE;
	dl.dots = 0;
	DL_Div(&dl, divisor, 0, 0, 0);
	DL_Mul(&dl,divisor, 0);
	residue = 0xFFFFFFFF - dl.lowlong + 1;		/* Get the residue */
	L2DL(residue, &dl, 0);
	DL_Mul(&dl, highdata, 0);
	DL_Div(&dl, divisor, 0, 0, 0);

	dltmp = ll->lowlong + dl.lowlong;
	if(ll->lowlong > dltmp)
		ll->highlong ++;
	ll->lowlong = dltmp;
	ll->highlong += dl.highlong;

	return (OK);
}


void DL_Clr(DoubleLong *ll)
{
	ll->highlong = 0;
	ll->lowlong = 0;
	ll->dots = 0;
	ll->sign = POSITIVE;
}


/* llx / lly -> llx, used for the exact result */
byte DL_Exact_Div(DoubleLong *llx, long lly, BYTE dots)
{
	byte sign1, sign2;		/* Store the sign of the llx and lly */
	DoubleLong dl,dl1;
	long residue;
	long quotient;
	long divisor;

	if(llx->dots < dots)
	{
		if(DL_Mul(llx, getLong(dots), 0) == NOTOK)
			return (NOTOK);
		dots = 0;
	}

	sign1 = llx->sign;
	llx->sign = POSITIVE;
	if(lly > 0)
		sign2 = POSITIVE;
	else
		sign2 = NEGATIVE;
	lly = labs(lly);

	DL_Eva(&dl, llx);
	if(DL_Div(&dl, lly, dots, 0, 0) == NOTOK)
		return (NOTOK);
	DL_Mul(&dl, lly, dots);
	residue = llx->lowlong - dl.lowlong;
	DL_Div(llx, lly, dots, 0, 0);

	divisor = lly;
	while(residue != 0)
	{
		if((llx->highlong > (0xFFFFFFFF/0x64)) || (llx->dots > 10))		/* The result is enough */
			break;
		L2DL(residue, &dl, 0);
		DL_Mul(&dl, 10, 0);
		DL_Eva(&dl1,&dl);
		DL_Div(&dl, divisor, 0, 0, 0);
		quotient = dl.lowlong;			/* Get the quotient */
		DL_Mul(llx, 10, 1);
		DL_Add(llx, quotient, llx->dots);			/* Add the quotient to the result */
		DL_Mul(&dl, divisor, 0);
		residue = dl1.lowlong - dl.lowlong;			/* Get the new residue */
	}

	llx->sign = (sign1^sign2)?NEGATIVE:POSITIVE;
	return (OK);
}


/* Adjust the two data llx and lly the same dots */
void DL_Add_Adj(DoubleLong *llx, DoubleLong *lly)
{
	if(llx->dots < lly->dots)
	{
		while((llx->highlong < 0xFFFFFFFF/0x0A) && (llx->dots < lly->dots))
			DL_Mul(llx, 10, 1);
		if(llx->dots < lly->dots)
		{
			while(llx->dots < lly->dots)
				DL_Div(lly, 10, 1, 0, 0);
		}
	}
	else if(llx->dots > lly->dots)
	{
		while((lly->highlong < 0xFFFFFFFF/0x0A) && (lly->dots < llx->dots))
			DL_Mul(lly, 10, 1);
		if(lly->dots < llx->dots)
		{
			while(lly->dots < llx->dots)
				DL_Div(llx, 10, 1, 0, 0);
		}
	}
}


#define MAX_BUF_LEN2			23
/* Transform the DoubleLong format to the ASCII format */
void DLong2Asc(DoubleLong *ll, char *obj_str, byte Adj_Len)
{
	char posi;
	char tmp_str[MAX_BUF_LEN2];
	byte i, j;
	byte cntr;
	byte dots;
	DoubleLong ll_tmp;
	DoubleLong ll_tmp1;

	j = 0;
	dots = ll->dots;
	posi = MAX_BUF_LEN2 - 1;
	cntr = dots;
	DL_Eva(&ll_tmp, ll);
	ll_tmp.sign = POSITIVE;
	while((ll_tmp.highlong != 0) || (ll_tmp.lowlong != 0))
	{
		DL_Eva(&ll_tmp1, &ll_tmp);					/* ll_tmp%10 -->> i */
		DL_Div(&ll_tmp1, 10, 0, 0, 0);
		DL_Mul(&ll_tmp1, 10, 0);
		ll_tmp1.sign = NEGATIVE;
		DL_Add2(&ll_tmp1, ll_tmp);
		i = ll_tmp1.lowlong;

		tmp_str[posi --] = i + '0';
		cntr --;
		if(cntr == 0)
			tmp_str[posi --] = '.';
		DL_Div(&ll_tmp, 10, 0, 0, 0);
		j ++;
	}

	if(j <= dots)
	{
		while(cntr)
		{
			tmp_str[posi --] = '0';
			cntr --;
		}
		if(j < dots)
			tmp_str[posi --] = '.';
		tmp_str[posi --] = '0';
	}

	if(dots != 0)
		cntr = 1;
	else
		cntr = 0;
	if((MAX_BUF_LEN2 - 1 - posi) < (Adj_Len + cntr))
	{
		j = (Adj_Len + cntr) - (MAX_BUF_LEN2 - 1 - posi);
		for(i = 0; i < j; i ++)
		{
			tmp_str[posi --] = '0';
		}
	}
	if(ll->sign == NEGATIVE)
		tmp_str[posi --] = '-';

	posi ++;
	memcpy(obj_str, tmp_str+posi, MAX_BUF_LEN2-posi);
	obj_str[MAX_BUF_LEN2-posi] = 0;
}
#undef MAX_BUF_LEN2		/* Release the define */

/*----------------------------------------------------------------------*
 *				Transform the double long format to the bcd format
 *
 *		bcdstr: Compressed BCD code, the high cell store the sign.
 *		Max_Len: The max length of the bcdstr, 4 bits equal 1 lenth;
 *
 *		Note: Take no account of the decimal dots.
 *----------------------------------------------------------------------*/
void DLong2Bcd(DoubleLong *ll, byte *bcdstr, byte Max_Len)
{
	byte i;
	byte posi;
	DoubleLong ll_tmp;
	DoubleLong ll_tmp1;

	if(Max_Len == 0)
		return;

	posi = 0;
	DL_Eva(&ll_tmp, ll);
	ll_tmp.sign = POSITIVE;
	while(Max_Len > 1)
	{
		DL_Eva(&ll_tmp1, &ll_tmp);					/* ll_tmp%10 -->> i */
		DL_Div(&ll_tmp1, 10, 0, 0, 0);
		DL_Mul(&ll_tmp1, 10, 0);
		ll_tmp1.sign = NEGATIVE;
		DL_Add2(&ll_tmp1, ll_tmp);
		i = ll_tmp1.lowlong;

		Store_CBCD_Cell(i, bcdstr, posi);
		posi ++;
		if(posi == Max_Len - 1)
			break;
		DL_Div(&ll_tmp, 10, 0, 0, 0);
	}
	if(ll->sign == NEGATIVE)
		i = 1;
	else // ll->sign == POSITIVE
		i = 0;
	Store_CBCD_Cell(i, bcdstr, posi);
	posi ++;
}

/*----------------------------------------------------------------------*
 *				Transform the bcd format to the double long format
 *
 *		bcdstr: Compressed BCD code, the high cell is the sign.
 *		Max_Len: The max length of the bcdstr, 4 bits equal 1 length;
 *		sign_flag: 1: Store the sign
 *					  0: Not store the sign
 *
 *		Note: Take no account of the decimal dots.
 *----------------------------------------------------------------------*/
void Bcd2DLong(byte *bcdstr, DoubleLong *ll, byte Max_Len)
{
	/* Reserved */
}

/*  Rev 1.0   30 Dec. 1996. LHM.
 *   mathmatic function and tax computation
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -