char * gnm_complex_to_string (gnm_complex const *src, char imunit) { char *re_buffer = NULL; char *im_buffer = NULL; char const *sign = ""; char const *suffix = ""; char *res; char suffix_buffer[2]; const char *fmt = "%.*" GNM_FORMAT_g; static int digits = -1; if (digits == -1) { gnm_float l10 = gnm_log10 (FLT_RADIX); digits = (int)gnm_ceil (GNM_MANT_DIG * l10) + (l10 == (int)l10 ? 0 : 1); } if (src->re != 0 || src->im == 0) { /* We have a real part. */ re_buffer = g_strdup_printf (fmt, digits, src->re); } if (src->im != 0) { /* We have an imaginary part. */ suffix = suffix_buffer; suffix_buffer[0] = imunit; suffix_buffer[1] = 0; if (src->im == 1) { if (re_buffer) sign = "+"; } else if (src->im == -1) { sign = "-"; } else { im_buffer = g_strdup_printf (fmt, digits, src->im); if (re_buffer && *im_buffer != '-' && *im_buffer != '+') sign = (src->im >= 0) ? "+" : "-"; } } res = g_strconcat (re_buffer ? re_buffer : "", sign, im_buffer ? im_buffer : "", suffix, NULL); g_free (re_buffer); g_free (im_buffer); return res; }
static GnmValue * gnumeric_randbetween (GnmFuncEvalInfo *ei, GnmValue const * const *argv) { gnm_float bottom = value_get_as_float (argv[0]); gnm_float top = value_get_as_float (argv[1]); if (bottom > top) return value_new_error_NUM (ei->pos); /* Bottom is ceiled, top floored. Neither is truncated. */ bottom = gnm_ceil (bottom); top = gnm_floor (top); return value_new_float (bottom + gnm_floor ((top + 1.0 - bottom) * random_01 ())); }
GnmValue * get_vdb (gnm_float cost, gnm_float salvage, gnm_float life, gnm_float start_period, gnm_float end_period, gnm_float factor, gboolean flag) { gnm_float fVdb; gnm_float fIntStart = gnm_floor (start_period); gnm_float fIntEnd = gnm_ceil (end_period); int i; int nLoopStart = (int) fIntStart; int nLoopEnd = (int) fIntEnd; fVdb = 0.0; if ( flag ) { for (i = nLoopStart + 1; i <= nLoopEnd; i++) { gnm_float fTerm; fTerm = ScGetGDA (cost, salvage, life, i, factor); if ( i == nLoopStart+1 ) fTerm *= ( MIN( end_period, fIntStart + 1.0 ) - start_period ); else if ( i == nLoopEnd ) fTerm *= ( end_period + 1.0 - fIntEnd ); fVdb += fTerm; } } else { gnm_float life1 = life; gnm_float fPart; if ( start_period != gnm_floor (start_period) ) if (factor > 1) { if (start_period >= life / 2) { fPart = start_period - life / 2; start_period = life / 2; end_period -= fPart; life1 += 1; } } cost -= ScInterVDB (cost, salvage, life, life1, start_period, factor); fVdb = ScInterVDB (cost, salvage, life, life - start_period, end_period - start_period, factor); } return value_new_float (fVdb); }
void gnm_string_add_number (GString *buf, gnm_float d) { size_t old_len = buf->len; double d2; static int digits; if (digits == 0) { gnm_float l10 = gnm_log10 (FLT_RADIX); digits = (int)gnm_ceil (GNM_MANT_DIG * l10) + (l10 == (int)l10 ? 0 : 1); } g_string_append_printf (buf, "%.*" GNM_FORMAT_g, digits - 1, d); d2 = gnm_strto (buf->str + old_len, NULL); if (d != d2) { g_string_truncate (buf, old_len); g_string_append_printf (buf, "%.*" GNM_FORMAT_g, digits, d); } }
static gnm_float ScInterVDB (gnm_float cost, gnm_float salvage, gnm_float life, gnm_float life1, gnm_float period, gnm_float factor) { gnm_float fVdb = 0; gnm_float fIntEnd = gnm_ceil (period); int nLoopEnd = fIntEnd; gnm_float fTerm, fLia; gnm_float fRestwert = cost - salvage; gboolean bNowLia = FALSE; gnm_float fGda; int i; fLia = 0; for ( i = 1; i <= nLoopEnd; i++ ) { if (!bNowLia) { fGda = ScGetGDA (cost, salvage, life, i, factor); fLia = fRestwert / (life1 - (gnm_float) (i - 1)); if (fLia > fGda) { fTerm = fLia; bNowLia = TRUE; } else { fTerm = fGda; fRestwert -= fGda; } } else fTerm = fLia; if ( i == nLoopEnd) fTerm *= ( period + 1.0 - fIntEnd ); fVdb += fTerm; } return fVdb; }
GnmValue * get_vdb (gnm_float cost, gnm_float salvage, gnm_float life, gnm_float start_period, gnm_float end_period, gnm_float factor, gboolean flag) { gnm_float fVdb; gnm_float fIntStart = gnm_floor (start_period); gnm_float fIntEnd = gnm_ceil (end_period); fVdb = 0.0; if ( flag ) { int i, nLoopStart, nLoopEnd; if (fIntEnd > G_MAXINT || fIntEnd - fIntStart > 10000 /* arbitrary */) return value_new_error_VALUE (NULL); nLoopStart = (int) fIntStart; nLoopEnd = (int) fIntEnd; for (i = nLoopStart + 1; i <= nLoopEnd; i++) { gnm_float fTerm; fTerm = ScGetGDA (cost, salvage, life, i, factor); if ( i == nLoopStart+1 ) fTerm *= ( MIN( end_period, fIntStart + 1.0 ) - start_period ); else if ( i == nLoopEnd ) fTerm *= ( end_period + 1.0 - fIntEnd ); fVdb += fTerm; } } else { gnm_float fPart = 0; double fIntEnd = gnm_ceil (end_period); if (start_period > fIntStart) { // First period is partial. Calculate the excess as // the pro-rata value of the first period as-if it // was not partial. double tempcost = cost - ScInterVDB( cost, salvage, life, life, fIntStart, factor); fPart += (start_period - fIntStart) * ScInterVDB( tempcost, salvage, life, life - fIntStart, 1, factor); } if (end_period < fIntEnd) { // Last period is partial. Calculate the excess as // the pro-rata value of the last period as-if it // was not partial. double em1 = fIntEnd - 1; // Start of last period double tempcost = cost - ScInterVDB (cost, salvage, life, life, em1, factor); fPart += (fIntEnd - end_period) * ScInterVDB (tempcost, salvage, life, life - em1, 1, factor); } cost -= ScInterVDB (cost, salvage, life, life, fIntStart, factor); fVdb = ScInterVDB (cost, salvage, life, life - fIntStart, fIntEnd - fIntStart, factor); fVdb -= fPart; } return value_new_float (fVdb); }
GnmConventions * xlsx_conventions_new (gboolean output) { static struct { char const *gnm_name; gpointer handler; } const xlfn_func_handlers[] = { {"BINOM.INV", xlsx_func_binominv_handler}, {"CHISQ.DIST", xlsx_func_chisqdist_handler}, {"F.DIST", xlsx_func_fdist_handler}, {"NEGBINOM.DIST", xlsx_func_negbinomdist_handler}, {"LOGNORM.DIST", xlsx_func_lognormdist_handler}, {NULL, NULL} }; static struct { char const *gnm_name; gpointer handler; } const xlfn_func_output_handlers[] = { {"R.QBETA", xlsx_func_betainv_output_handler}, {"R.QBINOM", xlsx_func_binominv_output_handler}, {"R.QCHISQ", xlsx_func_chisqinv_output_handler}, {"R.QF", xlsx_func_finv_output_handler}, {"R.QGAMMA", xlsx_func_gammainv_output_handler}, {"R.QLNORM", xlsx_func_lognorminv_output_handler}, {"R.QNORM", xlsx_func_norminv_output_handler}, {"R.QT", xlsx_func_tinv_output_handler}, {"ERF", xlsx_func_erf_output_handler}, {"FLOOR", xlsx_func_floor_output_handler}, {"HYPGEOMDIST", xlsx_func_hypgeomdist_output_handler}, {NULL, NULL} }; static struct { char const *xlsx_name; char const *gnm_name; } const xlfn_func_renames[] = { { "BETA.INV", "BETAINV" }, { "BINOM.DIST", "BINOMDIST" }, /* { "BINOM.INV", "R.QBINOM" }, see handlers */ { "CHISQ.DIST.RT", "CHIDIST" }, { "CHISQ.INV", "R.QCHISQ" }, /* see output handler */ { "CHISQ.INV.RT", "CHIINV" }, { "CHISQ.TEST", "CHITEST" }, { "CONFIDENCE.NORM", "CONFIDENCE" }, { "COVARIANCE.P", "COVAR" }, { "ERF.PRECISE", "ERF" }, { "ERFC.PRECISE", "ERFC" }, { "EXPON.DIST", "EXPONDIST" }, { "F.DIST.RT", "FDIST" }, { "F.INV", "R.QF" }, /* see output handler */ { "F.INV.RT", "FINV" }, { "F.TEST", "FTEST" }, { "GAMMA.DIST", "GAMMADIST" }, { "GAMMA.INV", "GAMMAINV" }, { "HYPGEOM.DIST", "HYPGEOMDIST" }, /* see output handler */ { "LOGNORM.INV", "LOGINV" }, { "MODE.SNGL", "MODE" }, { "NORM.DIST", "NORMDIST" }, { "NORM.INV", "NORMINV" }, { "NORM.S.INV", "NORMSINV" }, { "PERCENTILE.INC", "PERCENTILE" }, { "PERCENTRANK.INC", "PERCENTRANK" }, { "POISSON.DIST", "POISSON" }, { "QUARTILE.INC", "QUARTILE" }, { "RANK.EQ", "RANK" }, { "STDEV.P", "STDEVP" }, { "STDEV.S", "STDEV" }, { "T.TEST", "TTEST" }, { "T.INV.2T", "TINV" }, { "VAR.P", "VARP" }, { "VAR.S", "VAR" }, { "WEIBULL.DIST", "WEIBULL" }, { "Z.TEST", "ZTEST" }, { NULL, NULL } }; GnmConventions *convs = gnm_conventions_new_full ( sizeof (XLSXExprConventions)); XLSXExprConventions *xconv = (XLSXExprConventions *)convs; int i; convs->decimal_sep_dot = TRUE; convs->input.range_ref = rangeref_parse; convs->input.external_wb = xlsx_lookup_external_wb; convs->input.string = xlsx_string_parser; convs->output.cell_ref = xlsx_cellref_as_string; convs->output.range_ref = xlsx_rangeref_as_string; convs->output.string = xlsx_output_string; convs->range_sep_colon = TRUE; convs->sheet_name_sep = '!'; convs->arg_sep = ','; convs->array_col_sep = ','; convs->array_row_sep = ';'; convs->output.translated = FALSE; xconv->extern_id_by_wb = g_hash_table_new_full (g_direct_hash, g_direct_equal, (GDestroyNotify) g_object_unref, g_free); xconv->extern_wb_by_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); if (output) { gnm_float l10 = gnm_log10 (FLT_RADIX); convs->output.decimal_digits = (int)gnm_ceil (GNM_MANT_DIG * l10) + (l10 == (int)l10 ? 0 : 1); convs->output.func = xlsx_func_map_out; xconv->xlfn_map = g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal); for (i = 0; xlfn_func_renames[i].xlsx_name; i++) g_hash_table_insert (xconv->xlfn_map, (gchar *) xlfn_func_renames[i].gnm_name, (gchar *) xlfn_func_renames[i].xlsx_name); xconv->xlfn_handler_map = g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal); for (i = 0; xlfn_func_output_handlers[i].gnm_name; i++) g_hash_table_insert (xconv->xlfn_handler_map, (gchar *) xlfn_func_output_handlers[i].gnm_name, xlfn_func_output_handlers[i].handler); } else { convs->input.func = xlsx_func_map_in; xconv->xlfn_map = g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal); for (i = 0; xlfn_func_renames[i].xlsx_name; i++) g_hash_table_insert (xconv->xlfn_map, (gchar *) xlfn_func_renames[i].xlsx_name, (gchar *) xlfn_func_renames[i].gnm_name); xconv->xlfn_handler_map = g_hash_table_new (go_ascii_strcase_hash, go_ascii_strcase_equal); for (i = 0; xlfn_func_handlers[i].gnm_name; i++) g_hash_table_insert (xconv->xlfn_handler_map, (gchar *) xlfn_func_handlers[i].gnm_name, xlfn_func_handlers[i].handler); } return convs; }