1 /*
2 * analysis-exp-smoothing.c:
3 *
4 * This is a complete reimplementation of the exponential smoothing tool in tool in 2008
5 *
6 * Author:
7 * Andreas J. Guelzow <aguelzow@pyrshep.ca>
8 *
9 * (C) Copyright 2008 by Andreas J. Guelzow <aguelzow@pyrshep.ca>
10 *
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses/>.
24 */
25
26 #include <gnumeric-config.h>
27 #include <glib/gi18n-lib.h>
28 #include <gnumeric.h>
29 #include <tools/analysis-exp-smoothing.h>
30 #include <tools/analysis-tools.h>
31 #include <value.h>
32 #include <ranges.h>
33 #include <expr.h>
34 #include <graph.h>
35 #include <func.h>
36 #include <numbers.h>
37 #include <sheet-object-graph.h>
38 #include <goffice/goffice.h>
39 #include <sheet.h>
40
41
42 static GnmExpr const *
analysis_tool_exp_smoothing_funcall5(GnmFunc * fd,GnmExpr const * ex,int y,int x,int dy,int dx)43 analysis_tool_exp_smoothing_funcall5 (GnmFunc *fd, GnmExpr const *ex, int y, int x, int dy, int dx)
44 {
45 GnmExprList *list;
46 list = gnm_expr_list_prepend (NULL, gnm_expr_new_constant (value_new_int (dx)));
47 list = gnm_expr_list_prepend (list, gnm_expr_new_constant (value_new_int (dy)));
48 list = gnm_expr_list_prepend (list, gnm_expr_new_constant (value_new_int (x)));
49 list = gnm_expr_list_prepend (list, gnm_expr_new_constant (value_new_int (y)));
50 list = gnm_expr_list_prepend (list, ex);
51
52 return gnm_expr_new_funcall (fd, list);
53 }
54
55 static void
create_line_plot(GogPlot ** plot,SheetObject ** so)56 create_line_plot (GogPlot **plot, SheetObject **so)
57 {
58 GogGraph *graph;
59 GogChart *chart;
60
61 graph = g_object_new (GOG_TYPE_GRAPH, NULL);
62 chart = GOG_CHART (gog_object_add_by_name (GOG_OBJECT (graph), "Chart", NULL));
63 *plot = gog_plot_new_by_name ("GogLinePlot");
64 gog_object_add_by_name (GOG_OBJECT (chart), "Plot", GOG_OBJECT (*plot));
65 *so = sheet_object_graph_new (graph);
66 g_object_unref (graph);
67 }
68
69 static void
attach_series(GogPlot * plot,GOData * expr)70 attach_series (GogPlot *plot, GOData *expr)
71 {
72 GogSeries *series;
73
74 g_return_if_fail (plot != NULL);
75
76 series = gog_plot_new_series (plot);
77 gog_series_set_dim (series, 1, expr, NULL);
78 }
79
80 static gboolean
analysis_tool_exponential_smoothing_engine_ses_h_run(data_analysis_output_t * dao,analysis_tools_data_exponential_smoothing_t * info)81 analysis_tool_exponential_smoothing_engine_ses_h_run (data_analysis_output_t *dao,
82 analysis_tools_data_exponential_smoothing_t *info)
83 {
84 GSList *l;
85 gint col = 0;
86 gint source;
87 SheetObject *so = NULL;
88 GogPlot *plot = NULL;
89 GnmFunc *fd_index;
90 GnmFunc *fd_offset;
91 GnmFunc *fd_sqrt = NULL;
92 GnmFunc *fd_sumxmy2 = NULL;
93 GnmExpr const *expr_alpha = NULL;
94
95 if (info->std_error_flag) {
96 fd_sqrt = gnm_func_lookup_or_add_placeholder ("SQRT");
97 gnm_func_inc_usage (fd_sqrt);
98 fd_sumxmy2 = gnm_func_lookup_or_add_placeholder ("SUMXMY2");
99 gnm_func_inc_usage (fd_sumxmy2);
100 }
101
102 fd_index = gnm_func_lookup_or_add_placeholder ("INDEX");
103 gnm_func_inc_usage (fd_index);
104 fd_offset = gnm_func_lookup_or_add_placeholder ("OFFSET");
105 gnm_func_inc_usage (fd_offset);
106
107 if (info->show_graph)
108 create_line_plot (&plot, &so);
109
110 dao_set_italic (dao, 0, 0, 0, 0);
111 dao_set_cell (dao, 0, 0, _("Exponential Smoothing"));
112 dao_set_format (dao, 0, 1, 0, 1, _("\"\xce\xb1 =\" * 0.000"));
113 dao_set_cell_expr (dao, 0, 1, gnm_expr_new_constant (value_new_float (info->damp_fact)));
114 expr_alpha = dao_get_cellref (dao, 0, 1);
115
116 dao->offset_row = 2;
117
118 for (l = info->base.input, source = 1; l; l = l->next, col++, source++) {
119 GnmValue *val = value_dup ((GnmValue *)l->data);
120 GnmValue *val_c = NULL;
121 GnmExpr const *expr_title = NULL;
122 GnmExpr const *expr_input = NULL;
123 gint height;
124 gint x = 1;
125 gint y = 1;
126 gint *mover;
127 guint delta_x = 1;
128 guint delta_y = 1;
129 gint row;
130 Sheet *sheet;
131 GnmEvalPos ep;
132
133 sheet = val->v_range.cell.a.sheet;
134 eval_pos_init_sheet (&ep, sheet);
135
136 dao_set_italic (dao, col, 0, col, 0);
137 if (info->base.labels) {
138 val_c = value_dup (val);
139 switch (info->base.group_by) {
140 case GROUPED_BY_ROW:
141 val->v_range.cell.a.col++;
142 break;
143 default:
144 val->v_range.cell.a.row++;
145 break;
146 }
147 expr_title = gnm_expr_new_funcall1 (fd_index,
148 gnm_expr_new_constant (val_c));
149
150 dao_set_cell_expr (dao, col, 0, expr_title);
151 } else
152 dao_set_cell_printf
153 (dao, col, 0,
154 (info->base.group_by == GROUPED_BY_ROW ?
155 _("Row %d") : _("Column %d")),
156 source);
157
158 switch (info->base.group_by) {
159 case GROUPED_BY_ROW:
160 height = value_area_get_width (val, &ep);
161 mover = &x;
162 break;
163 default:
164 height = value_area_get_height (val, &ep);
165 mover = &y;
166 break;
167 }
168
169 expr_input = gnm_expr_new_constant (val);
170
171 if (plot != NULL) {
172 attach_series (plot, gnm_go_data_vector_new_expr (sheet, gnm_expr_top_new
173 (gnm_expr_copy (expr_input))));
174 attach_series (plot, dao_go_data_vector (dao, col, 1, col, height));
175 }
176
177 /* F(t+1) = F(t) + damp_fact * ( A(t) - F(t) ) */
178 (*mover) = 1;
179 dao_set_cell_expr (dao, col, 1,
180 gnm_expr_new_funcall1 (fd_index,
181 gnm_expr_copy (expr_input)));
182
183 for (row = 2; row <= height; row++, (*mover)++) {
184 GnmExpr const *A;
185 GnmExpr const *F;
186
187 A = gnm_expr_new_binary (gnm_expr_copy (expr_alpha),
188 GNM_EXPR_OP_MULT,
189 gnm_expr_new_funcall3
190 (fd_index,
191 gnm_expr_copy (expr_input),
192 gnm_expr_new_constant(value_new_int(y)),
193 gnm_expr_new_constant(value_new_int(x))));
194 F = gnm_expr_new_binary (gnm_expr_new_binary (gnm_expr_new_constant
195 (value_new_int (1)),
196 GNM_EXPR_OP_SUB,
197 gnm_expr_copy (expr_alpha)),
198 GNM_EXPR_OP_MULT,
199 make_cellref (0, -1));
200 dao_set_cell_expr (dao, col, row, gnm_expr_new_binary (A, GNM_EXPR_OP_ADD, F));
201 }
202
203 if (info->std_error_flag) {
204 col++;
205 dao_set_italic (dao, col, 0, col, 0);
206 dao_set_cell (dao, col, 0, _("Standard Error"));
207
208 y = 0;
209 x = 0;
210 (*mover) = 1;
211 for (row = 1; row <= height; row++) {
212 if (row > 1 && row <= height && (row - 1 - info->df) > 0) {
213 GnmExpr const *expr_offset;
214
215 if (info->base.group_by == GROUPED_BY_ROW)
216 delta_x = row - 1;
217 else
218 delta_y = row - 1;
219
220 expr_offset = analysis_tool_exp_smoothing_funcall5
221 (fd_offset, gnm_expr_copy (expr_input), y, x, delta_y, delta_x);
222 dao_set_cell_expr (dao, col, row,
223 gnm_expr_new_funcall1
224 (fd_sqrt,
225 gnm_expr_new_binary
226 (gnm_expr_new_funcall2
227 (fd_sumxmy2,
228 expr_offset,
229 make_rangeref (-1, 2 - row, -1, 0)),
230 GNM_EXPR_OP_DIV,
231 gnm_expr_new_constant (value_new_int
232 (row - 1 - info->df)))));
233 } else
234 dao_set_cell_na (dao, col, row);
235 }
236 }
237
238 gnm_expr_free (expr_input);
239 }
240
241 if (so != NULL)
242 dao_set_sheet_object (dao, 0, 1, so);
243
244 gnm_expr_free (expr_alpha);
245 if (fd_sqrt != NULL)
246 gnm_func_dec_usage (fd_sqrt);
247 if (fd_sumxmy2 != NULL)
248 gnm_func_dec_usage (fd_sumxmy2);
249 gnm_func_dec_usage (fd_offset);
250 gnm_func_dec_usage (fd_index);
251
252 dao_redraw_respan (dao);
253
254 return FALSE;
255 }
256
257 static gboolean
analysis_tool_exponential_smoothing_engine_ses_r_run(data_analysis_output_t * dao,analysis_tools_data_exponential_smoothing_t * info)258 analysis_tool_exponential_smoothing_engine_ses_r_run (data_analysis_output_t *dao,
259 analysis_tools_data_exponential_smoothing_t *info)
260 {
261 GSList *l;
262 gint col = 0;
263 gint source;
264 SheetObject *so = NULL;
265 GogPlot *plot = NULL;
266 GnmFunc *fd_index;
267 GnmFunc *fd_offset;
268 GnmFunc *fd_average;
269 GnmFunc *fd_sqrt = NULL;
270 GnmFunc *fd_sumxmy2 = NULL;
271 GnmExpr const *expr_alpha = NULL;
272
273 if (info->std_error_flag) {
274 fd_sqrt = gnm_func_lookup_or_add_placeholder ("SQRT");
275 gnm_func_inc_usage (fd_sqrt);
276 fd_sumxmy2 = gnm_func_lookup_or_add_placeholder ("SUMXMY2");
277 gnm_func_inc_usage (fd_sumxmy2);
278 }
279 fd_average = gnm_func_lookup_or_add_placeholder ("AVERAGE");
280 gnm_func_inc_usage (fd_average);
281 fd_index = gnm_func_lookup_or_add_placeholder ("INDEX");
282 gnm_func_inc_usage (fd_index);
283 fd_offset = gnm_func_lookup_or_add_placeholder ("OFFSET");
284 gnm_func_inc_usage (fd_offset);
285
286 if (info->show_graph)
287 create_line_plot (&plot, &so);
288
289 dao_set_italic (dao, 0, 0, 0, 0);
290 dao_set_cell (dao, 0, 0, _("Exponential Smoothing"));
291 dao_set_format (dao, 0, 1, 0, 1, _("\"\xce\xb1 =\" * 0.000"));
292 dao_set_cell_expr (dao, 0, 1, gnm_expr_new_constant (value_new_float (info->damp_fact)));
293 expr_alpha = dao_get_cellref (dao, 0, 1);
294
295 dao->offset_row = 2;
296
297 for (l = info->base.input, source = 1; l; l = l->next, col++, source++) {
298 GnmValue *val = value_dup ((GnmValue *)l->data);
299 GnmValue *val_c = NULL;
300 GnmExpr const *expr_title = NULL;
301 GnmExpr const *expr_input = NULL;
302 gint height;
303 gint x = 1;
304 gint y = 1;
305 gint *mover;
306 guint delta_x = 1;
307 guint delta_y = 1;
308 gint row;
309 Sheet *sheet;
310 GnmEvalPos ep;
311
312 sheet = val->v_range.cell.a.sheet;
313 eval_pos_init_sheet (&ep, sheet);
314
315 dao_set_italic (dao, col, 0, col, 0);
316 if (info->base.labels) {
317 val_c = value_dup (val);
318 switch (info->base.group_by) {
319 case GROUPED_BY_ROW:
320 val->v_range.cell.a.col++;
321 break;
322 default:
323 val->v_range.cell.a.row++;
324 break;
325 }
326 expr_title = gnm_expr_new_funcall1 (fd_index,
327 gnm_expr_new_constant (val_c));
328
329 dao_set_cell_expr (dao, col, 0, expr_title);
330 } else
331 dao_set_cell_printf
332 (dao, col, 0,
333 (info->base.group_by == GROUPED_BY_ROW ?
334 _("Row %d") : _("Column %d")),
335 source);
336
337 switch (info->base.group_by) {
338 case GROUPED_BY_ROW:
339 height = value_area_get_width (val, &ep);
340 mover = &x;
341 break;
342 default:
343 height = value_area_get_height (val, &ep);
344 mover = &y;
345 break;
346 }
347
348 expr_input = gnm_expr_new_constant (val);
349
350 if (plot != NULL) {
351 attach_series (plot, gnm_go_data_vector_new_expr (sheet, gnm_expr_top_new
352 (gnm_expr_copy (expr_input))));
353 attach_series (plot, dao_go_data_vector (dao, col, 2, col, height + 1));
354 }
355
356 /* F(t+1) = F(t) + damp_fact * ( A(t+1) - F(t) ) */
357
358 x = 1;
359 y = 1;
360 *mover = 5;
361 dao_set_cell_expr (dao, col, 1, gnm_expr_new_funcall1
362 (fd_average,
363 analysis_tool_exp_smoothing_funcall5 (fd_offset, gnm_expr_copy (expr_input), 0, 0, y, x)));
364 x = 1;
365 y = 1;
366 (*mover) = 1;
367 for (row = 1; row <= height; row++, (*mover)++) {
368 GnmExpr const *A;
369 GnmExpr const *F;
370
371 A = gnm_expr_new_binary (gnm_expr_copy (expr_alpha),
372 GNM_EXPR_OP_MULT,
373 gnm_expr_new_funcall3
374 (fd_index,
375 gnm_expr_copy (expr_input),
376 gnm_expr_new_constant(value_new_int(y)),
377 gnm_expr_new_constant(value_new_int(x))));
378 F = gnm_expr_new_binary (gnm_expr_new_binary (gnm_expr_new_constant
379 (value_new_int (1)),
380 GNM_EXPR_OP_SUB,
381 gnm_expr_copy (expr_alpha)),
382 GNM_EXPR_OP_MULT,
383 make_cellref (0, -1));
384 dao_set_cell_expr (dao, col, row + 1, gnm_expr_new_binary (A, GNM_EXPR_OP_ADD, F));
385 }
386
387 if (info->std_error_flag) {
388 col++;
389 dao_set_italic (dao, col, 0, col, 0);
390 dao_set_cell (dao, col, 0, _("Standard Error"));
391
392 y = 0;
393 x = 0;
394 (*mover) = 0;
395 for (row = 1; row <= height+1; row++) {
396 if (row > 1 && (row - 1 - info->df) > 0) {
397 GnmExpr const *expr_offset;
398
399 if (info->base.group_by == GROUPED_BY_ROW)
400 delta_x = row - 1;
401 else
402 delta_y = row - 1;
403
404 expr_offset = analysis_tool_exp_smoothing_funcall5
405 (fd_offset, gnm_expr_copy (expr_input), y, x, delta_y, delta_x);
406 dao_set_cell_expr (dao, col, row,
407 gnm_expr_new_funcall1
408 (fd_sqrt,
409 gnm_expr_new_binary
410 (gnm_expr_new_funcall2
411 (fd_sumxmy2,
412 expr_offset,
413 make_rangeref (-1, 1 - row, -1, -1)),
414 GNM_EXPR_OP_DIV,
415 gnm_expr_new_constant (value_new_int
416 (row - 1 - info->df)))));
417 } else
418 dao_set_cell_na (dao, col, row);
419 }
420 }
421 gnm_expr_free (expr_input);
422 }
423
424 if (so != NULL)
425 dao_set_sheet_object (dao, 0, 1, so);
426
427 gnm_expr_free (expr_alpha);
428 if (fd_sqrt != NULL)
429 gnm_func_dec_usage (fd_sqrt);
430 if (fd_sumxmy2 != NULL)
431 gnm_func_dec_usage (fd_sumxmy2);
432 gnm_func_dec_usage (fd_average);
433 gnm_func_dec_usage (fd_offset);
434 gnm_func_dec_usage (fd_index);
435
436 dao_redraw_respan (dao);
437
438 return FALSE;
439 }
440
441 static gboolean
analysis_tool_exponential_smoothing_engine_des_run(data_analysis_output_t * dao,analysis_tools_data_exponential_smoothing_t * info)442 analysis_tool_exponential_smoothing_engine_des_run (data_analysis_output_t *dao,
443 analysis_tools_data_exponential_smoothing_t *info)
444 {
445 GSList *l;
446 gint col = 0;
447 gint source;
448 SheetObject *so = NULL;
449 GogPlot *plot = NULL;
450 GnmFunc *fd_index;
451 GnmFunc *fd_offset;
452 GnmFunc *fd_linest;
453 GnmFunc *fd_sqrt = NULL;
454 GnmFunc *fd_sumxmy2 = NULL;
455 GnmExpr const *expr_alpha = NULL;
456 GnmExpr const *expr_gamma = NULL;
457
458 if (info->std_error_flag) {
459 fd_sqrt = gnm_func_lookup_or_add_placeholder ("SQRT");
460 gnm_func_inc_usage (fd_sqrt);
461 fd_sumxmy2 = gnm_func_lookup_or_add_placeholder ("SUMXMY2");
462 gnm_func_inc_usage (fd_sumxmy2);
463 }
464
465 fd_linest = gnm_func_lookup_or_add_placeholder ("LINEST");
466 gnm_func_inc_usage (fd_linest);
467 fd_index = gnm_func_lookup_or_add_placeholder ("INDEX");
468 gnm_func_inc_usage (fd_index);
469 fd_offset = gnm_func_lookup_or_add_placeholder ("OFFSET");
470 gnm_func_inc_usage (fd_offset);
471
472 if (info->show_graph)
473 create_line_plot (&plot, &so);
474
475 dao_set_italic (dao, 0, 0, 0, 0);
476 dao_set_cell (dao, 0, 0, _("Exponential Smoothing"));
477
478 dao_set_format (dao, 0, 1, 0, 1, _("\"\xce\xb1 =\" * 0.000"));
479 dao_set_cell_expr (dao, 0, 1, gnm_expr_new_constant (value_new_float (info->damp_fact)));
480 expr_alpha = dao_get_cellref (dao, 0, 1);
481
482 dao_set_format (dao, 1, 1, 1, 1, _("\"\xce\xb3 =\" * 0.000"));
483 dao_set_cell_expr (dao, 1, 1, gnm_expr_new_constant (value_new_float (info->g_damp_fact)));
484 expr_gamma = dao_get_cellref (dao, 1, 1);
485
486 dao->offset_row = 2;
487
488 for (l = info->base.input, source = 1; l; l = l->next, col++, source++) {
489 GnmValue *val = value_dup ((GnmValue *)l->data);
490 GnmValue *val_c = NULL;
491 GnmExpr const *expr_title = NULL;
492 GnmExpr const *expr_input = NULL;
493 gint height;
494 gint x = 1;
495 gint y = 1;
496 gint *mover;
497 guint delta_x = 1;
498 guint delta_y = 1;
499 gint row;
500 Sheet *sheet;
501 GnmEvalPos ep;
502
503 sheet = val->v_range.cell.a.sheet;
504 eval_pos_init_sheet (&ep, sheet);
505
506 dao_set_italic (dao, col, 0, col, 0);
507 if (info->base.labels) {
508 val_c = value_dup (val);
509 switch (info->base.group_by) {
510 case GROUPED_BY_ROW:
511 val->v_range.cell.a.col++;
512 break;
513 default:
514 val->v_range.cell.a.row++;
515 break;
516 }
517 expr_title = gnm_expr_new_funcall1 (fd_index,
518 gnm_expr_new_constant (val_c));
519
520 dao_set_cell_expr (dao, col, 0, expr_title);
521 } else
522 dao_set_cell_printf
523 (dao, col, 0,
524 (info->base.group_by == GROUPED_BY_ROW ?
525 _("Row %d") : _("Column %d")),
526 source);
527
528 switch (info->base.group_by) {
529 case GROUPED_BY_ROW:
530 height = value_area_get_width (val, &ep);
531 mover = &x;
532 break;
533 default:
534 height = value_area_get_height (val, &ep);
535 mover = &y;
536 break;
537 }
538
539 expr_input = gnm_expr_new_constant (val);
540
541 if (plot != NULL) {
542 attach_series (plot, gnm_go_data_vector_new_expr (sheet, gnm_expr_top_new
543 (gnm_expr_copy (expr_input))));
544 attach_series (plot, dao_go_data_vector (dao, col, 2, col, height + 1));
545 }
546
547 if (dao_cell_is_visible (dao, col+1, 1))
548 {
549 GnmExpr const *expr_linest;
550
551 x = 1;
552 y = 1;
553 *mover = 5;
554 expr_linest = gnm_expr_new_funcall1
555 (fd_linest,
556 analysis_tool_exp_smoothing_funcall5 (fd_offset, gnm_expr_copy (expr_input), 0, 0, y, x));
557 dao_set_cell_expr (dao, col, 1,
558 gnm_expr_new_funcall3 (fd_index,
559 gnm_expr_copy (expr_linest),
560 gnm_expr_new_constant (value_new_int (1)),
561 gnm_expr_new_constant (value_new_int (2))));
562 dao_set_cell_expr (dao, col + 1, 1,
563 gnm_expr_new_funcall3 (fd_index,
564 expr_linest,
565 gnm_expr_new_constant (value_new_int (1)),
566 gnm_expr_new_constant (value_new_int (1))));
567
568 *mover = 1;
569 for (row = 1; row <= height; row++, (*mover)++) {
570 GnmExpr const *LB;
571 GnmExpr const *A;
572 GnmExpr const *LL;
573 GnmExpr const *B;
574 A = gnm_expr_new_binary (gnm_expr_copy (expr_alpha),
575 GNM_EXPR_OP_MULT,
576 gnm_expr_new_funcall3
577 (fd_index,
578 gnm_expr_copy (expr_input),
579 gnm_expr_new_constant(value_new_int(y)),
580 gnm_expr_new_constant(value_new_int(x))));
581 LB = gnm_expr_new_binary (gnm_expr_new_binary (gnm_expr_new_constant
582 (value_new_int (1)),
583 GNM_EXPR_OP_SUB,
584 gnm_expr_copy (expr_alpha)),
585 GNM_EXPR_OP_MULT,
586 gnm_expr_new_binary (make_cellref (0, -1),
587 GNM_EXPR_OP_ADD,
588 make_cellref (1, -1)));
589 dao_set_cell_expr (dao, col, row + 1, gnm_expr_new_binary (A, GNM_EXPR_OP_ADD, LB));
590
591 LL = gnm_expr_new_binary (gnm_expr_copy (expr_gamma),
592 GNM_EXPR_OP_MULT,
593 gnm_expr_new_binary (make_cellref (-1, 0),
594 GNM_EXPR_OP_SUB,
595 make_cellref (-1, -1)));
596 B = gnm_expr_new_binary (gnm_expr_new_binary (gnm_expr_new_constant
597 (value_new_int (1)),
598 GNM_EXPR_OP_SUB,
599 gnm_expr_copy (expr_gamma)),
600 GNM_EXPR_OP_MULT,
601 make_cellref (0, -1));
602 dao_set_cell_expr (dao, col + 1, row + 1, gnm_expr_new_binary (LL, GNM_EXPR_OP_ADD, B));
603 }
604
605 col++;
606
607 if (info->std_error_flag) {
608 col++;
609 dao_set_italic (dao, col, 0, col, 0);
610 dao_set_cell (dao, col, 0, _("Standard Error"));
611
612 y = 0;
613 x = 0;
614 (*mover) = 0;
615 for (row = 1; row <= height+1; row++) {
616 if (row > 1 && (row - 1 - info->df) > 0) {
617 GnmExpr const *expr_offset;
618
619 if (info->base.group_by == GROUPED_BY_ROW)
620 delta_x = row - 1;
621 else
622 delta_y = row - 1;
623
624 expr_offset = analysis_tool_exp_smoothing_funcall5
625 (fd_offset, gnm_expr_copy (expr_input), y, x, delta_y, delta_x);
626
627 dao_set_cell_expr (dao, col, row,
628 gnm_expr_new_funcall1
629 (fd_sqrt,
630 gnm_expr_new_binary
631 (gnm_expr_new_funcall2
632 (fd_sumxmy2,
633 expr_offset,
634 gnm_expr_new_binary(make_rangeref (-2, 1 - row, -2, -1),
635 GNM_EXPR_OP_ADD,
636 make_rangeref (-1, 1 - row, -1, -1))),
637 GNM_EXPR_OP_DIV,
638 gnm_expr_new_constant (value_new_int
639 (row - 1 - info->df)))));
640 } else
641 dao_set_cell_na (dao, col, row);
642 }
643 }
644 gnm_expr_free (expr_input);
645 } else {
646 dao_set_cell (dao, col, 1, _("Holt's trend corrected exponential\n"
647 "smoothing requires at least 2\n"
648 "output columns for each data set."));
649 dao_set_cell_comment (dao, col, 0, _("Holt's trend corrected exponential\n"
650 "smoothing requires at least 2\n"
651 "output columns for each data set."));
652 value_release (val);
653 }
654 }
655
656 if (so != NULL)
657 dao_set_sheet_object (dao, 0, 1, so);
658
659 gnm_expr_free (expr_alpha);
660 gnm_expr_free (expr_gamma);
661 if (fd_sqrt != NULL)
662 gnm_func_dec_usage (fd_sqrt);
663 if (fd_sumxmy2 != NULL)
664 gnm_func_dec_usage (fd_sumxmy2);
665 gnm_func_dec_usage (fd_linest);
666 gnm_func_dec_usage (fd_offset);
667 gnm_func_dec_usage (fd_index);
668
669 dao_redraw_respan (dao);
670
671 return FALSE;
672 }
673
674
675 static gboolean
analysis_tool_exponential_smoothing_engine_ates_run(data_analysis_output_t * dao,analysis_tools_data_exponential_smoothing_t * info)676 analysis_tool_exponential_smoothing_engine_ates_run (data_analysis_output_t *dao,
677 analysis_tools_data_exponential_smoothing_t *info)
678 {
679 GSList *l;
680 gint col = 0, time, maxheight;
681 gint source;
682 SheetObject *so = NULL;
683 GogPlot *plot = NULL;
684 GnmFunc *fd_index;
685 GnmFunc *fd_linest;
686 GnmFunc *fd_average;
687 GnmFunc *fd_if;
688 GnmFunc *fd_mod;
689 GnmFunc *fd_row;
690 GnmFunc *fd_sqrt = NULL;
691 GnmFunc *fd_sumxmy2 = NULL;
692 GnmExpr const *expr_alpha = NULL;
693 GnmExpr const *expr_gamma = NULL;
694 GnmExpr const *expr_delta = NULL;
695
696 if (info->std_error_flag) {
697 fd_sqrt = gnm_func_lookup_or_add_placeholder ("SQRT");
698 gnm_func_inc_usage (fd_sqrt);
699 fd_sumxmy2 = gnm_func_lookup_or_add_placeholder ("SUMXMY2");
700 gnm_func_inc_usage (fd_sumxmy2);
701 }
702
703 fd_linest = gnm_func_lookup_or_add_placeholder ("LINEST");
704 gnm_func_inc_usage (fd_linest);
705 fd_index = gnm_func_lookup_or_add_placeholder ("INDEX");
706 gnm_func_inc_usage (fd_index);
707 fd_average = gnm_func_lookup_or_add_placeholder ("AVERAGE");
708 gnm_func_inc_usage (fd_average);
709 fd_if = gnm_func_lookup_or_add_placeholder ("IF");
710 gnm_func_inc_usage (fd_if);
711 fd_mod = gnm_func_lookup_or_add_placeholder ("mod");
712 gnm_func_inc_usage (fd_mod);
713 fd_row = gnm_func_lookup_or_add_placeholder ("row");
714 gnm_func_inc_usage (fd_row);
715
716 if (info->show_graph)
717 create_line_plot (&plot, &so);
718
719 dao_set_italic (dao, 0, 0, 0, 0);
720 dao_set_cell (dao, 0, 0, _("Exponential Smoothing"));
721
722 dao_set_format (dao, 2, 0, 2, 0, _("\"\xce\xb1 =\" * 0.000"));
723 dao_set_cell_expr (dao, 2, 0, gnm_expr_new_constant (value_new_float (info->damp_fact)));
724 expr_alpha = dao_get_cellref (dao, 2, 0);
725
726 dao_set_format (dao, 3, 0, 3, 0, _("\"\xce\xb3 =\" * 0.000"));
727 dao_set_cell_expr (dao, 3, 0, gnm_expr_new_constant (value_new_float (info->g_damp_fact)));
728 expr_gamma = dao_get_cellref (dao, 3, 0);
729
730 dao_set_format (dao, 4, 0, 4, 0, _("\"\xce\xb4 =\" * 0.000"));
731 dao_set_cell_expr (dao, 4, 0, gnm_expr_new_constant (value_new_float (info->s_damp_fact)));
732 expr_delta = dao_get_cellref (dao, 4, 0);
733
734 dao_set_italic (dao, 0, 2, 0, 2);
735 dao_set_cell (dao, 0, 2, _("Time"));
736
737 maxheight = analysis_tool_calc_length (&info->base);
738
739 dao->offset_row = 2 + info->s_period;
740
741 for (time = 1 - info->s_period; time <= maxheight; time++)
742 dao_set_cell_int (dao, 0, time, time);
743
744 dao->offset_col = 1;
745
746 for (l = info->base.input, source = 1; l; l = l->next, source++) {
747 GnmValue *val = value_dup ((GnmValue *)l->data);
748 GnmValue *val_c = NULL;
749 GnmExpr const *expr_title = NULL;
750 GnmExpr const *expr_input = NULL;
751 GnmExpr const *expr_index = NULL;
752 GnmExpr const *expr_linest;
753 GnmExpr const *expr_level;
754 GnmExpr const *expr_trend;
755 GnmExpr const *expr_season;
756 GnmExpr const *expr_season_est;
757 GnmExpr const *expr_data;
758 GnmExpr const *expr_linest_intercept;
759 GnmExpr const *expr_linest_slope;
760 gint height;
761 GnmEvalPos ep;
762
763 eval_pos_init_sheet (&ep, val->v_range.cell.a.sheet);
764
765 if (dao_cell_is_visible (dao, col+3, 1))
766 {
767 dao_set_italic (dao, col + 1, -info->s_period, col + 3, -info->s_period);
768 set_cell_text_row (dao, col + 1, -info->s_period, _("/Level"
769 "/Trend"
770 "/Seasonal Adjustment"));
771
772 dao_set_italic (dao, col, -info->s_period, col, -info->s_period);
773 if (info->base.labels) {
774 val_c = value_dup (val);
775 switch (info->base.group_by) {
776 case GROUPED_BY_ROW:
777 val->v_range.cell.a.col++;
778 break;
779 default:
780 val->v_range.cell.a.row++;
781 break;
782 }
783 expr_title = gnm_expr_new_funcall1 (fd_index,
784 gnm_expr_new_constant (val_c));
785
786 dao_set_cell_expr (dao, col, -info->s_period, expr_title);
787 } else
788 dao_set_cell_printf
789 (dao, col, -info->s_period,
790 (info->base.group_by == GROUPED_BY_ROW ?
791 _("Row %d") : _("Column %d")),
792 source);
793
794
795 switch (info->base.group_by) {
796 case GROUPED_BY_ROW:
797 height = value_area_get_width (val, &ep);
798 expr_input = gnm_expr_new_constant (val);
799 expr_index = gnm_expr_new_funcall3 (fd_index, gnm_expr_copy (expr_input),
800 gnm_expr_new_constant (value_new_int (1)),
801 make_cellref (-1 - col, 0));
802 break;
803 default:
804 height = value_area_get_height (val, &ep);
805 expr_input = gnm_expr_new_constant (val);
806 expr_index = gnm_expr_new_funcall3 (fd_index, gnm_expr_copy (expr_input),
807 make_cellref (-1 - col, 0),
808 gnm_expr_new_constant (value_new_int (1)));
809 break;
810 }
811
812 expr_data = dao_get_rangeref (dao, col, 1, col, height);
813 expr_linest = gnm_expr_new_funcall1
814 (fd_linest, gnm_expr_copy (expr_data));
815 dao_set_cell_expr (dao, col+1, 0,
816 gnm_expr_new_funcall3 (fd_index,
817 gnm_expr_copy (expr_linest),
818 gnm_expr_new_constant (value_new_int (1)),
819 gnm_expr_new_constant (value_new_int (2))));
820 expr_linest_intercept = dao_get_cellref (dao, col + 1, 0);
821 dao_set_cell_expr (dao, col + 2, 0,
822 gnm_expr_new_funcall3 (fd_index,
823 expr_linest,
824 gnm_expr_new_constant (value_new_int (1)),
825 gnm_expr_new_constant (value_new_int (1))));
826 expr_linest_slope = dao_get_cellref (dao, col + 2, 0);
827 expr_level = gnm_expr_new_binary (gnm_expr_new_binary
828 (gnm_expr_copy (expr_alpha),
829 GNM_EXPR_OP_MULT,
830 gnm_expr_new_binary
831 (make_cellref (-1,0),
832 GNM_EXPR_OP_SUB,
833 make_cellref (2,-info->s_period))),
834 GNM_EXPR_OP_ADD,
835 gnm_expr_new_binary
836 (gnm_expr_new_binary
837 (gnm_expr_new_constant (value_new_int (1)),
838 GNM_EXPR_OP_SUB,
839 gnm_expr_copy (expr_alpha)),
840 GNM_EXPR_OP_MULT,
841 gnm_expr_new_binary
842 (make_cellref (0,-1),
843 GNM_EXPR_OP_ADD,
844 make_cellref (1,-1))));
845 expr_trend = gnm_expr_new_binary (gnm_expr_new_binary
846 (gnm_expr_copy (expr_gamma),
847 GNM_EXPR_OP_MULT,
848 gnm_expr_new_binary
849 (make_cellref (-1,0),
850 GNM_EXPR_OP_SUB,
851 make_cellref (-1,-1))),
852 GNM_EXPR_OP_ADD,
853 gnm_expr_new_binary
854 (gnm_expr_new_binary
855 (gnm_expr_new_constant (value_new_int (1)),
856 GNM_EXPR_OP_SUB,
857 gnm_expr_copy (expr_gamma)),
858 GNM_EXPR_OP_MULT,
859 make_cellref (0,-1)));
860 expr_season = gnm_expr_new_binary (gnm_expr_new_binary
861 (gnm_expr_copy (expr_delta),
862 GNM_EXPR_OP_MULT,
863 gnm_expr_new_binary
864 (make_cellref (-3,0),
865 GNM_EXPR_OP_SUB,
866 make_cellref (-2,0))),
867 GNM_EXPR_OP_ADD,
868 gnm_expr_new_binary
869 (gnm_expr_new_binary
870 (gnm_expr_new_constant (value_new_int (1)),
871 GNM_EXPR_OP_SUB,
872 gnm_expr_copy (expr_delta)),
873 GNM_EXPR_OP_MULT,
874 make_cellref (0,-info->s_period)));
875
876 for (time = 1; time <= maxheight; time++) {
877 dao_set_cell_expr (dao, col, time, gnm_expr_copy (expr_index));
878 dao_set_cell_expr (dao, col+1, time, gnm_expr_copy (expr_level));
879 dao_set_cell_expr (dao, col+2, time, gnm_expr_copy (expr_trend));
880 dao_set_cell_expr (dao, col+3, time, gnm_expr_copy (expr_season));
881 }
882 gnm_expr_free (expr_index);
883 gnm_expr_free (expr_level);
884 gnm_expr_free (expr_trend);
885 gnm_expr_free (expr_season);
886
887 if (plot != NULL) {
888 attach_series (plot, dao_go_data_vector (dao, col, 1, col, height));
889 attach_series (plot, dao_go_data_vector (dao, col+1, 1, col+1, height));
890 }
891
892 /* We still need to calculate the estimates for the seasonal adjustment. */
893
894 expr_season_est = gnm_expr_new_funcall1
895 (fd_average,
896 gnm_expr_new_funcall3
897 (fd_if,
898 gnm_expr_new_binary
899 (gnm_expr_new_funcall2
900 (fd_mod,
901 gnm_expr_new_binary
902 (gnm_expr_new_funcall1
903 (fd_row,
904 gnm_expr_copy (expr_data)),
905 GNM_EXPR_OP_SUB,
906 gnm_expr_new_funcall (fd_row, NULL)),
907 gnm_expr_new_constant (value_new_int (info->s_period))),
908 GNM_EXPR_OP_EQUAL,
909 gnm_expr_new_constant (value_new_int (0))),
910 gnm_expr_new_binary
911 (expr_data,
912 GNM_EXPR_OP_SUB,
913 gnm_expr_new_binary
914 (expr_linest_intercept,
915 GNM_EXPR_OP_ADD,
916 gnm_expr_new_binary
917 (dao_get_rangeref (dao, -1, 1, -1, height),
918 GNM_EXPR_OP_MULT,
919 expr_linest_slope))),
920 gnm_expr_new_constant (value_new_string ("NA"))));
921
922 for (time = 0; time > -info->s_period; time--)
923 dao_set_cell_array_expr (dao, col+3, time, gnm_expr_copy (expr_season_est));
924
925 gnm_expr_free (expr_season_est);
926
927 col += 4;
928 if (info->std_error_flag) {
929 int row;
930
931 dao_set_italic (dao, col, - info->s_period, col, - info->s_period);
932 dao_set_cell (dao, col, - info->s_period, _("Standard Error"));
933
934 for (row = 1; row <= height; row++) {
935 if (row > 1 && (row - info->df) > 0) {
936 GnmExpr const *expr_stderr;
937
938 expr_stderr = gnm_expr_new_funcall1
939 (fd_sqrt,
940 gnm_expr_new_binary
941 (gnm_expr_new_funcall2
942 (fd_sumxmy2,
943 make_rangeref (-4, 1 - row, -4, 0),
944 gnm_expr_new_binary
945 (make_rangeref (-1, 1 - row - info->s_period,
946 -1, - info->s_period),
947 GNM_EXPR_OP_ADD,
948 gnm_expr_new_binary
949 (make_rangeref (-2, - row, -2, -1),
950 GNM_EXPR_OP_ADD,
951 make_rangeref (-3, - row, -3, -1)))),
952 GNM_EXPR_OP_DIV,
953 gnm_expr_new_constant (value_new_int
954 (row - info->df))));
955 dao_set_cell_expr (dao, col, row, expr_stderr);
956 } else
957 dao_set_cell_na (dao, col, row);
958 }
959 col++;
960 }
961 gnm_expr_free (expr_input);
962 } else {
963 dao_set_cell (dao, col, 0, _("The additive Holt-Winters exponential\n"
964 "smoothing method requires at least 4\n"
965 "output columns for each data set."));
966 dao_set_cell_comment (dao, col, 0, _("The additive Holt-Winters exponential\n"
967 "smoothing method requires at least 4\n"
968 "output columns for each data set."));
969 value_release (val);
970 }
971 }
972
973 if (so != NULL)
974 dao_set_sheet_object (dao, 0, 1, so);
975
976 gnm_expr_free (expr_alpha);
977 gnm_expr_free (expr_gamma);
978 gnm_expr_free (expr_delta);
979 if (fd_sqrt != NULL)
980 gnm_func_dec_usage (fd_sqrt);
981 if (fd_sumxmy2 != NULL)
982 gnm_func_dec_usage (fd_sumxmy2);
983 gnm_func_dec_usage (fd_linest);
984 gnm_func_dec_usage (fd_index);
985 gnm_func_dec_usage (fd_average);
986 gnm_func_dec_usage (fd_if);
987 gnm_func_dec_usage (fd_mod);
988 gnm_func_dec_usage (fd_row);
989
990 dao_redraw_respan (dao);
991
992 return FALSE;
993 }
994
995 static gboolean
analysis_tool_exponential_smoothing_engine_mtes_run(data_analysis_output_t * dao,analysis_tools_data_exponential_smoothing_t * info)996 analysis_tool_exponential_smoothing_engine_mtes_run (data_analysis_output_t *dao,
997 analysis_tools_data_exponential_smoothing_t *info)
998 {
999 GSList *l;
1000 gint col = 0, time, maxheight;
1001 gint source;
1002 SheetObject *so = NULL;
1003 GogPlot *plot = NULL;
1004 GnmFunc *fd_index;
1005 GnmFunc *fd_offset;
1006 GnmFunc *fd_linest;
1007 GnmFunc *fd_average;
1008 GnmFunc *fd_if;
1009 GnmFunc *fd_mod;
1010 GnmFunc *fd_row;
1011 GnmFunc *fd_sqrt = NULL;
1012 GnmFunc *fd_sumsq = NULL;
1013 GnmExpr const *expr_alpha = NULL;
1014 GnmExpr const *expr_gamma = NULL;
1015 GnmExpr const *expr_delta = NULL;
1016
1017 if (info->std_error_flag) {
1018 fd_sqrt = gnm_func_lookup_or_add_placeholder ("SQRT");
1019 gnm_func_inc_usage (fd_sqrt);
1020 fd_sumsq = gnm_func_lookup_or_add_placeholder ("SUMSQ");
1021 gnm_func_inc_usage (fd_sumsq);
1022 }
1023
1024 fd_linest = gnm_func_lookup_or_add_placeholder ("LINEST");
1025 gnm_func_inc_usage (fd_linest);
1026 fd_index = gnm_func_lookup_or_add_placeholder ("INDEX");
1027 gnm_func_inc_usage (fd_index);
1028 fd_offset = gnm_func_lookup_or_add_placeholder ("OFFSET");
1029 gnm_func_inc_usage (fd_offset);
1030 fd_average = gnm_func_lookup_or_add_placeholder ("AVERAGE");
1031 gnm_func_inc_usage (fd_average);
1032 fd_if = gnm_func_lookup_or_add_placeholder ("IF");
1033 gnm_func_inc_usage (fd_if);
1034 fd_mod = gnm_func_lookup_or_add_placeholder ("mod");
1035 gnm_func_inc_usage (fd_mod);
1036 fd_row = gnm_func_lookup_or_add_placeholder ("row");
1037 gnm_func_inc_usage (fd_row);
1038
1039 if (info->show_graph)
1040 create_line_plot (&plot, &so);
1041
1042 dao_set_italic (dao, 0, 0, 0, 0);
1043 dao_set_cell (dao, 0, 0, _("Exponential Smoothing"));
1044
1045 dao_set_format (dao, 2, 0, 2, 0, _("\"\xce\xb1 =\" * 0.000"));
1046 dao_set_cell_expr (dao, 2, 0, gnm_expr_new_constant (value_new_float (info->damp_fact)));
1047 expr_alpha = dao_get_cellref (dao, 2, 0);
1048
1049 dao_set_format (dao, 3, 0, 3, 0, _("\"\xce\xb3 =\" * 0.000"));
1050 dao_set_cell_expr (dao, 3, 0, gnm_expr_new_constant (value_new_float (info->g_damp_fact)));
1051 expr_gamma = dao_get_cellref (dao, 3, 0);
1052
1053 dao_set_format (dao, 4, 0, 4, 0, _("\"\xce\xb4 =\" * 0.000"));
1054 dao_set_cell_expr (dao, 4, 0, gnm_expr_new_constant (value_new_float (info->s_damp_fact)));
1055 expr_delta = dao_get_cellref (dao, 4, 0);
1056
1057 dao_set_italic (dao, 0, 2, 0, 2);
1058 dao_set_cell (dao, 0, 2, _("Time"));
1059
1060 maxheight = analysis_tool_calc_length (&info->base);
1061
1062 dao->offset_row = 2 + info->s_period;
1063
1064 for (time = 1 - info->s_period; time <= maxheight; time++)
1065 dao_set_cell_int (dao, 0, time, time);
1066
1067 dao->offset_col = 1;
1068
1069 for (l = info->base.input, source = 1; l; l = l->next, source++) {
1070 GnmValue *val = value_dup ((GnmValue *)l->data);
1071 GnmValue *val_c = NULL;
1072 GnmExpr const *expr_title = NULL;
1073 GnmExpr const *expr_input = NULL;
1074 GnmExpr const *expr_index = NULL;
1075 GnmExpr const *expr_linest;
1076 GnmExpr const *expr_level;
1077 GnmExpr const *expr_trend;
1078 GnmExpr const *expr_season;
1079 GnmExpr const *expr_season_est;
1080 GnmExpr const *expr_season_denom;
1081 GnmExpr const *expr_data;
1082 GnmExpr const *expr_linest_intercept;
1083 GnmExpr const *expr_linest_slope;
1084 gint height, starting_length, i;
1085 GnmExprList *args = NULL;
1086 GnmEvalPos ep;
1087
1088 eval_pos_init_sheet (&ep, val->v_range.cell.a.sheet);
1089
1090 if (dao_cell_is_visible (dao, col+3, 1))
1091 {
1092 dao_set_italic (dao, col + 1, -info->s_period, col + 3, -info->s_period);
1093 set_cell_text_row (dao, col + 1, -info->s_period, _("/Level"
1094 "/Trend"
1095 "/Seasonal Adjustment"));
1096
1097 dao_set_italic (dao, col, -info->s_period, col, -info->s_period);
1098 if (info->base.labels) {
1099 val_c = value_dup (val);
1100 switch (info->base.group_by) {
1101 case GROUPED_BY_ROW:
1102 val->v_range.cell.a.col++;
1103 break;
1104 default:
1105 val->v_range.cell.a.row++;
1106 break;
1107 }
1108 expr_title = gnm_expr_new_funcall1 (fd_index,
1109 gnm_expr_new_constant (val_c));
1110
1111 dao_set_cell_expr (dao, col, -info->s_period, expr_title);
1112 } else
1113 dao_set_cell_printf
1114 (dao, col, -info->s_period,
1115 (info->base.group_by == GROUPED_BY_ROW ?
1116 _("Row %d") : _("Column %d")),
1117 source);
1118
1119
1120 switch (info->base.group_by) {
1121 case GROUPED_BY_ROW:
1122 height = value_area_get_width (val, &ep);
1123 expr_input = gnm_expr_new_constant (val);
1124 expr_index = gnm_expr_new_funcall3 (fd_index, gnm_expr_copy (expr_input),
1125 gnm_expr_new_constant (value_new_int (1)),
1126 make_cellref (-1 - col, 0));
1127 break;
1128 default:
1129 height = value_area_get_height (val, &ep);
1130 expr_input = gnm_expr_new_constant (val);
1131 expr_index = gnm_expr_new_funcall3 (fd_index, gnm_expr_copy (expr_input),
1132 make_cellref (-1 - col, 0),
1133 gnm_expr_new_constant (value_new_int (1)));
1134 break;
1135 }
1136 starting_length = 4 * info->s_period;
1137 if (starting_length > height)
1138 starting_length = height;
1139 expr_data = analysis_tool_exp_smoothing_funcall5 (fd_offset,
1140 dao_get_rangeref (dao, col, 1, col, height),
1141 0, 0, starting_length, 1);
1142 expr_linest = gnm_expr_new_funcall1 (fd_linest, gnm_expr_copy (expr_data));
1143 dao_set_cell_expr (dao, col+1, 0,
1144 gnm_expr_new_funcall3 (fd_index,
1145 gnm_expr_copy (expr_linest),
1146 gnm_expr_new_constant (value_new_int (1)),
1147 gnm_expr_new_constant (value_new_int (2))));
1148 expr_linest_intercept = dao_get_cellref (dao, col + 1, 0);
1149 dao_set_cell_expr (dao, col + 2, 0,
1150 gnm_expr_new_funcall3 (fd_index,
1151 expr_linest,
1152 gnm_expr_new_constant (value_new_int (1)),
1153 gnm_expr_new_constant (value_new_int (1))));
1154 expr_linest_slope = dao_get_cellref (dao, col + 2, 0);
1155 expr_level = gnm_expr_new_binary (gnm_expr_new_binary
1156 (gnm_expr_copy (expr_alpha),
1157 GNM_EXPR_OP_MULT,
1158 gnm_expr_new_binary
1159 (make_cellref (-1,0),
1160 GNM_EXPR_OP_DIV,
1161 make_cellref (2,-info->s_period))),
1162 GNM_EXPR_OP_ADD,
1163 gnm_expr_new_binary
1164 (gnm_expr_new_binary
1165 (gnm_expr_new_constant (value_new_int (1)),
1166 GNM_EXPR_OP_SUB,
1167 gnm_expr_copy (expr_alpha)),
1168 GNM_EXPR_OP_MULT,
1169 gnm_expr_new_binary
1170 (make_cellref (0,-1),
1171 GNM_EXPR_OP_ADD,
1172 make_cellref (1,-1))));
1173 expr_trend = gnm_expr_new_binary (gnm_expr_new_binary
1174 (gnm_expr_copy (expr_gamma),
1175 GNM_EXPR_OP_MULT,
1176 gnm_expr_new_binary
1177 (make_cellref (-1,0),
1178 GNM_EXPR_OP_SUB,
1179 make_cellref (-1,-1))),
1180 GNM_EXPR_OP_ADD,
1181 gnm_expr_new_binary
1182 (gnm_expr_new_binary
1183 (gnm_expr_new_constant (value_new_int (1)),
1184 GNM_EXPR_OP_SUB,
1185 gnm_expr_copy (expr_gamma)),
1186 GNM_EXPR_OP_MULT,
1187 make_cellref (0,-1)));
1188 expr_season = gnm_expr_new_binary (gnm_expr_new_binary
1189 (gnm_expr_copy (expr_delta),
1190 GNM_EXPR_OP_MULT,
1191 gnm_expr_new_binary
1192 (make_cellref (-3,0),
1193 GNM_EXPR_OP_DIV,
1194 make_cellref (-2,0))),
1195 GNM_EXPR_OP_ADD,
1196 gnm_expr_new_binary
1197 (gnm_expr_new_binary
1198 (gnm_expr_new_constant (value_new_int (1)),
1199 GNM_EXPR_OP_SUB,
1200 gnm_expr_copy (expr_delta)),
1201 GNM_EXPR_OP_MULT,
1202 make_cellref (0,-info->s_period)));
1203
1204 for (time = 1; time <= maxheight; time++) {
1205 dao_set_cell_expr (dao, col, time, gnm_expr_copy (expr_index));
1206 dao_set_cell_expr (dao, col+1, time, gnm_expr_copy (expr_level));
1207 dao_set_cell_expr (dao, col+2, time, gnm_expr_copy (expr_trend));
1208 dao_set_cell_expr (dao, col+3, time, gnm_expr_copy (expr_season));
1209 }
1210 gnm_expr_free (expr_index);
1211 gnm_expr_free (expr_level);
1212 gnm_expr_free (expr_trend);
1213 gnm_expr_free (expr_season);
1214
1215 if (plot != NULL) {
1216 attach_series (plot, dao_go_data_vector (dao, col, 1, col, height));
1217 attach_series (plot, dao_go_data_vector (dao, col+1, 1, col+1, height));
1218 }
1219
1220 /* We still need to calculate the estimates for the seasonal adjustment. */
1221 /* = average(if(mod(row(expr_data)-row(),4)=0,expr_data/($E$7+$F$7*$C$8:$C$23),"NA")) */
1222 for (i = 0; i<info->s_period; i++) {
1223 expr_season_est = gnm_expr_new_funcall1
1224 (fd_average,
1225 gnm_expr_new_funcall3
1226 (fd_if,
1227 gnm_expr_new_binary
1228 (gnm_expr_new_funcall2
1229 (fd_mod,
1230 gnm_expr_new_binary
1231 (gnm_expr_new_funcall1
1232 (fd_row,
1233 gnm_expr_copy (expr_data)),
1234 GNM_EXPR_OP_SUB,
1235 gnm_expr_new_constant (value_new_int (i))),
1236 gnm_expr_new_constant (value_new_int (info->s_period))),
1237 GNM_EXPR_OP_EQUAL,
1238 gnm_expr_new_constant (value_new_int (0))),
1239 gnm_expr_new_binary
1240 (gnm_expr_copy (expr_data),
1241 GNM_EXPR_OP_DIV,
1242 gnm_expr_new_binary
1243 (gnm_expr_copy (expr_linest_intercept),
1244 GNM_EXPR_OP_ADD,
1245 gnm_expr_new_binary
1246 (analysis_tool_exp_smoothing_funcall5
1247 (fd_offset, dao_get_rangeref
1248 (dao, -1, 1, -1, height), 0, 0, starting_length, 1),
1249 GNM_EXPR_OP_MULT,
1250 gnm_expr_copy (expr_linest_slope)))),
1251 gnm_expr_new_constant (value_new_string ("NA"))));
1252 args = gnm_expr_list_prepend (args, expr_season_est);
1253 }
1254 expr_season_denom = gnm_expr_new_funcall (fd_average, args);
1255
1256 expr_season_est = gnm_expr_new_funcall1
1257 (fd_average,
1258 gnm_expr_new_funcall3
1259 (fd_if,
1260 gnm_expr_new_binary
1261 (gnm_expr_new_funcall2
1262 (fd_mod,
1263 gnm_expr_new_binary
1264 (gnm_expr_new_funcall1
1265 (fd_row,
1266 gnm_expr_copy (expr_data)),
1267 GNM_EXPR_OP_SUB,
1268 gnm_expr_new_funcall (fd_row, NULL)),
1269 gnm_expr_new_constant (value_new_int (info->s_period))),
1270 GNM_EXPR_OP_EQUAL,
1271 gnm_expr_new_constant (value_new_int (0))),
1272 gnm_expr_new_binary
1273 (expr_data,
1274 GNM_EXPR_OP_DIV,
1275 gnm_expr_new_binary
1276 (expr_linest_intercept,
1277 GNM_EXPR_OP_ADD,
1278 gnm_expr_new_binary
1279 (analysis_tool_exp_smoothing_funcall5
1280 (fd_offset, dao_get_rangeref
1281 (dao, -1, 1, -1, height), 0, 0, starting_length, 1),
1282 GNM_EXPR_OP_MULT,
1283 expr_linest_slope))),
1284 gnm_expr_new_constant (value_new_string ("NA"))));
1285
1286 expr_season_est = gnm_expr_new_binary (expr_season_est,
1287 GNM_EXPR_OP_DIV,
1288 expr_season_denom);
1289
1290 for (time = 0; time > -info->s_period; time--)
1291 dao_set_cell_array_expr (dao, col+3, time, gnm_expr_copy (expr_season_est));
1292
1293 gnm_expr_free (expr_season_est);
1294 col += 4;
1295 if (info->std_error_flag) {
1296 int row;
1297
1298 dao_set_italic (dao, col, - info->s_period, col, - info->s_period);
1299 dao_set_cell (dao, col, - info->s_period, _("Standard Error"));
1300
1301 for (row = 1; row <= height; row++) {
1302 if (row > 1 && (row - info->df) > 0) {
1303 GnmExpr const *expr_stderr;
1304 GnmExpr const *expr_denom;
1305
1306 expr_denom = gnm_expr_new_binary
1307 (gnm_expr_new_binary
1308 (make_rangeref (-2, - row, -2, -1),
1309 GNM_EXPR_OP_ADD,
1310 make_rangeref (-3, - row, -3, -1)),
1311 GNM_EXPR_OP_MULT,
1312 make_rangeref (-1, 1 - row - info->s_period,
1313 -1, - info->s_period));
1314 expr_stderr = gnm_expr_new_funcall1
1315 (fd_sqrt,
1316 gnm_expr_new_binary
1317 (gnm_expr_new_funcall1
1318 (fd_sumsq,
1319 gnm_expr_new_binary
1320 (gnm_expr_new_binary
1321 (make_rangeref (-4, 1 - row, -4, 0),
1322 GNM_EXPR_OP_SUB,
1323 gnm_expr_copy (expr_denom)),
1324 GNM_EXPR_OP_DIV,
1325 expr_denom)),
1326 GNM_EXPR_OP_DIV,
1327 gnm_expr_new_constant (value_new_int
1328 (row - info->df))));
1329 dao_set_cell_array_expr (dao, col, row, expr_stderr);
1330 } else
1331 dao_set_cell_na (dao, col, row);
1332 }
1333 col++;
1334 }
1335 gnm_expr_free (expr_input);
1336 } else {
1337 dao_set_cell (dao, col, 0, _("The multiplicative Holt-Winters exponential\n"
1338 "smoothing method requires at least 4\n"
1339 "output columns for each data set."));
1340 dao_set_cell_comment (dao, col, 0, _("The multiplicative Holt-Winters exponential\n"
1341 "smoothing method requires at least 4\n"
1342 "output columns for each data set."));
1343 value_release (val);
1344 }
1345
1346 }
1347
1348 if (so != NULL)
1349 dao_set_sheet_object (dao, 0, 1, so);
1350
1351 gnm_expr_free (expr_alpha);
1352 gnm_expr_free (expr_gamma);
1353 gnm_expr_free (expr_delta);
1354 if (fd_sqrt != NULL)
1355 gnm_func_dec_usage (fd_sqrt);
1356 if (fd_sumsq != NULL)
1357 gnm_func_dec_usage (fd_sumsq);
1358 gnm_func_dec_usage (fd_linest);
1359 gnm_func_dec_usage (fd_offset);
1360 gnm_func_dec_usage (fd_index);
1361 gnm_func_dec_usage (fd_average);
1362 gnm_func_dec_usage (fd_if);
1363 gnm_func_dec_usage (fd_mod);
1364 gnm_func_dec_usage (fd_row);
1365
1366 dao_redraw_respan (dao);
1367
1368 return FALSE;
1369 }
1370
1371 gboolean
analysis_tool_exponential_smoothing_engine(G_GNUC_UNUSED GOCmdContext * gcc,data_analysis_output_t * dao,gpointer specs,analysis_tool_engine_t selector,gpointer result)1372 analysis_tool_exponential_smoothing_engine (G_GNUC_UNUSED GOCmdContext *gcc, data_analysis_output_t *dao,
1373 gpointer specs,
1374 analysis_tool_engine_t selector,
1375 gpointer result)
1376 {
1377 analysis_tools_data_exponential_smoothing_t *info = specs;
1378 int n = 0, m;
1379
1380 switch (selector) {
1381 case TOOL_ENGINE_UPDATE_DESCRIPTOR:
1382 return (dao_command_descriptor (dao, _("Exponential Smoothing (%s)"), result)
1383 == NULL);
1384 case TOOL_ENGINE_UPDATE_DAO:
1385 prepare_input_range (&info->base.input, info->base.group_by);
1386 n = 1;
1387 m = 3 + analysis_tool_calc_length (specs);
1388 if (info->std_error_flag)
1389 n++;
1390 if (info->es_type == exp_smoothing_type_ses_r) {
1391 m++;
1392 }
1393 if (info->es_type == exp_smoothing_type_des) {
1394 n++;
1395 m++;
1396 }
1397 if (info->es_type == exp_smoothing_type_ates ||
1398 info->es_type == exp_smoothing_type_mtes) {
1399 n += 4;
1400 m += info->s_period;
1401 }
1402 dao_adjust (dao,
1403 n * g_slist_length (info->base.input), m);
1404 return FALSE;
1405 case TOOL_ENGINE_CLEAN_UP:
1406 return analysis_tool_generic_clean (specs);
1407 case TOOL_ENGINE_LAST_VALIDITY_CHECK:
1408 return FALSE;
1409 case TOOL_ENGINE_PREPARE_OUTPUT_RANGE:
1410 dao_prepare_output (NULL, dao, _("Exponential Smoothing"));
1411 return FALSE;
1412 case TOOL_ENGINE_FORMAT_OUTPUT_RANGE:
1413 return dao_format_output (dao, _("Exponential Smoothing"));
1414 case TOOL_ENGINE_PERFORM_CALC:
1415 default:
1416 switch (info->es_type) {
1417 case exp_smoothing_type_mtes:
1418 return analysis_tool_exponential_smoothing_engine_mtes_run (dao, specs);
1419 case exp_smoothing_type_ates:
1420 return analysis_tool_exponential_smoothing_engine_ates_run (dao, specs);
1421 case exp_smoothing_type_des:
1422 return analysis_tool_exponential_smoothing_engine_des_run (dao, specs);
1423 case exp_smoothing_type_ses_r:
1424 return analysis_tool_exponential_smoothing_engine_ses_r_run (dao, specs);
1425 case exp_smoothing_type_ses_h:
1426 default:
1427 return analysis_tool_exponential_smoothing_engine_ses_h_run (dao, specs);
1428 }
1429 }
1430 return TRUE; /* We shouldn't get here */
1431 }
1432