/* Statistics Plugin * * Richard Hestilow */ #include #include #include "stat.h" #include static char *help_stat_stdev = { N_("@FUNCTION=STDEV\n" "@SYNTAX = STDEV(value1, value2, ...)" "@DESCRIPTION=" "Computes the standard deviation of all the values and cells" " referenced in the argument list. This is equivalent to the square " "root of the variance." "\n" "@SEEALSO=VARIANCE") }; static char *help_stat_variance = { N_("@FUNCTION=VARIANCE\n" "@SYNTAX = VARIANCE(value1, value2, ...)" "@DESCRIPTION=" "Computes the variation of all the values and cells referenced in the " "argument list. This is equivalent to the sum of (value - average)^2, " "divided by the number of values minus 1. If you want it divided by " "N instead of N - 1, use NVARIANCE." "@SEEALSO=AVERAGE, NVARIANCE") }; static char *help_stat_nvariance = { N_("@FUNCTION=NVARIANCE\n" "@SYNTAX = NVARIANVE(value1, value2, ...)" "@DESCRIPTION=" "Computes the variation of all the values and cells references in the " "argument list. This is equivalent to the sum of (value - average)^2, " "divided by the number of values. If you want it divided by N - 1 " "instead of N, use VARIANCE." "@SEEALSO=AVERAGE, VARIANCE") }; static FunctionDefinition plugin_functions[] = { {"stdev", "", "", &help_stat_stdev, stat_stdev, NULL }, {"variance", "", "", &help_stat_variance, stat_variance, NULL }, {"nvariance", "", "", &help_stat_nvariance, stat_nvariance, NULL }, { NULL, NULL }, }; static int can_unload (PluginData *pd) { Symbol *sym; sym = symbol_lookup (global_symbol_table, "stat_variance"); return sym->ref_count <= 1; } int init_plugin (PluginData *pd) { install_symbols (plugin_functions); pd->can_unload = can_unload; pd->cleanup_plugin = cleanup_plugin; pd->title = g_strdup (_("Statistics Plugin")); return 0; } static void cleanup_plugin (PluginData *pd) { Symbol *sym; unsigned int i; g_free (pd->title); for (i = 0; i <(((sizeof(plugin_functions))/(sizeof(FunctionDefinition)))-1); i++){ sym = symbol_lookup(global_symbol_table, plugin_functions [i].name); if (sym) symbol_unref(sym); } } static Value * stat_variance (void *sheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string) { float undiv; unsigned int len; undiv = stat_undivided_variance (sheet, expr_node_list, eval_col, eval_row, error_string); len = g_list_length (expr_node_list); if (len == 1){ *error_string = _("variance - division by 0"); return NULL; } return value_float (undiv / (len - 1)); } static Value * stat_nvariance (void *sheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string) { float undiv; unsigned int len; undiv = stat_undivided_variance(sheet, expr_node_list, eval_col, eval_row, error_string); len = g_list_length(expr_node_list); return value_float (undiv / len); } float stat_undivided_variance (void *sheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string) { Value *avgV, *tmpval; GPtrArray *values; float tmp; float result = 0.0; unsigned int i; float avg; avgV = g_malloc(sizeof(Value *)); tmpval = g_malloc(sizeof(Value *)); values = g_ptr_array_new(); function_iterate_argument_values(sheet, callback_var, values, expr_node_list, eval_col, eval_row, error_string); avgV = function_call_with_values(sheet, "average", values->len, (Value **)values->pdata, error_string); avg = value_get_as_double(avgV); for (i = 0; i < values->len; i++){ tmpval = g_ptr_array_index (values, i); tmp = tmpval->v.v_float - avg; tmp *= tmp; result += tmp; } g_free (avgV); return result; } static Value * stat_stdev (void *sheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string) { Value *result, *var; result = g_malloc(sizeof(Value *)); result->type = VALUE_FLOAT; result->v.v_float = 0.0; var = stat_variance(sheet, expr_node_list, eval_col, eval_row, error_string); result->v.v_float = sqrt(var->v.v_float); g_free(var); return result; } int callback_var (Sheet *sheet, Value *value, char **error_string, void *closure) { GPtrArray *values = (GPtrArray *) closure; float tmp; tmp = value_get_as_double (value); value->v.v_float = tmp; value->type = VALUE_FLOAT; g_ptr_array_add (values, g_memdup (value, sizeof (*value))); return TRUE; }