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 ); }
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; }
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); } }
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; }
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; }
/** * 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)); }