Files correlati : gfm.dll Ricompilazione Demo : [ ] Commento : Modifiche per la compilazione Linux git-svn-id: svn://10.65.10.50/trunk@11079 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			386 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			386 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* DEC	*_CompoundAux(fun, nperi, nperd, intr, pv, pmt,	fv, begend, opt)
 | 
						|
 *
 | 
						|
 * ARGUMENT
 | 
						|
 *	int	fun, *nperi, begend, opt;
 | 
						|
 *	DEC	*nperd,	*intr, *pv, *pmt, *fv;
 | 
						|
 *
 | 
						|
 * DESCRIPTION
 | 
						|
 *	Given four variables involved in compound interest, solves for the
 | 
						|
 *  fifth one.	The variables are the number of	periods	nper, the percentage
 | 
						|
 *  interest rate per period intr, the present value pv, the periodic payment
 | 
						|
 *  pmt, and the future	value fv.  begend specifies whether payments take
 | 
						|
 *  place at the beginning or the end of each month, while opt tells which
 | 
						|
 *  variable to	solve for.
 | 
						|
 *	This auxillary function	does the work of CompoundInterest,
 | 
						|
 *  CompoundInterestSimple, CompoundInterestCompound,
 | 
						|
 *  and	AdvancePayment.
 | 
						|
 *
 | 
						|
 * SIDE	EFFECTS
 | 
						|
 *	Changes	value of unknown variable.
 | 
						|
 *
 | 
						|
 * RETURNS
 | 
						|
 *	In case	of success when	not solving for	nper, the result is returned.
 | 
						|
 *  If solving for nper	or if an error occurs, GM_NULL is returned.
 | 
						|
 *
 | 
						|
 * POSSIBLE ERRORS
 | 
						|
 *	GM_NULLPOINTER
 | 
						|
 *	GM_ARGVAL
 | 
						|
 *
 | 
						|
 *
 | 
						|
 *
 | 
						|
 * AUTHOR
 | 
						|
 *  Jared Levy
 | 
						|
 *   Copyright (C) 1988-1990 Greenleaf Software	Inc.  All rights reserved.
 | 
						|
 *
 | 
						|
 * ALGORITHM
 | 
						|
 *	Solve the following formula for	the unknown variable:
 | 
						|
 *  0=pv*alpha + (1+intr*begend)*pmt*[1-(1+intr)^-int(nper)]/intr +
 | 
						|
 *	 fv*(1+intr)^-int(nper)
 | 
						|
 *  where alpha=1 for no odd period,
 | 
						|
 *	  alpha=1+intr*frac(nper) for an odd period with simple	interest
 | 
						|
 *	  alpha=(1+intr)^frac(nper) for	an odd period with compound interest
 | 
						|
 *
 | 
						|
 *  If intr==0,	the function solves
 | 
						|
 *	0 = pv + nper *	pmt + fv
 | 
						|
 *  If nper==0,	the function solves
 | 
						|
 *	0 = pv * alpha + fv
 | 
						|
 *
 | 
						|
 *  The	equation can be	solved in closed form for any variable except intr,
 | 
						|
 *  which requires numerical methods.
 | 
						|
 *  The	variables used by this routine have the	following meanings:
 | 
						|
 *	fun:   1 if called by ComoundInterest, 2 if by CompoundInterestSimple,
 | 
						|
 *		3 if by	CompoundInterestCompound, and 0	if by AdvancePayment
 | 
						|
 *	nperi: integer number of periods if fun==1
 | 
						|
 *	nperd: DEC number of periods if	fun==2 or fun==3
 | 
						|
 *	intr:  interest	rate per period
 | 
						|
 *	pv:    present value
 | 
						|
 *	pmt:   period payment
 | 
						|
 *	fv:    future value (balloon payment)
 | 
						|
 *	begend:	GM_BEGIN if payments at	beginning of period, GM_END if at end
 | 
						|
 *		(or if fun==0, number of advanced payments ad)
 | 
						|
 *	opt:   variable	to solve for: GM_N, GM_PV, GM_INTR, GM_FV, GM_PMT
 | 
						|
 *
 | 
						|
 *	opi:   1 + intr
 | 
						|
 *	intper:	integer	part of	nper
 | 
						|
 *	fractper: fractional part of nper (if fun==2 or	fun==3)
 | 
						|
 *	opitmn:	(1 + intr) ^ -intper
 | 
						|
 *	mess: (1 + begend)[1 - (1 + intr) ^ -intper]/intr
 | 
						|
 *	alpha: 1 + intr	* fractper if fun==2, (1 + intr) ^ fractper if fun==3
 | 
						|
 *	pva:   pv * alpha
 | 
						|
 *	fvopi: fv * opitmn
 | 
						|
 *	pmtm:  pmt * mess
 | 
						|
 *	temp, temp2: temporary DEC's
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include "gm.h"
 | 
						|
#include "gmsystem.h"
 | 
						|
 | 
						|
DEC	*_CompoundAux(fun, nperi, nperd, intr, pv, pmt,	fv, begend, opt)
 | 
						|
int	fun, *nperi, begend, opt;
 | 
						|
DEC	*nperd,	*intr, *pv, *pmt, *fv;
 | 
						|
{
 | 
						|
	int	intper,	ad;
 | 
						|
	DEC	dopi, *opi=&dopi, dfractper, *fractper=&dfractper;
 | 
						|
	DEC	dmess, *mess=&dmess, dalpha, *alpha=&dalpha;
 | 
						|
	DEC	dpva, *pva=&dpva, dfvopi, *fvopi=&dfvopi;
 | 
						|
	DEC	dpmtm, *pmtm=&dpmtm, dopitmn, *opitmn=&dopitmn;
 | 
						|
	DEC	dtemp, *temp=&dtemp, dtemp2, *temp2=&dtemp2;
 | 
						|
	DEC	dnintr,	*nintr=&dnintr;
 | 
						|
	DEC	ddad, *dad=&ddad, dopitmna, *opitmna=&dopitmna;
 | 
						|
 | 
						|
 | 
						|
	if (!intr||!pv||!pmt||!fv||!nperd)  {
 | 
						|
		_MacErr(GM_NULLPOINTER);
 | 
						|
		return(GM_NULL);
 | 
						|
	}
 | 
						|
	if ((opt!=GM_I && _MacBad(intr)) || (opt!=GM_PV	&& _MacBad(pv))	||
 | 
						|
	    (opt!=GM_PMT && _MacBad(pmt)) || (opt!=GM_FV && _MacBad(fv))) {
 | 
						|
		    _MacErr(GM_INIT);
 | 
						|
		    return(GM_NULL);
 | 
						|
	    }
 | 
						|
 | 
						|
	if ((begend!=GM_BEGIN&&begend!=GM_END&&fun!=0)||
 | 
						|
		(opt!=GM_N&&opt!=GM_I&&opt!=GM_PV&&opt!=GM_PMT&&opt!=GM_FV)||
 | 
						|
		(opt!=GM_I&&CompareDecimal(intr,&decMinusHundred)!=1))	{
 | 
						|
		_MacErr(GM_ARGVAL);
 | 
						|
		return(GM_NULL);
 | 
						|
	}
 | 
						|
 | 
						|
	intper = 0;
 | 
						|
	ad = begend;
 | 
						|
 | 
						|
	if (opt!=GM_N)	{
 | 
						|
/* determine integer & fractional parts	of nper, if in range */
 | 
						|
		if (fun<=1)  {
 | 
						|
			if (*nperi<0)  {
 | 
						|
				_MacErr(GM_ARGVAL);
 | 
						|
				return(GM_NULL);
 | 
						|
			}
 | 
						|
			intper=*nperi;
 | 
						|
		}
 | 
						|
		else {
 | 
						|
			if (_MacIsDecN(nperd)||
 | 
						|
				(CompareDecimal(nperd,&decMaxTime)==1))	{
 | 
						|
				_MacErr(GM_ARGVAL);
 | 
						|
				return(GM_NULL);
 | 
						|
			}
 | 
						|
			(void) _TruncateDec80Bit(temp, nperd, 0);
 | 
						|
			intper=temp->dc.sl[0];
 | 
						|
			(void) _SubDec80Bit(fractper, nperd, temp);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (opt==GM_I)	{
 | 
						|
		opi=_InterestAux(fun, intper, fractper,
 | 
						|
			intr, pv, pmt, fv, begend);
 | 
						|
		return(opi);
 | 
						|
	}
 | 
						|
 | 
						|
	_MacDCopy(nintr, intr);
 | 
						|
	nintr->dc.id+=2;
 | 
						|
 | 
						|
/* opi = 1+i */
 | 
						|
	(void) _AddDec80Bit(opi, nintr,	&decOne);
 | 
						|
 | 
						|
	if (opt!=GM_N)	{
 | 
						|
/* handle zero interest	*/
 | 
						|
		if (_MacIsDecZ(intr))  {
 | 
						|
			(void) ConvLongToDecimal(temp2,	(long) intper);
 | 
						|
 | 
						|
			if (opt==GM_PV)	 {
 | 
						|
				(void) _MulDec80Bit(temp, temp2, pmt);
 | 
						|
				(void) _AddDec80Bit(temp, temp,	fv);
 | 
						|
				_MacDChgs(temp);
 | 
						|
				(void) _ScaleDec80Bit(pv, temp,	2);
 | 
						|
				return(pv);
 | 
						|
			}
 | 
						|
 | 
						|
			if (opt==GM_FV)	 {
 | 
						|
				(void) _MulDec80Bit(temp, temp2, pmt);
 | 
						|
				(void) _AddDec80Bit(temp, temp,	pv);
 | 
						|
				_MacDChgs(temp);
 | 
						|
				(void) _ScaleDec80Bit(fv, temp,	2);
 | 
						|
				return(fv);
 | 
						|
			}
 | 
						|
 | 
						|
			if (opt==GM_PMT)  {
 | 
						|
				if (intper==0)	{
 | 
						|
					_MacErr(GM_ARGVAL);
 | 
						|
					return(GM_NULL);
 | 
						|
				}
 | 
						|
				(void) _AddDec80Bit(temp, pv, fv);
 | 
						|
				_MacDChgs(temp);
 | 
						|
				(void) _DivRndDec80Bit(pmt, temp, temp2, 2);
 | 
						|
				return(pmt);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
/* calculate alpha */
 | 
						|
		if (fun==2)  {
 | 
						|
			(void) _MulDec80Bit(temp, nintr, fractper);
 | 
						|
			(void) _AddDec80Bit(alpha, temp, &decOne);
 | 
						|
		}
 | 
						|
		if (fun==3)  {
 | 
						|
			(void) _LnDec80Bit(temp, opi);
 | 
						|
			(void) _MulDec80Bit(temp, temp,	fractper);
 | 
						|
			(void) _ExpDec80Bit(alpha, temp);
 | 
						|
		}
 | 
						|
 | 
						|
/* handle zero nper */
 | 
						|
		if (intper==0)	{
 | 
						|
			if (opt==GM_PMT)  {
 | 
						|
				_MacErr(GM_ARGVAL);
 | 
						|
				return(GM_NULL);
 | 
						|
			}
 | 
						|
 | 
						|
			if (opt==GM_PV)	 {
 | 
						|
				if (fun<=1)
 | 
						|
					(void) _ScaleDec80Bit(pv, fv, 2);
 | 
						|
				else
 | 
						|
					(void) _DivRndDec80Bit(
 | 
						|
						pv, fv,	alpha, 2);
 | 
						|
				_MacDChgs(pv);
 | 
						|
				return(pv);
 | 
						|
			}
 | 
						|
 | 
						|
			if (opt==GM_FV)	 {
 | 
						|
				if (fun<=1)
 | 
						|
					(void) _ScaleDec80Bit(fv, pv, 2);
 | 
						|
				else  {
 | 
						|
					(void) _MulDec80Bit(fv,	pv, alpha);
 | 
						|
					(void) _ScaleDec80Bit(fv, fv, 2);
 | 
						|
				}
 | 
						|
				_MacDChgs(fv);
 | 
						|
				return(fv);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
/* calcuate (1+i)^-n and (1+iS)[1-(1+i)^-n]/i */
 | 
						|
		(void) _IntPwrDec80Bit(opitmn, opi, -intper);
 | 
						|
		(void) _SubDec80Bit(temp, &decOne, opitmn);
 | 
						|
 | 
						|
/* Advance payment needs (1+i)^-(n-a) */
 | 
						|
		if (fun==0)  {
 | 
						|
			(void) _IntPwrDec80Bit(opitmna,	opi, -(intper-ad));
 | 
						|
			(void) _SubDec80Bit(temp, &decOne, opitmna);
 | 
						|
			(void) ConvLongToDecimal(dad, (long) ad);
 | 
						|
		}
 | 
						|
		else
 | 
						|
		(void) _SubDec80Bit(temp, &decOne, opitmn);
 | 
						|
 | 
						|
		(void) _DivDec80Bit(mess, temp,	nintr);
 | 
						|
		if (begend==GM_BEGIN &&	fun!=0)
 | 
						|
			(void) _MulDec80Bit(mess, mess,	opi);
 | 
						|
 | 
						|
		if ((opt==GM_PMT||opt==GM_FV))	{
 | 
						|
			if (fun>1)
 | 
						|
				(void) _MulDec80Bit(pva, pv, alpha);
 | 
						|
			if (fun<=1)
 | 
						|
				_MacDCopy(pva, pv);
 | 
						|
		}
 | 
						|
 | 
						|
		/* calculate FV*(1+i)^-n */
 | 
						|
		if (opt==GM_PV||opt==GM_PMT)
 | 
						|
			(void) _MulDec80Bit(fvopi, fv, opitmn);
 | 
						|
 | 
						|
		if (opt==GM_PV||opt==GM_FV)
 | 
						|
			(void) _MulDec80Bit(pmtm, pmt, mess);
 | 
						|
 | 
						|
		if (opt==GM_PV)	 {
 | 
						|
			(void) _AddDec80Bit(temp, pmtm,	fvopi);
 | 
						|
			_MacDChgs(temp);
 | 
						|
			if (fun>1)
 | 
						|
				(void) _DivRndDec80Bit(pv, temp, alpha,	2);
 | 
						|
			if (fun==1)
 | 
						|
				(void) _ScaleDec80Bit(pv, temp,	2);
 | 
						|
			if (fun==0)  {
 | 
						|
				(void) _MulDec80Bit(temp2, dad,	pmt);
 | 
						|
				(void) _SubDec80Bit(temp, temp,	temp2);
 | 
						|
				(void) _ScaleDec80Bit(pv, temp,	2);
 | 
						|
			}
 | 
						|
			return(pv);
 | 
						|
		}
 | 
						|
 | 
						|
		if (opt==GM_PMT)  {
 | 
						|
			(void) _AddDec80Bit(temp, pva, fvopi);
 | 
						|
			_MacDChgs(temp);
 | 
						|
			if (fun==0)
 | 
						|
				(void) _AddDec80Bit(mess, mess,	dad);
 | 
						|
			(void) _DivRndDec80Bit(pmt, temp, mess,	2);
 | 
						|
			return(pmt);
 | 
						|
		}
 | 
						|
 | 
						|
		if (opt==GM_FV)	 {
 | 
						|
			if (fun==0)  {
 | 
						|
				(void) _MulDec80Bit(temp, pmt, dad);
 | 
						|
				(void) _AddDec80Bit(pva, pv, temp);
 | 
						|
			}
 | 
						|
			(void) _AddDec80Bit(temp, pva, pmtm);
 | 
						|
			_MacDChgs(temp);
 | 
						|
			(void) _DivRndDec80Bit(fv, temp, opitmn, 2);
 | 
						|
			return(fv);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* opt==GM_N */
 | 
						|
/* handle zero interest	*/
 | 
						|
	if (_MacIsDecZ(intr))  {
 | 
						|
		if (_MacIsDecZ(pmt))  {
 | 
						|
			_MacErr(GM_ARGVAL);
 | 
						|
			return(GM_NULL);
 | 
						|
		}
 | 
						|
 | 
						|
		(void) _AddDec80Bit(temp, pv, fv);
 | 
						|
		_MacDChgs(temp);
 | 
						|
 | 
						|
		(void) _DivTrnDec80Bit(temp2, temp, pmt, 0);
 | 
						|
/* check for exact division => don't increment */
 | 
						|
		(void) _MulDec80Bit(mess, temp2, pmt);
 | 
						|
		if (CompareDecimal(temp,mess)!=0)
 | 
						|
			(void) _AddDec80Bit(temp2, temp2, &decOne);
 | 
						|
 | 
						|
		if (_MacIsDecN(temp2)||CompareDecimal(temp2,&decMaxTime)==1) {
 | 
						|
			_MacErr(GM_ARGVAL);
 | 
						|
			return(GM_NULL);
 | 
						|
		}
 | 
						|
 | 
						|
		if (fun==1)  {
 | 
						|
			*nperi=temp2->dc.sl[0];
 | 
						|
			return(GM_NULL);
 | 
						|
		}
 | 
						|
		else  {
 | 
						|
			_MacDCopy(nperd, temp2);
 | 
						|
			return(nperd);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
/* first solve for integer part	of period */
 | 
						|
	(void) _DivDec80Bit(temp, pmt, nintr);
 | 
						|
	if (begend==GM_BEGIN)
 | 
						|
		(void) _MulDec80Bit(temp, temp,	opi);
 | 
						|
	_MacDCopy(temp2, temp);
 | 
						|
	(void) _AddDec80Bit(temp, temp,	pv);
 | 
						|
	(void) _SubDec80Bit(temp2, temp2, fv);
 | 
						|
	if (_MacIsDecZ(temp)||_MacIsDecZ(temp2))  {
 | 
						|
		_MacErr(GM_ARGVAL);
 | 
						|
		return(GM_NULL);
 | 
						|
	}
 | 
						|
	(void) _DivDec80Bit(temp, temp2, temp);
 | 
						|
	if (!_MacIsDecP(temp))	{
 | 
						|
		_MacErr(GM_ARGVAL);
 | 
						|
		return(GM_NULL);
 | 
						|
	}
 | 
						|
	(void) _LnDec80Bit(temp, temp);
 | 
						|
	(void) _LnDec80Bit(temp2, opi);
 | 
						|
 | 
						|
	(void) _DivTrnDec80Bit(temp, temp, temp2, 0);
 | 
						|
	if (_MacIsDecN(temp)||(CompareDecimal(temp,&decMaxTime)==1)) {
 | 
						|
		_MacErr(GM_ARGVAL);
 | 
						|
		return(GM_NULL);
 | 
						|
	}
 | 
						|
 | 
						|
	intper=temp->dc.sl[0]+1;
 | 
						|
	if (intper==1)
 | 
						|
		intper--;
 | 
						|
 | 
						|
/* the +1 rounding assumes the ratio of	logarithms is not an integer */
 | 
						|
	if (fun==1)  {
 | 
						|
		*nperi=intper;	/* always round	up */
 | 
						|
		return(GM_NULL);
 | 
						|
	}
 | 
						|
 | 
						|
	/* fun > 1 */
 | 
						|
	(void) ConvLongToDecimal(nperd,	(long) intper);
 | 
						|
/* zero	pv makes fractional period irrelevant */
 | 
						|
	if (_MacIsDecZ(pv))
 | 
						|
		return(nperd);
 | 
						|
/* now solve for fractional part & add to integer part */
 | 
						|
	(void) _IntPwrDec80Bit(opitmn, opi, -intper);
 | 
						|
	(void) _SubDec80Bit(temp, &decOne, opitmn);
 | 
						|
	(void) _DivDec80Bit(mess, temp,	nintr);
 | 
						|
	if (begend==GM_BEGIN)
 | 
						|
		(void) _MulDec80Bit(mess, mess,	opi);
 | 
						|
	(void) _MulDec80Bit(pmtm, pmt, mess);
 | 
						|
	(void) _MulDec80Bit(fvopi, fv, opitmn);
 | 
						|
	(void) _AddDec80Bit(temp, pmtm,	fvopi);
 | 
						|
	_MacDChgs(temp);
 | 
						|
	(void) _DivDec80Bit(alpha, temp, pv);
 | 
						|
	if (fun==2)  {
 | 
						|
		(void) _SubDec80Bit(temp, alpha, &decOne);
 | 
						|
		(void) _DivDec80Bit(fractper, temp, nintr);
 | 
						|
		(void) _AddDec80Bit(nperd, nperd, fractper);
 | 
						|
		(void) _Sq5UnsTo4Uns(nperd);
 | 
						|
	}
 | 
						|
	if (fun==3)  {
 | 
						|
		if (!_MacIsDecP(alpha))
 | 
						|
			return(nperd);
 | 
						|
		(void) _LnDec80Bit(temp, alpha);
 | 
						|
		(void) _LnDec80Bit(temp2, opi);
 | 
						|
		(void) _DivDec80Bit(fractper, temp, temp2);
 | 
						|
		(void) _AddDec80Bit(nperd, nperd, fractper);
 | 
						|
		(void) _Sq5UnsTo4Uns(nperd);
 | 
						|
	}
 | 
						|
	return(nperd);
 | 
						|
}
 |