dataset.c (gretl-2020d.tar.xz) | : | dataset.c (gretl-2020e.tar.xz) | ||
---|---|---|---|---|
skipping to change at line 46 | skipping to change at line 46 | |||
char display_name[MAXDISP]; | char display_name[MAXDISP]; | |||
char parent[VNAMELEN]; | char parent[VNAMELEN]; | |||
VarFlags flags; | VarFlags flags; | |||
char compact_method; | char compact_method; | |||
gint64 mtime; | gint64 mtime; | |||
short transform; /* note: command index of transform */ | short transform; /* note: command index of transform */ | |||
short lag; | short lag; | |||
short stack_level; | short stack_level; | |||
short midas_period; | short midas_period; | |||
char midas_freq; | char midas_freq; | |||
short orig_pd; | ||||
series_table *st; | series_table *st; | |||
}; | }; | |||
static int pad_daily_data (DATASET *dset, int pd, PRN *prn); | static int pad_daily_data (DATASET *dset, int pd, PRN *prn); | |||
/** | /** | |||
* check_dataset_is_changed: | * check_dataset_is_changed: | |||
* @dset: dataset to check. | * @dset: dataset to check. | |||
* | * | |||
* Returns: 1 if @dset has been modified since | * Returns: 1 if @dset has been modified since | |||
skipping to change at line 312 | skipping to change at line 313 | |||
static void gretl_varinfo_init (VARINFO *vinfo) | static void gretl_varinfo_init (VARINFO *vinfo) | |||
{ | { | |||
vinfo->label = NULL; | vinfo->label = NULL; | |||
vinfo->display_name[0] = '\0'; | vinfo->display_name[0] = '\0'; | |||
vinfo->parent[0] = '\0'; | vinfo->parent[0] = '\0'; | |||
vinfo->flags = 0; | vinfo->flags = 0; | |||
vinfo->transform = 0; | vinfo->transform = 0; | |||
vinfo->lag = 0; | vinfo->lag = 0; | |||
vinfo->midas_period = 0; | vinfo->midas_period = 0; | |||
vinfo->midas_freq = 0; | vinfo->midas_freq = 0; | |||
vinfo->orig_pd = 0; | ||||
vinfo->compact_method = COMPACT_NONE; | vinfo->compact_method = COMPACT_NONE; | |||
vinfo->mtime = 0; | vinfo->mtime = 0; | |||
vinfo->stack_level = gretl_function_depth(); | vinfo->stack_level = gretl_function_depth(); | |||
vinfo->st = NULL; | vinfo->st = NULL; | |||
} | } | |||
static void copy_label (char **targ, const char *src) | static void copy_label (char **targ, const char *src) | |||
{ | { | |||
free(*targ); | free(*targ); | |||
if (src == NULL) { | if (src == NULL) { | |||
skipping to change at line 360 | skipping to change at line 362 | |||
return; | return; | |||
} | } | |||
copy_label(&targ->label, src->label); | copy_label(&targ->label, src->label); | |||
strcpy(targ->display_name, src->display_name); | strcpy(targ->display_name, src->display_name); | |||
strcpy(targ->parent, src->parent); | strcpy(targ->parent, src->parent); | |||
targ->flags = src->flags; | targ->flags = src->flags; | |||
targ->transform = src->transform; | targ->transform = src->transform; | |||
targ->lag = src->lag; | targ->lag = src->lag; | |||
targ->midas_period = src->midas_period; | targ->midas_period = src->midas_period; | |||
targ->midas_freq = src->midas_freq; | targ->midas_freq = src->midas_freq; | |||
targ->orig_pd = src->orig_pd; | ||||
targ->compact_method = src->compact_method; | targ->compact_method = src->compact_method; | |||
targ->stack_level = src->stack_level; | targ->stack_level = src->stack_level; | |||
if (src->st != NULL) { | if (src->st != NULL) { | |||
targ->st = series_table_copy(src->st); | targ->st = series_table_copy(src->st); | |||
} | } | |||
} | } | |||
/* For use in the context of returning from a sub-sampled | /* For use in the context of returning from a sub-sampled | |||
dataset to the full one: trim off series names and | dataset to the full one: trim off series names and | |||
"varinfo" beyond the index @nv, which gives the number | "varinfo" beyond the index @nv, which gives the number | |||
skipping to change at line 1001 | skipping to change at line 1004 | |||
} | } | |||
dataset_set_nobs(dset, bign); | dataset_set_nobs(dset, bign); | |||
if (opt & OPT_A) { | if (opt & OPT_A) { | |||
maybe_extend_trends(dset, oldn); | maybe_extend_trends(dset, oldn); | |||
maybe_extend_dummies(dset, oldn); | maybe_extend_dummies(dset, oldn); | |||
} | } | |||
/* does daily data need special handling? */ | /* does daily data need special handling? */ | |||
ntodate(dset->endobs, bign - 1, dset); | ntolabel(dset->endobs, bign - 1, dset); | |||
return err; | return err; | |||
} | } | |||
static int panel_dataset_extend_time (DATASET *dset, int n) | static int panel_dataset_extend_time (DATASET *dset, int n) | |||
{ | { | |||
double *utmp, *vtmp; | double *utmp, *vtmp; | |||
char **S = NULL; | char **S = NULL; | |||
int newT, oldT = dset->pd; | int newT, oldT = dset->pd; | |||
int oldn = dset->n; | int oldn = dset->n; | |||
skipping to change at line 1131 | skipping to change at line 1134 | |||
dset->S = S; | dset->S = S; | |||
S = NULL; | S = NULL; | |||
} | } | |||
if (dset->t2 == dset->n - 1) { | if (dset->t2 == dset->n - 1) { | |||
dset->t2 = bign - 1; | dset->t2 = bign - 1; | |||
} | } | |||
dataset_set_nobs(dset, bign); | dataset_set_nobs(dset, bign); | |||
dset->pd = newT; | dset->pd = newT; | |||
ntodate(dset->endobs, bign - 1, dset); | ntolabel(dset->endobs, bign - 1, dset); | |||
bailout: | bailout: | |||
free(utmp); | free(utmp); | |||
if (S != NULL) { | if (S != NULL) { | |||
strings_array_free(S, bign); | strings_array_free(S, bign); | |||
} | } | |||
return err; | return err; | |||
} | } | |||
skipping to change at line 1206 | skipping to change at line 1209 | |||
strcpy(dset->S[t], dset->S[t-1]); | strcpy(dset->S[t], dset->S[t-1]); | |||
} | } | |||
sprintf(dset->S[pos], "%d", pos + 1); | sprintf(dset->S[pos], "%d", pos + 1); | |||
} | } | |||
if (dset->t2 == dset->n - 1) { | if (dset->t2 == dset->n - 1) { | |||
dset->t2 = n - 1; | dset->t2 = n - 1; | |||
} | } | |||
dataset_set_nobs(dset, n); | dataset_set_nobs(dset, n); | |||
ntodate(dset->endobs, n - 1, dset); | ntolabel(dset->endobs, n - 1, dset); | |||
return err; | return err; | |||
} | } | |||
/** | /** | |||
* dataset_drop_observations: | * dataset_drop_observations: | |||
* @dset: pointer to dataset. | * @dset: pointer to dataset. | |||
* @n: number of observations to drop. | * @n: number of observations to drop. | |||
* | * | |||
* Deletes @n observations from the end of each series in the | * Deletes @n observations from the end of each series in the | |||
skipping to change at line 1269 | skipping to change at line 1272 | |||
} | } | |||
} | } | |||
if (dset->t2 > newn - 1) { | if (dset->t2 > newn - 1) { | |||
dset->t2 = newn - 1; | dset->t2 = newn - 1; | |||
} | } | |||
dataset_set_nobs(dset, newn); | dataset_set_nobs(dset, newn); | |||
/* does daily data need special handling? */ | /* does daily data need special handling? */ | |||
ntodate(dset->endobs, newn - 1, dset); | ntolabel(dset->endobs, newn - 1, dset); | |||
return 0; | return 0; | |||
} | } | |||
/** | /** | |||
* dataset_shrink_obs_range: | * dataset_shrink_obs_range: | |||
* @dset: pointer to dataset. | * @dset: pointer to dataset. | |||
* | * | |||
* Truncates the range of observations in the dataset, based on | * Truncates the range of observations in the dataset, based on | |||
* the current values of the t1 and t2 members of @dset. | * the current values of the t1 and t2 members of @dset. | |||
skipping to change at line 1317 | skipping to change at line 1320 | |||
if (dataset_has_markers(dset)) { | if (dataset_has_markers(dset)) { | |||
for (i=0; i<offset; i++) { | for (i=0; i<offset; i++) { | |||
free(dset->S[i]); | free(dset->S[i]); | |||
} | } | |||
mvsize = newn * sizeof *dset->S; | mvsize = newn * sizeof *dset->S; | |||
memmove(dset->S, dset->S + offset, mvsize); | memmove(dset->S, dset->S + offset, mvsize); | |||
} | } | |||
if (dset->structure == CROSS_SECTION) { | if (dset->structure == CROSS_SECTION) { | |||
ntodate(dset->stobs, 0, dset); | ntolabel(dset->stobs, 0, dset); | |||
} else { | } else { | |||
/* FIXME panel? */ | /* FIXME panel? */ | |||
ntodate(dset->stobs, dset->t1, dset); | ntolabel(dset->stobs, dset->t1, dset); | |||
dset->sd0 = get_date_x(dset->pd, dset->stobs); | dset->sd0 = get_date_x(dset->pd, dset->stobs); | |||
} | } | |||
dset->t1 = 0; | dset->t1 = 0; | |||
} | } | |||
err = dataset_drop_observations(dset, tail); | err = dataset_drop_observations(dset, tail); | |||
return err; | return err; | |||
} | } | |||
skipping to change at line 2486 | skipping to change at line 2489 | |||
ret = -1; | ret = -1; | |||
} | } | |||
} else { | } else { | |||
ret = (pa->vals[i] < pb->vals[i]) - (pa->vals[i] > pb->vals[i]); | ret = (pa->vals[i] < pb->vals[i]) - (pa->vals[i] > pb->vals[i]); | |||
} | } | |||
} | } | |||
return ret; | return ret; | |||
} | } | |||
/* Turn a string-valued series into an integer-valued series | ||||
representing the places of the strings in lexical order. | ||||
*/ | ||||
typedef struct lexval_ { | ||||
const char *s; | ||||
int code; | ||||
} lexval; | ||||
static int compare_lexvals (const void *a, const void *b) | ||||
{ | ||||
const lexval *lva = (const lexval *) a; | ||||
const lexval *lvb = (const lexval *) b; | ||||
return g_utf8_collate(lva->s, lvb->s); | ||||
} | ||||
static int series_to_lexvals (DATASET *dset, int v, int *targ) | ||||
{ | ||||
int i, t, ct, n_strs; | ||||
series_table *st = series_get_string_table(dset, v); | ||||
char **strs = series_table_get_strings(st, &n_strs); | ||||
lexval *lexvals; | ||||
lexvals = calloc(n_strs, sizeof *lexvals); | ||||
if (lexvals == NULL) { | ||||
return E_ALLOC; | ||||
} | ||||
for (i=0; i<n_strs; i++) { | ||||
lexvals[i].s = strs[i]; | ||||
lexvals[i].code = i+1; | ||||
} | ||||
qsort(lexvals, n_strs, sizeof *lexvals, compare_lexvals); | ||||
for (t=0; t<dset->n; t++) { | ||||
if (na(dset->Z[v][t])) { | ||||
targ[t] = INT_MAX; | ||||
} else { | ||||
ct = (int) dset->Z[v][t]; | ||||
targ[t] = 0; | ||||
for (i=0; i<n_strs; i++) { | ||||
if (ct == lexvals[i].code) { | ||||
targ[t] = i+1; | ||||
break; | ||||
} | ||||
} | ||||
} | ||||
} | ||||
free(lexvals); | ||||
return 0; | ||||
} | ||||
int dataset_sort_by (DATASET *dset, const int *list, gretlopt opt) | int dataset_sort_by (DATASET *dset, const int *list, gretlopt opt) | |||
{ | { | |||
spoint_t *sv = NULL; | spoint_t *sv = NULL; | |||
double *x = NULL; | double *x = NULL; | |||
int *xs = NULL; | ||||
int *xsi = NULL; | ||||
char **S = NULL; | char **S = NULL; | |||
int ns = list[0]; | int ns = list[0]; | |||
int nsvals = 0; | ||||
int i, t, v; | int i, t, v; | |||
int err = 0; | int err = 0; | |||
sv = allocate_spoints(dset->n, ns); | sv = allocate_spoints(dset->n, ns); | |||
if (sv == NULL) { | if (sv == NULL) { | |||
return E_ALLOC; | return E_ALLOC; | |||
} | } | |||
x = malloc(dset->n * sizeof *x); | x = malloc(dset->n * sizeof *x); | |||
if (x == NULL) { | if (x == NULL) { | |||
skipping to change at line 2514 | skipping to change at line 2576 | |||
} | } | |||
if (dset->S != NULL) { | if (dset->S != NULL) { | |||
S = strings_array_new_with_length(dset->n, OBSLEN); | S = strings_array_new_with_length(dset->n, OBSLEN); | |||
if (S == NULL) { | if (S == NULL) { | |||
err = E_ALLOC; | err = E_ALLOC; | |||
goto bailout; | goto bailout; | |||
} | } | |||
} | } | |||
for (i=0; i<ns; i++) { | ||||
if (is_string_valued(dset, list[i+1])) { | ||||
nsvals++; | ||||
} | ||||
} | ||||
if (nsvals > 0) { | ||||
xs = malloc(nsvals * dset->n * sizeof *xs); | ||||
if (xs == NULL) { | ||||
err = E_ALLOC; | ||||
} else { | ||||
xsi = xs; | ||||
for (i=0; i<ns && !err; i++) { | ||||
v = list[i+1]; | ||||
if (is_string_valued(dset, v)) { | ||||
err = series_to_lexvals(dset, v, xsi); | ||||
xsi += dset->n; | ||||
} | ||||
} | ||||
} | ||||
if (err) { | ||||
goto bailout; | ||||
} | ||||
} | ||||
for (t=0; t<dset->n; t++) { | for (t=0; t<dset->n; t++) { | |||
sv[t].obsnum = t; | sv[t].obsnum = t; | |||
for (i=0; i<ns; i++) { | sv[t].nvals = ns; | |||
v = list[i+1]; | } | |||
sv[t].vals[i] = dset->Z[v][t]; | xsi = xs; | |||
sv[t].nvals = ns; | for (i=0; i<ns; i++) { | |||
v = list[i+1]; | ||||
if (is_string_valued(dset, v)) { | ||||
for (t=0; t<dset->n; t++) { | ||||
if (xsi[t] == INT_MAX) { | ||||
sv[t].vals[i] = NADBL; | ||||
} else { | ||||
sv[t].vals[i] = (double) xsi[t]; | ||||
} | ||||
} | ||||
xsi += dset->n; | ||||
} else { | ||||
for (t=0; t<dset->n; t++) { | ||||
sv[t].vals[i] = dset->Z[v][t]; | ||||
} | ||||
} | } | |||
} | } | |||
if (opt & OPT_D) { | if (opt & OPT_D) { | |||
/* descending */ | /* descending */ | |||
qsort(sv, dset->n, sizeof *sv, compare_vals_down); | qsort(sv, dset->n, sizeof *sv, compare_vals_down); | |||
} else { | } else { | |||
qsort(sv, dset->n, sizeof *sv, compare_vals_up); | qsort(sv, dset->n, sizeof *sv, compare_vals_up); | |||
} | } | |||
skipping to change at line 2551 | skipping to change at line 2651 | |||
strcpy(S[t], dset->S[sv[t].obsnum]); | strcpy(S[t], dset->S[sv[t].obsnum]); | |||
} | } | |||
strings_array_free(dset->S, dset->n); | strings_array_free(dset->S, dset->n); | |||
dset->S = S; | dset->S = S; | |||
} | } | |||
bailout: | bailout: | |||
free_spoints(sv, dset->n); | free_spoints(sv, dset->n); | |||
free(x); | free(x); | |||
free(xs); | ||||
return err; | return err; | |||
} | } | |||
static int dataset_sort (DATASET *dset, const int *list, | static int dataset_sort (DATASET *dset, const int *list, | |||
gretlopt opt) | gretlopt opt) | |||
{ | { | |||
if (dataset_is_time_series(dset) || | if (dataset_is_time_series(dset) || | |||
dataset_is_panel(dset)) { | dataset_is_panel(dset)) { | |||
gretl_errmsg_set("You can only do this with undated data"); | gretl_errmsg_set("You can only do this with undated data"); | |||
skipping to change at line 3009 | skipping to change at line 3110 | |||
return 0; | return 0; | |||
} | } | |||
if (k <= 0 || (op == DS_RESAMPLE && k < 1)) { | if (k <= 0 || (op == DS_RESAMPLE && k < 1)) { | |||
*err = E_DATA; | *err = E_DATA; | |||
} else if (op == DS_INSOBS) { | } else if (op == DS_INSOBS) { | |||
if (k > dset->n) { | if (k > dset->n) { | |||
*err = E_DATA; | *err = E_DATA; | |||
} | } | |||
} else if (op == DS_COMPACT) { | } else if (op == DS_COMPACT) { | |||
int ok = 0; | *err = E_PDWRONG; | |||
if (dset->pd == 12 && (k == 4 || k == 1)) { | if (dset->pd == 12 && (k == 4 || k == 1)) { | |||
ok = 1; | *err = 0; | |||
} else if (dset->pd == 4 && k == 1) { | } else if (dset->pd == 4 && k == 1) { | |||
ok = 1; | *err = 0; | |||
} else if (dset->pd == 52 && k == 12) { | } else if (dset->pd == 52 && k == 12) { | |||
ok = 1; | *err = 0; | |||
} else if (dated_daily_data(dset) && (k == 52 || k == 12)) { | } else if (dated_daily_data(dset) && (k == 52 || k == 12)) { | |||
ok = 1; | *err = 0; | |||
} else if (dataset_is_daily(dset) && k == 4) { | } else if (dataset_is_daily(dset) && k == 4) { | |||
if (strstr(*ps, "spread")) { | if (strstr(*ps, "spread")) { | |||
ok = 1; | *err = 0; | |||
} | } | |||
} | } | |||
} else if (op == DS_EXPAND) { | ||||
if (!ok) { | *err = E_PDWRONG; | |||
*err = E_PDWRONG; | if (dset->pd == 1 && (k == 4 || k == 12)) { | |||
gretl_errmsg_set("This conversion is not supported"); | *err = 0; | |||
} else if (dset->pd == 4 && k == 12) { | ||||
*err = 0; | ||||
} | } | |||
} else if (op == DS_PAD_DAILY) { | } else if (op == DS_PAD_DAILY) { | |||
if (k < 5 || k > 7 || k < dset->pd) { | if (k < 5 || k > 7 || k < dset->pd) { | |||
*err = E_PDWRONG; | *err = E_PDWRONG; | |||
gretl_errmsg_set("This conversion is not supported"); | ||||
} | } | |||
} | } | |||
if (*err == E_PDWRONG) { | ||||
gretl_errmsg_set("This conversion is not supported"); | ||||
} | ||||
return k; | return k; | |||
} | } | |||
static int compact_data_set_wrapper (const char *s, DATASET *dset, | static int compact_data_set_wrapper (const char *s, DATASET *dset, | |||
int k) | int k) | |||
{ | { | |||
CompactMethod method = COMPACT_AVG; | CompactMethod method = COMPACT_AVG; | |||
if (s != NULL) { | if (s != NULL) { | |||
s += strspn(s, " "); | s += strspn(s, " "); | |||
skipping to change at line 3248 | skipping to change at line 3353 | |||
return err; | return err; | |||
} | } | |||
/* alternate forms: | /* alternate forms: | |||
@op @list @param | @op @list @param | |||
dataset addobs 24 | dataset addobs 24 | |||
dataset compact 1 | dataset compact 1 | |||
dataset compact 4 last | dataset compact 4 last | |||
dataset expand interpolate | dataset expand 4 | |||
dataset transpose | dataset transpose | |||
dataset sortby x1 | dataset sortby x1 | |||
dataset resample 500 | dataset resample 500 | |||
dataset clear | dataset clear | |||
dataset renumber orig 2 | dataset renumber orig 2 | |||
dataset insobs 13 | dataset insobs 13 | |||
dataset pad-daily 7 | dataset pad-daily 7 | |||
*/ | */ | |||
skipping to change at line 3328 | skipping to change at line 3433 | |||
op == DS_PAD_DAILY) { | op == DS_PAD_DAILY) { | |||
if (param == NULL) { | if (param == NULL) { | |||
err = E_ARGS; | err = E_ARGS; | |||
} else { | } else { | |||
k = dataset_int_param(¶m, op, dset, &err); | k = dataset_int_param(¶m, op, dset, &err); | |||
} | } | |||
if (err) { | if (err) { | |||
return err; | return err; | |||
} | } | |||
} else if (op == DS_EXPAND) { | } else if (op == DS_EXPAND) { | |||
if (dset->pd == 1) { | if (param != NULL) { | |||
k = dataset_int_param(¶m, op, dset, &err); | ||||
} else if (dset->pd == 1) { | ||||
k = 4; | k = 4; | |||
} else if (dset->pd == 4) { | } else if (dset->pd == 4) { | |||
k = 12; | k = 12; | |||
} else { | } else { | |||
return E_PDWRONG; | err = E_PDWRONG; | |||
} | ||||
if (err) { | ||||
return err; | ||||
} | } | |||
} | } | |||
if (op == DS_ADDOBS) { | if (op == DS_ADDOBS) { | |||
err = add_obs(k, dset, opt, prn); | err = add_obs(k, dset, opt, prn); | |||
} else if (op == DS_INSOBS) { | } else if (op == DS_INSOBS) { | |||
err = insert_obs(k, dset, prn); | err = insert_obs(k, dset, prn); | |||
} else if (op == DS_COMPACT) { | } else if (op == DS_COMPACT) { | |||
err = compact_data_set_wrapper(param, dset, k); | err = compact_data_set_wrapper(param, dset, k); | |||
} else if (op == DS_EXPAND) { | } else if (op == DS_EXPAND) { | |||
int n = (param == NULL)? 0 : strlen(param); | err = expand_data_set(dset, k); | |||
int interp = 0; | ||||
if (n > 0 && !strncmp(param, "interpolate", n)) { | ||||
interp = 1; | ||||
} | ||||
err = expand_data_set(dset, k, interp); | ||||
} else if (op == DS_PAD_DAILY) { | } else if (op == DS_PAD_DAILY) { | |||
err = pad_daily_data(dset, k, prn); | err = pad_daily_data(dset, k, prn); | |||
} else if (op == DS_TRANSPOSE) { | } else if (op == DS_TRANSPOSE) { | |||
err = transpose_data(dset); | err = transpose_data(dset); | |||
} else if (op == DS_SORTBY) { | } else if (op == DS_SORTBY) { | |||
err = dataset_sort(dset, list, OPT_NONE); | err = dataset_sort(dset, list, OPT_NONE); | |||
} else if (op == DS_DSORTBY) { | } else if (op == DS_DSORTBY) { | |||
err = dataset_sort(dset, list, OPT_D); | err = dataset_sort(dset, list, OPT_D); | |||
} else if (op == DS_RESAMPLE) { | } else if (op == DS_RESAMPLE) { | |||
err = dataset_resample(dset, k, 0); | err = dataset_resample(dset, k, 0); | |||
skipping to change at line 3586 | skipping to change at line 3690 | |||
if (pd == 1) { | if (pd == 1) { | |||
stobs = g_strdup_printf("%d", yr0); | stobs = g_strdup_printf("%d", yr0); | |||
} else if (pd == 4) { | } else if (pd == 4) { | |||
stobs = g_strdup_printf("%d.%d", yr0, minor0); | stobs = g_strdup_printf("%d.%d", yr0, minor0); | |||
} else { | } else { | |||
stobs = g_strdup_printf("%d.%02d", yr0, minor0); | stobs = g_strdup_printf("%d.%02d", yr0, minor0); | |||
} | } | |||
dset->sd0 = dot_atof(stobs); | dset->sd0 = dot_atof(stobs); | |||
ntodate(dset->stobs, 0, dset); | ntolabel(dset->stobs, 0, dset); | |||
ntodate(dset->endobs, dset->n - 1, dset); | ntolabel(dset->endobs, dset->n - 1, dset); | |||
g_free(stobs); | g_free(stobs); | |||
} | } | |||
return err; | return err; | |||
} | } | |||
void dataset_clear_sample_record (DATASET *dset) | void dataset_clear_sample_record (DATASET *dset) | |||
{ | { | |||
if (dset->restriction != NULL) { | if (dset->restriction != NULL) { | |||
free(dset->restriction); | free(dset->restriction); | |||
skipping to change at line 4222 | skipping to change at line 4326 | |||
} | } | |||
return ret; | return ret; | |||
} | } | |||
/** | /** | |||
* series_get_string_vals: | * series_get_string_vals: | |||
* @dset: pointer to dataset. | * @dset: pointer to dataset. | |||
* @i: index number of series. | * @i: index number of series. | |||
* @n_strs: location to receive the number of strings, or NULL. | * @n_strs: location to receive the number of strings, or NULL. | |||
* @subsample: non-zero to restrict to current sample range. | ||||
* | * | |||
* Returns: the array of strings associated with distinct numerical | * Returns: the array of strings associated with distinct numerical | |||
* values of series @i, or NULL if there's no such array. The returned | * values of series @i, or NULL if there's no such array. The returned | |||
* array should not be modified in any way; copy the strings first if | * array should not be modified in any way; copy the strings first if | |||
* you need to modify them. | * you need to modify them. | |||
*/ | */ | |||
char **series_get_string_vals (const DATASET *dset, int i, | char **series_get_string_vals (const DATASET *dset, int i, | |||
int *n_strs, int subsample) | int *n_strs, int subsample) | |||
{ | { | |||
skipping to change at line 4446 | skipping to change at line 4551 | |||
if (!err) { | if (!err) { | |||
*pU = U; | *pU = U; | |||
*pnu = nu; | *pnu = nu; | |||
} else if (U != NULL) { | } else if (U != NULL) { | |||
strings_array_free(U, nu); | strings_array_free(U, nu); | |||
} | } | |||
return err; | return err; | |||
} | } | |||
/* Recognize the case where we have an "empty" series | ||||
and an array of strings of full dataset length. | ||||
*/ | ||||
static int alt_strvals_case (DATASET *dset, int v, gretl_array *a) | static int alt_strvals_case (DATASET *dset, int v, gretl_array *a) | |||
{ | { | |||
double *x = dset->Z[v]; | double *x = dset->Z[v]; | |||
double x0 = dset->Z[v][0]; | int i; | |||
int i, xconst = 1; | ||||
for (i=1; i<dset->n && xconst; i++) { | if (gretl_array_get_length(a) != dset->n) { | |||
if (na(x0)) { | return 0; | |||
if (!na(x[i])) { | } | |||
xconst = 0; | ||||
} | for (i=0; i<dset->n; i++) { | |||
} else if (x[i] != x0) { | if (x[i] != 0) { | |||
xconst = 0; | return 0; | |||
} | } | |||
} | } | |||
return xconst && gretl_array_get_length(a) == dset->n; | return 1; | |||
} | } | |||
/* here we're trying to set strings values on a series from | /* here we're trying to set strings values on a series from | |||
scratch */ | scratch */ | |||
int series_set_string_vals (DATASET *dset, int i, void *ptr) | int series_set_string_vals (DATASET *dset, int i, void *ptr) | |||
{ | { | |||
gretl_array *a = ptr; | gretl_array *a = ptr; | |||
gretl_matrix *vals = NULL; | gretl_matrix *vals = NULL; | |||
char **S = NULL; | char **S = NULL; | |||
skipping to change at line 4534 | skipping to change at line 4634 | |||
gretl_errmsg_sprintf("String %d is not valid UTF-8", i+1); | gretl_errmsg_sprintf("String %d is not valid UTF-8", i+1); | |||
err = E_DATA; | err = E_DATA; | |||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
do_strtable: | do_strtable: | |||
if (!err) { | if (!err) { | |||
series_table *st = series_table_new(S, ns); | series_table *st = series_table_new(S, ns, &err); | |||
if (st == NULL) { | if (!err) { | |||
err = E_ALLOC; | ||||
} else { | ||||
if (dset->varinfo[i]->st != NULL) { | if (dset->varinfo[i]->st != NULL) { | |||
/* remove any pre-existing table */ | /* remove any pre-existing table */ | |||
series_table_destroy(dset->varinfo[i]->st); | series_table_destroy(dset->varinfo[i]->st); | |||
} | } | |||
series_set_discrete(dset, i, 1); | series_set_discrete(dset, i, 1); | |||
dset->varinfo[i]->st = st; | dset->varinfo[i]->st = st; | |||
maybe_adjust_label(dset, i, S, ns); | maybe_adjust_label(dset, i, S, ns); | |||
} | } | |||
} | } | |||
if (err && S != NULL && ns > 0) { | if (err && S != NULL && ns > 0) { | |||
strings_array_free(S, ns); | strings_array_free(S, ns); | |||
} | } | |||
gretl_matrix_free(vals); | gretl_matrix_free(vals); | |||
return err; | return err; | |||
} | } | |||
/* The pre-checked case: we know that series @i is suitable | ||||
for stringifying, and that @S contains the right number of | ||||
strings. | ||||
*/ | ||||
int series_set_string_vals_direct (DATASET *dset, int i, | ||||
char **S, int ns) | ||||
{ | ||||
int err = 0; | ||||
series_table *st = series_table_new(S, ns, &err); | ||||
if (!err) { | ||||
if (dset->varinfo[i]->st != NULL) { | ||||
/* remove any pre-existing table */ | ||||
series_table_destroy(dset->varinfo[i]->st); | ||||
} | ||||
series_set_discrete(dset, i, 1); | ||||
dset->varinfo[i]->st = st; | ||||
maybe_adjust_label(dset, i, S, ns); | ||||
} | ||||
if (err && S != NULL && ns > 0) { | ||||
strings_array_free(S, ns); | ||||
} | ||||
return err; | ||||
} | ||||
/** | /** | |||
* series_recode_strings: | * series_recode_strings: | |||
* @dset: pointer to dataset. | * @dset: pointer to dataset. | |||
* @v: index number of target string-valued series. | * @v: index number of target string-valued series. | |||
* @opt: may contain OPT_P (see below). | * @opt: may contain OPT_P (see below). | |||
* @changed: location to receive "changed" feedback, or NULL. | * @changed: location to receive "changed" feedback, or NULL. | |||
* | * | |||
* This function "trims" the array of string values associated | * This function "trims" the array of string values associated | |||
* with series @v so that it contains no redundant elements -- | * with series @v so that it contains no redundant elements -- | |||
* that is, values of which there is no instance in the | * that is, values of which there is no instance in the | |||
skipping to change at line 4635 | skipping to change at line 4761 | |||
S[i] = gretl_strdup(si); | S[i] = gretl_strdup(si); | |||
repl->val[i] = i + 1; | repl->val[i] = i + 1; | |||
} | } | |||
substitute_values(x, x, n, vals->val, nu, repl->val, nu); | substitute_values(x, x, n, vals->val, nu, repl->val, nu); | |||
if (!(opt & OPT_P)) { | if (!(opt & OPT_P)) { | |||
series_table_destroy(dset->varinfo[v]->st); | series_table_destroy(dset->varinfo[v]->st); | |||
} | } | |||
/* the series table takes ownership of @S */ | /* the series table takes ownership of @S */ | |||
dset->varinfo[v]->st = series_table_new(S, nu); | dset->varinfo[v]->st = series_table_new(S, nu, &err); | |||
if (changed != NULL) { | if (changed != NULL) { | |||
*changed = 1; | *changed = 1; | |||
} | } | |||
} | } | |||
gretl_matrix_free(vals); | gretl_matrix_free(vals); | |||
gretl_matrix_free(repl); | gretl_matrix_free(repl); | |||
return err; | return err; | |||
skipping to change at line 4872 | skipping to change at line 4998 | |||
static int pad_daily_data (DATASET *dset, int pd, PRN *prn) | static int pad_daily_data (DATASET *dset, int pd, PRN *prn) | |||
{ | { | |||
DATASET *bigset = NULL; | DATASET *bigset = NULL; | |||
char datestr[OBSLEN]; | char datestr[OBSLEN]; | |||
guint32 ed, ed0 = 0, edbak = 0; | guint32 ed, ed0 = 0, edbak = 0; | |||
int wd, skip, totskip = 0; | int wd, skip, totskip = 0; | |||
int t, err = 0; | int t, err = 0; | |||
for (t=0; t<dset->n; t++) { | for (t=0; t<dset->n; t++) { | |||
ntodate(datestr, t, dset); | ntolabel(datestr, t, dset); | |||
if (t == 0) { | if (t == 0) { | |||
ed0 = edbak = get_epoch_day(datestr); | ed0 = edbak = get_epoch_day(datestr); | |||
} else { | } else { | |||
wd = weekday_from_date(datestr); | wd = weekday_from_date(datestr); | |||
ed = get_epoch_day(datestr); | ed = get_epoch_day(datestr); | |||
skip = effective_daily_skip(ed - edbak, wd, pd); | skip = effective_daily_skip(ed - edbak, wd, pd); | |||
totskip += skip; | totskip += skip; | |||
edbak = ed; | edbak = ed; | |||
} | } | |||
} | } | |||
if (totskip == 0) { | if (totskip == 0) { | |||
pprintf(prn, "Dataset is already complete for %d-day calendar", pd); | pprintf(prn, "Dataset is already complete for %d-day calendar", pd); | |||
return 0; | return 0; | |||
} | } | |||
bigset = create_new_dataset(dset->v, dset->n + totskip, NO_MARKERS); | /* We pass OPT_R here to avoid allocating varnames in @bigset, | |||
since we're going to preserve these from @dset. | ||||
*/ | ||||
bigset = real_create_new_dataset(dset->v, dset->n + totskip, OPT_R); | ||||
if (bigset == NULL) { | if (bigset == NULL) { | |||
err = E_ALLOC; | err = E_ALLOC; | |||
} else { | } else { | |||
int i, s = 0; | int i, s = 0; | |||
edbak = ed0; | edbak = ed0; | |||
for (t=0; t<dset->n; t++) { | for (t=0; t<dset->n; t++) { | |||
if (t > 0) { | if (t > 0) { | |||
ntodate(datestr, t, dset); | ntolabel(datestr, t, dset); | |||
wd = weekday_from_date(datestr); | wd = weekday_from_date(datestr); | |||
ed = get_epoch_day(datestr); | ed = get_epoch_day(datestr); | |||
s += 1 + effective_daily_skip(ed - edbak, wd, pd); | s += 1 + effective_daily_skip(ed - edbak, wd, pd); | |||
edbak = ed; | edbak = ed; | |||
} | } | |||
for (i=1; i<dset->v; i++) { | for (i=1; i<dset->v; i++) { | |||
bigset->Z[i][s] = dset->Z[i][t]; | bigset->Z[i][s] = dset->Z[i][t]; | |||
} | } | |||
} | } | |||
bigset->varname = dset->varname; | bigset->varname = dset->varname; | |||
bigset->varinfo = dset->varinfo; | bigset->varinfo = dset->varinfo; | |||
bigset->descrip = dset->descrip; | bigset->descrip = dset->descrip; | |||
bigset->pd = pd; | bigset->pd = pd; | |||
bigset->structure = TIME_SERIES; | bigset->structure = TIME_SERIES; | |||
bigset->sd0 = (double) ed0; | bigset->sd0 = (double) ed0; | |||
strcpy(bigset->stobs, dset->stobs); | strcpy(bigset->stobs, dset->stobs); | |||
ntodate(bigset->endobs, bigset->n - 1, bigset); | ntolabel(bigset->endobs, bigset->n - 1, bigset); | |||
dset->varname = NULL; | dset->varname = NULL; | |||
dset->varinfo = NULL; | dset->varinfo = NULL; | |||
dset->descrip = NULL; | dset->descrip = NULL; | |||
dataset_destroy_obs_markers(dset); | dataset_destroy_obs_markers(dset); | |||
free_Z(dset); | free_Z(dset); | |||
clear_datainfo(dset, CLEAR_SUBSAMPLE); | clear_datainfo(dset, CLEAR_SUBSAMPLE); | |||
*dset = *bigset; | *dset = *bigset; | |||
free(bigset); /* avoid leaking memory */ | ||||
} | } | |||
return err; | return err; | |||
} | } | |||
/* MIDAS-related functions */ | /* MIDAS-related functions */ | |||
/* postprocess: fill missing slots in daily data array | /* postprocess: fill missing slots in daily data array | |||
with the period (month or quarter) average | with the period (month or quarter) average | |||
(FIXME support interpolation as an option?) | (FIXME support interpolation as an option?) | |||
skipping to change at line 5036 | skipping to change at line 5166 | |||
void series_set_midas_anchor (const DATASET *dset, int i) | void series_set_midas_anchor (const DATASET *dset, int i) | |||
{ | { | |||
if (i > 0 && i < dset->v) { | if (i > 0 && i < dset->v) { | |||
dset->varinfo[i]->flags |= VAR_HFANCHOR; | dset->varinfo[i]->flags |= VAR_HFANCHOR; | |||
} | } | |||
} | } | |||
/* end MIDAS-related functions */ | /* end MIDAS-related functions */ | |||
int series_get_orig_pd (const DATASET *dset, int i) | ||||
{ | ||||
if (i > 0 && i < dset->v) { | ||||
return dset->varinfo[i]->orig_pd; | ||||
} else { | ||||
return 0; | ||||
} | ||||
} | ||||
void series_set_orig_pd (const DATASET *dset, int i, int pd) | ||||
{ | ||||
if (i > 0 && i < dset->v) { | ||||
dset->varinfo[i]->orig_pd = pd; | ||||
} | ||||
} | ||||
void series_unset_orig_pd (const DATASET *dset, int i) | ||||
{ | ||||
if (i > 0 && i < dset->v) { | ||||
dset->varinfo[i]->orig_pd = 0; | ||||
} | ||||
} | ||||
void *series_info_bundle (const DATASET *dset, int i, | void *series_info_bundle (const DATASET *dset, int i, | |||
int *err) | int *err) | |||
{ | { | |||
gretl_bundle *b = NULL; | gretl_bundle *b = NULL; | |||
if (dset != NULL && i >= 0 && i < dset->v) { | if (dset != NULL && i >= 0 && i < dset->v) { | |||
b = gretl_bundle_new(); | b = gretl_bundle_new(); | |||
if (b == NULL) { | if (b == NULL) { | |||
*err = E_ALLOC; | *err = E_ALLOC; | |||
} | } | |||
skipping to change at line 5079 | skipping to change at line 5232 | |||
gretl_bundle_set_string(b, "transform", "none"); | gretl_bundle_set_string(b, "transform", "none"); | |||
} | } | |||
gretl_bundle_set_int(b, "lag", vinfo->lag); | gretl_bundle_set_int(b, "lag", vinfo->lag); | |||
gretl_bundle_set_int(b, "has_string_table", vinfo->st != NULL); | gretl_bundle_set_int(b, "has_string_table", vinfo->st != NULL); | |||
if (vinfo->midas_period > 0) { | if (vinfo->midas_period > 0) { | |||
gretl_bundle_set_int(b, "midas_period", vinfo->midas_period); | gretl_bundle_set_int(b, "midas_period", vinfo->midas_period); | |||
} | } | |||
if (vinfo->midas_freq > 0) { | if (vinfo->midas_freq > 0) { | |||
gretl_bundle_set_int(b, "midas_freq", vinfo->midas_freq); | gretl_bundle_set_int(b, "midas_freq", vinfo->midas_freq); | |||
} | } | |||
if (vinfo->orig_pd > 0) { | ||||
gretl_bundle_set_int(b, "orig_pd", vinfo->orig_pd); | ||||
} | ||||
} | } | |||
return b; | return b; | |||
} | } | |||
/* Given a series label @s, see if it can be recognized | /* Given a series label @s, see if it can be recognized | |||
as identifying the series as the product of two others, | as identifying the series as the product of two others, | |||
and if so write the names of the others into @targ1 | and if so write the names of the others into @targ1 | |||
and @targ2. | and @targ2. | |||
*/ | */ | |||
End of changes. 45 change blocks. | ||||
57 lines changed or deleted | 213 lines changed or added |