Beispiel #1
0
static gnm_float
Duration (GDate *nSettle, GDate *nMat, gnm_float fCoup, gnm_float fYield,
	  gint nFreq, gint nBase, gnm_float fNumOfCoups)
{
        /* gnm_float  fYearfrac   = yearfrac ( nSettle, nMat, nBase ); */
        gnm_float  fDur        = 0.0;
	gnm_float  t, p        = 0.0;

        const gnm_float f100   = 100.0;

        fCoup  *= f100 / (gnm_float) nFreq; /* fCoup is used as cash flow */
        fYield /= nFreq;
        fYield += 1.0;

        for ( t = 1.0 ; t < fNumOfCoups ; t++ )
                fDur += t * ( fCoup ) / gnm_pow ( fYield, t );

        fDur += fNumOfCoups * ( fCoup + f100 ) / gnm_pow ( fYield, fNumOfCoups );

        for ( t = 1.0 ; t < fNumOfCoups ; t++ )
                p += fCoup / gnm_pow ( fYield, t );

        p += ( fCoup + f100 ) / gnm_pow ( fYield, fNumOfCoups );

        fDur /= p;
        fDur /= (gnm_float) nFreq;

        return ( fDur );
}
Beispiel #2
0
static gnm_float
ScGetGDA (gnm_float fWert, gnm_float fRest, gnm_float fDauer,
	  gnm_float fPeriode, gnm_float fFaktor)
{
        gnm_float fGda, fZins, fAlterWert, fNeuerWert;  /* FIXME: translate? */

        fZins = fFaktor / fDauer;
        if (fZins >= 1.0) {
                fZins = 1.0;
                if (fPeriode == 1.0)
                        fAlterWert = fWert;
                else
                        fAlterWert = 0.0;
        } else
                fAlterWert = fWert * gnm_pow (1.0 - fZins, fPeriode - 1.0);
        fNeuerWert = fWert * gnm_pow (1.0 - fZins, fPeriode);

        if (fNeuerWert < fRest)
                fGda = fAlterWert - fRest;
        else
                fGda = fAlterWert - fNeuerWert;
        if (fGda < 0.0)
                fGda = 0.0;
        return fGda;
}
Beispiel #3
0
void
gsl_complex_tanh (complex_t const *a, complex_t *res)
{                               /* z = tanh(a) */
        gnm_float R = GSL_REAL (a), I = GSL_IMAG (a);

	if (gnm_abs (R) < 1.0) {
	         gnm_float D =
			 gnm_pow (gnm_cos (I), 2.0) +
			 gnm_pow (gnm_sinh (R), 2.0);

		 complex_init (res, gnm_sinh (R) * cosh (R) / D,
			       0.5 * gnm_sin (2 * I) / D);
	} else {
	         gnm_float D =
			 gnm_pow (gnm_cos (I), 2.0) +
			 gnm_pow (gnm_sinh (R), 2.0);
		 gnm_float F = 1 + gnm_pow (gnm_cos (I) / gnm_sinh (R), 2.0);

		 complex_init (res, 1.0 / (gnm_tanh (R) * F),
			       0.5 * gnm_sin (2 * I) / D);
	}
}
Beispiel #4
0
static gnm_float
GetZw ( gnm_float fZins, gnm_float fZzr, gnm_float fRmz, gnm_float fBw,
	gint nF )
{
        gnm_float fZw;

        if ( fZins == 0.0 )
                fZw = fBw + fRmz * fZzr;
        else {
                gnm_float fTerm = gnm_pow ( 1.0 + fZins, fZzr );
                if ( nF > 0 )
                        fZw = fBw * fTerm + fRmz * ( 1.0 + fZins ) *
				( fTerm - 1.0 ) / fZins;
                else
                        fZw = fBw * fTerm + fRmz * ( fTerm - 1.0 ) / fZins;
        }

        return -fZw;
}
Beispiel #5
0
static gnm_float
GetRmz ( gnm_float fZins, gnm_float fZzr, gnm_float fBw, gnm_float fZw,
	 gint nF )
{
        gnm_float fRmz;

        if ( fZins == 0.0 )
                fRmz = ( fBw + fZw ) / fZzr;
        else {
                gnm_float fTerm = gnm_pow ( 1.0 + fZins, fZzr );
                if ( nF > 0 )
                        fRmz = ( fZw * fZins / ( fTerm - 1.0 ) + fBw * fZins /
				 ( 1.0 - 1.0 / fTerm ) ) / ( 1.0 + fZins );
                else
                        fRmz = fZw * fZins / ( fTerm - 1.0 ) + fBw * fZins /
				( 1.0 - 1.0 / fTerm );
        }

        return -fRmz;
}
Beispiel #6
0
/**
 * FIXME: In the long term this needs optimising.
 **/
static GnmValue *
val_to_base (GnmFuncEvalInfo *ei,
	     GnmValue const *value,
	     GnmValue const *aplaces,
	     int src_base, int dest_base,
	     gnm_float min_value, gnm_float max_value,
	     Val2BaseFlags flags)
{
	int digit, min, max, places;
	gnm_float v;
	GString *buffer;
	GnmValue *vstring = NULL;

	g_return_val_if_fail (src_base > 1 && src_base <= 36,
			      value_new_error_VALUE (ei->pos));
	g_return_val_if_fail (dest_base > 1 && dest_base <= 36,
			      value_new_error_VALUE (ei->pos));

	/* func.c ought to take care of this.  */
	if (VALUE_IS_BOOLEAN (value))
		return value_new_error_VALUE (ei->pos);
	if (aplaces && VALUE_IS_BOOLEAN (aplaces))
		return value_new_error_VALUE (ei->pos);

	switch (value->type) {
	default:
		return value_new_error_NUM (ei->pos);

	case VALUE_STRING:
		if (flags & V2B_STRINGS_GENERAL) {
			vstring = format_match_number
				(value_peek_string (value), NULL,
				 workbook_date_conv (ei->pos->sheet->workbook));
			if (!vstring || !VALUE_IS_FLOAT (vstring)) {
				value_release (vstring);
				return value_new_error_VALUE (ei->pos);
			}
		} else {
			char const *str = value_peek_string (value);
			size_t len;
			gboolean hsuffix = FALSE;
			char *err;

			if ((flags & V2B_STRINGS_BLANK_ZERO) && *str == 0)
				str = "0";

			/* This prevents leading spaces, signs, etc, and "".  */
			if (!g_ascii_isalnum (*str))
				return value_new_error_NUM (ei->pos);

			len = strlen (str);
			/* We check length in bytes.  Since we are going to
			   require nothing but digits, that is fine.  */
			if ((flags & V2B_STRINGS_MAXLEN) && len > 10)
				return value_new_error_NUM (ei->pos);

			if (flags & V2B_STRINGS_0XH) {
				if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
					str += 2;
				else if (str[len - 1] == 'h' || str[len - 1] == 'H')
					hsuffix = TRUE;
			}

			v = g_ascii_strtoll (str, &err, src_base);
			if (err == str || err[hsuffix] != 0)
				return value_new_error_NUM (ei->pos);

			if (v < min_value || v > max_value)
				return value_new_error_NUM (ei->pos);

			break;
		}
		/* Fall through.  */

	case VALUE_FLOAT: {
		gnm_float val = gnm_fake_trunc (value_get_as_float (vstring ? vstring : value));
		char buf[GNM_MANT_DIG + 10];
		char *err;

		value_release (vstring);

		if (val < min_value || val > max_value)
			return value_new_error_NUM (ei->pos);

		g_ascii_formatd (buf, sizeof (buf) - 1,
				 "%.0" GNM_FORMAT_f,
				 val);

		v = g_ascii_strtoll (buf, &err, src_base);
		if (*err != 0)
			return value_new_error_NUM (ei->pos);
		break;
	}
	}

	if (src_base != 10) {
		gnm_float b10 = gnm_pow (src_base, 10);
		if (v >= b10 / 2) /* N's complement */
			v = v - b10;
	}

	if (flags & V2B_NUMBER)
		return value_new_float (v);

	if (v < 0) {
		min = 1;
		max = 10;
		v += gnm_pow (dest_base, max);
	} else {
		if (v == 0)
			min = max = 1;
		else
			min = max = (int)(gnm_log (v + 0.5) /
					  gnm_log (dest_base)) + 1;
	}

	if (aplaces) {
		gnm_float fplaces = value_get_as_float (aplaces);
		if (fplaces < min || fplaces > 10)
			return value_new_error_NUM (ei->pos);
		places = (int)fplaces;
		if (v >= 0 && places > max)
			max = places;
	} else
		places = 1;

	buffer = g_string_sized_new (max);
	g_string_set_size (buffer, max);

	for (digit = max - 1; digit >= 0; digit--) {
		int thisdigit = gnm_fmod (v + 0.5, dest_base);
		v = gnm_floor ((v + 0.5) / dest_base);
		buffer->str[digit] =
			thisdigit["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
	}

	return value_new_string_nocopy (g_string_free (buffer, FALSE));
}