Skip to content

Commit

Permalink
fixes for "dataset addobs" in the panel case
Browse files Browse the repository at this point in the history
  • Loading branch information
AllinCottrell committed Jan 22, 2025
1 parent 084d446 commit 178819f
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 90 deletions.
34 changes: 23 additions & 11 deletions gui/dialogs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3542,26 +3542,38 @@ static void set_add_obs (GtkButton *b, int *n_add)
}

int add_obs_dialog (const char *blurb, int addmin,
gretlopt opt, GtkWidget *parent)
int *optval, GtkWidget *parent)
{
int step, panel = dataset_is_panel(dataset);
GtkWidget *dlg, *vbox, *hbox;
GtkWidget *addspin, *tmp;
int n_add = -1;

if (panel && !(opt & OPT_T)) {
addmin = dataset->pd;
step = dataset->pd;
} else {
step = 1;
}

dlg = gretl_dialog_new(_("Add observations"), parent,
GRETL_DLG_MODAL | GRETL_DLG_BLOCK);

vbox = gtk_dialog_get_content_area(GTK_DIALOG(dlg));

if (blurb != NULL) {
if (dataset_is_panel(dataset) && addmin > 0) {
const char *opts[] = {
_("in the cross-sectional dimension"),
_("in the time dimension")
};
GSList *group = NULL;
GtkWidget *b;
int i;

for (i=0; i<2; i++) {
b = gtk_radio_button_new_with_label(group, _(opts[i]));
gtk_box_pack_start(GTK_BOX(vbox), b, TRUE, TRUE, 0);
g_object_set_data(G_OBJECT(b), "action", GINT_TO_POINTER(i));
g_signal_connect(G_OBJECT(b), "clicked",
G_CALLBACK(set_radio_opt), optval);
if (i == 0) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), TRUE);
}
group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(b));
}
} else if (blurb != NULL) {
hbox = gtk_hbox_new(FALSE, 5);
tmp = gtk_label_new(blurb);
gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);
Expand All @@ -3572,7 +3584,7 @@ int add_obs_dialog (const char *blurb, int addmin,
tmp = gtk_label_new(_("Number of observations to add:"));
gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 5);

addspin = gtk_spin_button_new_with_range(addmin, 10000, step);
addspin = gtk_spin_button_new_with_range(1, 10000, 1);
gtk_entry_set_activates_default(GTK_ENTRY(addspin), TRUE);
gtk_box_pack_start(GTK_BOX(hbox), addspin, TRUE, TRUE, 5);

Expand Down
2 changes: 1 addition & 1 deletion gui/dialogs.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ int combo_selector_dialog (GList *list, const char *msg,
int yes_no_help_dialog (const char *msg, int hcode, int deflt);

int add_obs_dialog (const char *blurb, int addmin,
gretlopt opt, GtkWidget *parent);
int *optval, GtkWidget *parent);

int forecast_dialog (int t1min, int t1max, int *t1,
int t2min, int t2max, int *t2,
Expand Down
24 changes: 7 additions & 17 deletions gui/library.c
Original file line number Diff line number Diff line change
Expand Up @@ -6465,34 +6465,24 @@ void add_index (GtkAction *action)

void do_add_obs (void)
{
gretlopt opt = OPT_A;
int timedim = 0;
int n, err = 0;

if (dataset_is_panel(dataset)) {
const char *opts[] = {
_("in the cross-sectional dimension"),
_("in the time dimension")
};
int resp;

resp = radio_dialog(NULL, _("Add observations"),
opts, 2, 0, 0, NULL);
if (resp == GRETL_CANCEL) {
return;
}
if (resp == 1) {
opt |= OPT_T;
}
n = add_obs_dialog(NULL, 1, &timedim, NULL);
} else {
n = add_obs_dialog(NULL, 1, NULL, NULL);
}

n = add_obs_dialog(NULL, 1, opt, NULL);

if (n > 0) {
gretlopt opt = timedim ? OPT_T : OPT_A;

err = dataset_add_observations(dataset, n, opt);
if (err) {
gui_errmsg(err);
} else {
mark_dataset_as_modified();
/* FIXME record command */
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions gui/ssheet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1249,7 +1249,7 @@ static void sheet_add_obs_direct (Spreadsheet *sheet)
if (dataset->markers) {
new_case_dialog(sheet);
} else if (sheet->point == SHEET_AT_END) {
int n = add_obs_dialog(NULL, 1, OPT_NONE, sheet->win);
int n = add_obs_dialog(NULL, 1, NULL, sheet->win);

if (n > 0) {
real_add_new_obs(sheet, NULL, n);
Expand Down Expand Up @@ -1314,7 +1314,6 @@ static void build_sheet_popup (Spreadsheet *sheet)
G_CALLBACK(popup_sheet_add_obs),
sheet);
}

if (sheet->flags & SHEET_INSERT_OBS_OK) {
add_popup_item(_("Insert Observation"), sheet->popup,
G_CALLBACK(popup_sheet_insert_obs),
Expand Down Expand Up @@ -3073,8 +3072,10 @@ static void adjust_add_menu_state (Spreadsheet *sheet)
if (complex_subsampled() || dataset->t2 < dataset->n - 1) {
sheet->flags &= ~SHEET_ADD_OBS_OK;
sheet->flags &= ~SHEET_INSERT_OBS_OK;
} else if ((sheet->flags & SHEET_SHORT_VARLIST) ||
dataset_is_panel(dataset)) {
} else if (dataset_is_panel(dataset)) {
sheet->flags &= ~SHEET_ADD_OBS_OK;
sheet->flags &= ~SHEET_INSERT_OBS_OK;
} else if (sheet->flags & SHEET_SHORT_VARLIST) {
sheet->flags &= ~SHEET_INSERT_OBS_OK;
}
}
Expand Down
71 changes: 53 additions & 18 deletions lib/src/dataset.c
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,25 @@ static void maybe_extend_dummies (DATASET *dset, int oldn)
}
}

static void maybe_extend_indices (DATASET *dset, int oldn)
{
int minval, incr;
int i, t;

for (i=1; i<dset->v; i++) {
if (is_panel_time_var(dset, i, oldn, &minval, &incr)) {
for (t=oldn; t<dset->n; t++) {
if (t % dset->pd == 0) {
dset->Z[i][t] = minval;
} else {
dset->Z[i][t] = dset->Z[i][t-1] + incr;
}
}
}
/* FIXME unit index */
}
}

static void maybe_extend_lags (DATASET *dset, int t1, int t2)
{
int i, j, t, p;
Expand Down Expand Up @@ -1087,10 +1106,6 @@ static int real_dataset_add_observations (DATASET *dset, int n,
return 0;
}

if (dataset_is_panel(dset) && n % dset->pd != 0) {
return E_PDWRONG;
}

bign = oldn + n;

for (i=0; i<dset->v; i++) {
Expand Down Expand Up @@ -1137,6 +1152,9 @@ static int real_dataset_add_observations (DATASET *dset, int n,
maybe_extend_dummies(dset, oldn);
}
maybe_extend_lags(dset, oldn, dset->n - 1);
} else if (dataset_is_panel(dset)) {
maybe_extend_dummies(dset, oldn);
maybe_extend_indices(dset, oldn);
} else {
maybe_extend_index(dset, oldn);
}
Expand Down Expand Up @@ -1321,6 +1339,9 @@ int dataset_add_observations (DATASET *dset, int n, gretlopt opt)
if (opt & OPT_T) {
return panel_dataset_extend_time(dset, n, opt);
} else {
if (dataset_is_panel(dset)) {
n *= dset->pd;
}
return real_dataset_add_observations(dset, n, opt);
}
}
Expand Down Expand Up @@ -3310,7 +3331,11 @@ int series_record_display_name (DATASET *dset, int i,
return 0;
}

static int add_obs (int n, DATASET *dset, gretlopt opt, PRN *prn)
/* called by modify_dataset(), below, in response to the command
"dataset addobs n"
*/

static int add_obs (DATASET *dset, int n, gretlopt opt, PRN *prn)
{
int err = 0;

Expand All @@ -3319,15 +3344,24 @@ static int add_obs (int n, DATASET *dset, gretlopt opt, PRN *prn)
err = E_DATA;
} else if (n <= 0) {
err = E_PARSE;
} else if (opt & OPT_T) {
/* extending panel time */
err = panel_dataset_extend_time(dset, n, opt | OPT_A);
if (!err) {
pprintf(prn, _("Panel time extended by %d observations"), n);
pputc(prn, '\n');
}
} else if (dataset_is_panel(dset)) {
if (opt & OPT_T) {
/* extending the time dimension */
err = panel_dataset_extend_time(dset, n, opt | OPT_A);
if (!err) {
pprintf(prn, _("Panel time extended by %d observations"), n);
pputc(prn, '\n');
}
} else {
err = real_dataset_add_observations(dset, n * dset->pd, OPT_A);
if (!err) {
pprintf(prn, _("Dataset extended by %d units"), n);
pputc(prn, '\n');
extend_function_sample_range(n * dset->pd);
}
}
} else {
err = dataset_add_observations(dset, n, OPT_A);
err = real_dataset_add_observations(dset, n, OPT_A);
if (!err) {
pprintf(prn, _("Dataset extended by %d observations"), n);
pputc(prn, '\n');
Expand All @@ -3338,7 +3372,7 @@ static int add_obs (int n, DATASET *dset, gretlopt opt, PRN *prn)
return err;
}

static int insert_obs (int n, DATASET *dset, PRN *prn)
static int insert_obs (DATASET *dset, int i, PRN *prn)
{
int err = 0;

Expand All @@ -3347,10 +3381,11 @@ static int insert_obs (int n, DATASET *dset, PRN *prn)
err = E_DATA;
} else if (dataset_is_panel(dset)) {
err = E_PDWRONG;
} else if (n <= 0 || n > dset->n) {
} else if (i <= 0 || i > dset->n) {
err = E_DATA;
} else {
err = real_insert_observation(n - 1, dset);
/* convert to 0-based */
err = real_insert_observation(i - 1, dset);
}

return err;
Expand Down Expand Up @@ -3824,9 +3859,9 @@ int modify_dataset (DATASET *dset, int op, const int *list,
}

if (op == DS_ADDOBS) {
err = add_obs(k, dset, opt, prn);
err = add_obs(dset, k, opt, prn);
} else if (op == DS_INSOBS) {
err = insert_obs(k, dset, prn);
err = insert_obs(dset, k, prn);
} else if (op == DS_COMPACT) {
err = compact_dataset_wrapper(param, dset, k, opt);
} else if (op == DS_EXPAND) {
Expand Down
83 changes: 44 additions & 39 deletions lib/src/geneval.c
Original file line number Diff line number Diff line change
Expand Up @@ -13994,12 +13994,11 @@ static int scan_to_vector (NODE *n, const char *fmt,
return nmax;
}

/* Common code to handle printf(), sprintf() and sscanf(). The @l node
is non-NULL only in the case of sscanf(). The @m node is a format
string in all cases, and the @r node holds args or NULL.
/* Code to handle printf() and sprintf(). The @l node is a
format string; the @r node holds varargs or may be NULL.
*/

static NODE *eval_print_scan (NODE *l, NODE *m, NODE *r, int f, parser *p)
static NODE *print_func_node (NODE *l, NODE *r, int f, parser *p)
{
NODE *ret;

Expand All @@ -14010,41 +14009,48 @@ static NODE *eval_print_scan (NODE *l, NODE *m, NODE *r, int f, parser *p)
}

if (ret != NULL) {
const char *fmt = m->v.str;
const char *lstr = NULL;
const char *fmt = l->v.str;
const char *args = NULL;
int n = 0;

if (l != NULL && l->t == ARRAY) {
/* scanning array of strings to vector */
n = scan_to_vector(l, fmt, r->v.str, &p->err);
goto finish;
} else if (l != NULL) {
/* sscanf() only */
if (l->t == STR) {
lstr = l->v.str;
} else {
p->err = E_INVARG;
}
if (!null_node(r)) {
args = r->v.str;
}
if (f == F_SPRINTF) {
ret->v.str = do_sprintf_function(fmt, args, p->dset, &p->err);
} else {
p->err = do_printf(fmt, args, p->dset, p->prn, &n);
}
if (!p->err && f == F_PRINTF) {
ret->v.xval = n;
}
}

if (!p->err) {
const char *args = NULL;
return ret;
}

if (!null_node(r)) {
args = r->v.str;
}
if (f == F_SSCANF) {
p->err = do_sscanf(lstr, fmt, args, p->dset, &n);
} else if (f == F_SPRINTF) {
ret->v.str = do_sprintf_function(fmt, args, p->dset, &p->err);
} else {
p->err = do_printf(fmt, args, p->dset, p->prn, &n);
}
}
/* Code to handle sscanf(). The @l node must be a string, or array of
strings; @m holds a format string; and @r holds varargs.
*/

finish:
static NODE *sscanf_node (NODE *l, NODE *m, NODE *r, parser *p)
{
NODE *ret = aux_scalar_node(p);

if (ret != NULL) {
const char *fmt = m->v.str;
const char *args = r->v.str;
const char *src = NULL;
int n = 0;

if (!p->err && f != F_SPRINTF) {
if (l->t == ARRAY) {
/* scanning array of strings to vector */
n = scan_to_vector(l, fmt, r->v.str, &p->err);
} else {
src = l->v.str;
p->err = do_sscanf(src, fmt, args, p->dset, &n);
}
if (!p->err) {
ret->v.xval = n;
}
}
Expand Down Expand Up @@ -19152,18 +19158,17 @@ static NODE *eval (NODE *t, parser *p)
case F_PRINTF:
case F_SPRINTF:
if (l->t == STR && null_or_string(r)) {
ret = eval_print_scan(NULL, l, r, t->t, p);
ret = print_func_node(l, r, t->t, p);
} else {
node_type_error(t->t, 0, STR, NULL, p);
p->err = E_INVARG;
}
break;
case F_SSCANF:
if (l->t == STR && m->t == STR && r->t == STR) {
ret = eval_print_scan(l, m, r, t->t, p);
} else if (l->t == ARRAY && m->t == STR && r->t == STR) {
ret = eval_print_scan(l, m, r, t->t, p);
if ((l->t == STR || l->t == ARRAY) &&
(m->t == STR && r->t == STR)) {
ret = sscanf_node(l, m, r, p);
} else {
node_type_error(t->t, 0, STR, NULL, p);
p->err = E_INVARG;
}
break;
case F_BESSEL:
Expand Down
Loading

0 comments on commit 178819f

Please sign in to comment.