1 /*
2 * gretl -- Gnu Regression, Econometrics and Time-series Library
3 * Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #define FULL_XML_HEADERS 1
21
22 #include "libgretl.h"
23 #include "uservar.h"
24 #include "gretl_func.h"
25 #include "gretl_xml.h"
26 #include "gretl_typemap.h"
27 #include "matrix_extra.h"
28 #include "gretl_cmatrix.h"
29 #include "gretl_array.h"
30
31 /**
32 * gretl_array:
33 *
34 * An opaque type; use the relevant accessor functions.
35 */
36
37 struct gretl_array_ {
38 GretlType type; /* type of data */
39 int n; /* number of elements */
40 void **data; /* actual data array */
41 double *mdata; /* for matrix block */
42 };
43
gretl_array_destroy_data(gretl_array * A)44 static void gretl_array_destroy_data (gretl_array *A)
45 {
46 int i;
47
48 if (A->data != NULL) {
49 if (A->type == GRETL_TYPE_STRINGS ||
50 A->type == GRETL_TYPE_LISTS) {
51 /* a simple "free" will do */
52 for (i=0; i<A->n; i++) {
53 free(A->data[i]);
54 }
55 } else if (A->type == GRETL_TYPE_MATRICES) {
56 if (A->mdata != NULL) {
57 free(A->mdata);
58 for (i=0; i<A->n; i++) {
59 free(A->data[i]);
60 }
61 } else {
62 for (i=0; i<A->n; i++) {
63 gretl_matrix_free(A->data[i]);
64 }
65 }
66 } else if (A->type == GRETL_TYPE_BUNDLES) {
67 for (i=0; i<A->n; i++) {
68 gretl_bundle_destroy(A->data[i]);
69 }
70 } else if (A->type == GRETL_TYPE_ARRAYS) {
71 for (i=0; i<A->n; i++) {
72 gretl_array_destroy(A->data[i]);
73 }
74 }
75 free(A->data);
76 A->data = NULL;
77 }
78 }
79
80 /* Destroy the whole array, including freeing its
81 contents.
82 */
83
gretl_array_destroy(gretl_array * A)84 void gretl_array_destroy (gretl_array *A)
85 {
86 if (A != NULL) {
87 gretl_array_destroy_data(A);
88 free(A);
89 }
90 }
91
92 /* Reduce the array to empty status, freeing the
93 contents but not the array structure itself.
94 */
95
gretl_array_void_content(gretl_array * A)96 void gretl_array_void_content (gretl_array *A)
97 {
98 if (A != NULL) {
99 gretl_array_destroy_data(A);
100 A->n = 0;
101 }
102 }
103
104 /* Reduce the array to empty status, setting the
105 entire data array to NULL without freeing anything.
106 Makes sense only if the data array is actually
107 "owned" elsewhere.
108 */
109
gretl_array_nullify_content(gretl_array * A)110 void gretl_array_nullify_content (gretl_array *A)
111 {
112 if (A != NULL) {
113 A->data = NULL;
114 A->n = 0;
115 }
116 }
117
118 /* Set the array's element pointers to NULL, without
119 freeing them. Makes sense only if the element
120 pointers are actually "owned" by something else
121 (have not been copied into the array).
122 */
123
gretl_array_nullify_elements(gretl_array * A)124 void gretl_array_nullify_elements (gretl_array *A)
125 {
126 if (A != NULL && A->data != NULL) {
127 int i;
128
129 for (i=0; i<A->n; i++) {
130 A->data[i] = NULL;
131 }
132 }
133 }
134
array_allocate_storage(gretl_array * A)135 static int array_allocate_storage (gretl_array *A)
136 {
137 int i, err = 0;
138
139 A->data = malloc(A->n * sizeof *A->data);
140
141 if (A->data == NULL) {
142 err = E_ALLOC;
143 } else {
144 for (i=0; i<A->n; i++) {
145 A->data[i] = NULL;
146 }
147 }
148
149 return err;
150 }
151
array_extend_content(gretl_array * A,int plus)152 static int array_extend_content (gretl_array *A, int plus)
153 {
154 if (plus == 0) {
155 return 0; /* no-op */
156 } else if (plus < 0) {
157 return E_DATA;
158 } else {
159 void **data;
160 int n = A->n + plus;
161 int i, err = 0;
162
163 data = realloc(A->data, n * sizeof *A->data);
164
165 if (data == NULL) {
166 err = E_ALLOC;
167 } else {
168 for (i=A->n; i<n-1; i++) {
169 data[i] = NULL;
170 }
171 A->data = data;
172 A->n = n;
173 }
174
175 return err;
176 }
177 }
178
179 /* Create a new array of type @type. The idea is that it's OK
180 to have n = 0: in that case the array starts empty but can
181 be extended by the += operator. Or it can be sized in
182 advance.
183 */
184
gretl_array_new(GretlType type,int n,int * err)185 gretl_array *gretl_array_new (GretlType type, int n, int *err)
186 {
187 gretl_array *A;
188
189 if (type != GRETL_TYPE_STRINGS &&
190 type != GRETL_TYPE_MATRICES &&
191 type != GRETL_TYPE_BUNDLES &&
192 type != GRETL_TYPE_LISTS &&
193 type != GRETL_TYPE_ARRAYS &&
194 type != GRETL_TYPE_ANY) {
195 *err = E_TYPES;
196 return NULL;
197 } else if (n < 0) {
198 *err = E_DATA;
199 return NULL;
200 }
201
202 A = malloc(sizeof *A);
203
204 if (A == NULL) {
205 *err = E_ALLOC;
206 } else {
207 A->type = type;
208 A->n = n;
209 A->data = NULL;
210 A->mdata = NULL;
211 if (n > 0) {
212 *err = array_allocate_storage(A);
213 if (*err) {
214 gretl_array_destroy(A);
215 A = NULL;
216 }
217 }
218 }
219
220 return A;
221 }
222
gretl_singleton_array(void * ptr,GretlType atype,int copy,int * err)223 gretl_array *gretl_singleton_array (void *ptr, GretlType atype,
224 int copy, int *err)
225 {
226 gretl_array *A = gretl_array_new(atype, 1, err);
227
228 if (A != NULL) {
229 GretlType t = gretl_type_get_singular(atype);
230
231 *err = gretl_array_set_element(A, 0, ptr, t, copy);
232 if (*err) {
233 free(A);
234 A = NULL;
235 }
236 }
237
238 return A;
239 }
240
gretl_array_from_strings(char ** S,int n,int copy,int * err)241 gretl_array *gretl_array_from_strings (char **S, int n,
242 int copy, int *err)
243 {
244 gretl_array *A;
245
246 A = gretl_array_new(GRETL_TYPE_STRINGS, 0, err);
247
248 if (A != NULL && n > 0) {
249 if (copy) {
250 A->data = (void **) strings_array_dup(S, n);
251 if (A->data == NULL) {
252 *err = E_ALLOC;
253 }
254 } else {
255 A->data = (void **) S;
256 }
257 if (!*err) {
258 A->n = n;
259 }
260 }
261
262 return A;
263 }
264
265 #define COMMON_BLOCK 1
266
gretl_matrix_array_sized(int n,int r,int c,int * err)267 gretl_array *gretl_matrix_array_sized (int n, int r, int c,
268 int *err)
269 {
270 gretl_array *A;
271
272 A = gretl_array_new(GRETL_TYPE_MATRICES, n, err);
273
274 #if COMMON_BLOCK
275 if (A != NULL && n > 0) {
276 size_t msize = n * r * c * sizeof(double);
277 double *ai_val;
278 gretl_matrix *ai;
279 int i, rc = r * c;
280
281 /* common block for matrix data */
282 ai_val = A->mdata = malloc(msize);
283 if (A->mdata == NULL) {
284 *err = E_ALLOC;
285 }
286
287 for (i=0; i<n && !*err; i++) {
288 ai = gretl_null_matrix_new();
289 if (ai == NULL) {
290 *err = E_ALLOC;
291 break;
292 }
293 ai->val = ai_val;
294 ai->rows = r;
295 ai->cols = c;
296 A->data[i] = ai;
297 ai_val += rc;
298 }
299 }
300 #else
301 if (A != NULL && n > 0) {
302 int i;
303
304 for (i=0; i<n && !*err; i++) {
305 A->data[i] = gretl_matrix_alloc(r, c);
306 if (A->data[i] == NULL) {
307 *err = E_ALLOC;
308 }
309 }
310 }
311 #endif
312
313 if (*err && A != NULL) {
314 gretl_array_destroy(A);
315 A = NULL;
316 }
317
318 return A;
319 }
320
321 /* When we're returning an array of strings, ensure
322 that any NULL elements are converted to empty
323 strings.
324 */
325
strings_array_null_check(gretl_array * A)326 static int strings_array_null_check (gretl_array *A)
327 {
328 int i;
329
330 for (i=0; i<A->n; i++) {
331 if (A->data[i] == NULL) {
332 A->data[i] = gretl_strdup("");
333 if (A->data[i] == NULL) {
334 return E_ALLOC;
335 }
336 }
337 }
338
339 return 0;
340 }
341
342 /* note: don't modify the returned value */
343
gretl_array_get_strings(gretl_array * A,int * ns)344 char **gretl_array_get_strings (gretl_array *A, int *ns)
345 {
346 char **AS = NULL;
347
348 *ns = 0;
349
350 if (A != NULL && A->type == GRETL_TYPE_STRINGS) {
351 int err = strings_array_null_check(A);
352
353 if (!err) {
354 *ns = A->n;
355 AS = (char **) A->data;
356 }
357 }
358
359 return AS;
360 }
361
362 /* note: take ownership of the returned value */
363
gretl_array_steal_strings(gretl_array * A,int * ns)364 char **gretl_array_steal_strings (gretl_array *A, int *ns)
365 {
366 char **AS = NULL;
367
368 *ns = 0;
369
370 if (A != NULL && A->type == GRETL_TYPE_STRINGS) {
371 int err = strings_array_null_check(A);
372
373 if (!err) {
374 *ns = A->n;
375 AS = (char **) A->data;
376 A->n = 0;
377 A->data = NULL;
378 }
379 }
380
381 return AS;
382 }
383
gretl_array_get_stringify_strings(gretl_array * A,int nreq,int * pns,int * err)384 char **gretl_array_get_stringify_strings (gretl_array *A,
385 int nreq, int *pns,
386 int *err)
387 {
388 char **S = NULL;
389
390 *pns = 0;
391
392 if (A == NULL) {
393 *err = E_DATA;
394 } else if (A->type != GRETL_TYPE_STRINGS) {
395 *err = E_TYPES;
396 } else if (A->n < nreq) {
397 gretl_errmsg_sprintf("Too few strings: %d given but %d needed",
398 A->n, nreq);
399 *err = E_DATA;
400 }
401
402 if (!*err) {
403 char **AS = (char **) A->data;
404
405 S = strings_array_new(A->n);
406 if (S == NULL) {
407 *err = E_ALLOC;
408 } else {
409 int myerr = 0;
410 int ndone = 0;
411 int i, j;
412
413 for (i=0; i<A->n && !myerr; i++) {
414 if (AS[i] == NULL || AS[i][0] == '\0') {
415 myerr = E_DATA;
416 } else {
417 S[i] = gretl_strdup(AS[i]);
418 if (i > 0) {
419 for (j=0; j<i; j++) {
420 if (!strcmp(AS[j], S[i])) {
421 gretl_errmsg_sprintf("Duplicated string '%s'", S[i]);
422 myerr = E_DATA;
423 }
424 }
425 }
426 }
427 if (!myerr) {
428 ndone++;
429 }
430 }
431 if (myerr && ndone < nreq) {
432 *err = myerr;
433 strings_array_free(S, A->n);
434 S = NULL;
435 } else {
436 *pns = ndone;
437 }
438 }
439 }
440
441 return S;
442 }
443
444 /* note: the return value is newly allocated, and owned by the caller */
445
gretl_strings_array_flatten(gretl_array * A,int space,int * err)446 char *gretl_strings_array_flatten (gretl_array *A, int space, int *err)
447 {
448 const char *sep = space ? " " : "\n";
449 char *s = NULL;
450
451 if (A == NULL) {
452 *err = E_DATA;
453 } else if (A->type != GRETL_TYPE_STRINGS) {
454 *err = E_TYPES;
455 } else {
456 int i, len = 0;
457
458 for (i=0; i<A->n; i++) {
459 if (A->data[i] == NULL) {
460 *err = E_MISSDATA;
461 break;
462 } else {
463 len += strlen(A->data[i]) + 1;
464 }
465 }
466
467 if (!*err) {
468 s = calloc(len, 1);
469 if (s == NULL) {
470 *err = E_ALLOC;
471 } else {
472 for (i=0; i<A->n; i++) {
473 strcat(s, A->data[i]);
474 if (i < A->n - 1) {
475 strcat(s, sep);
476 }
477 }
478 }
479 }
480 }
481
482 return s;
483 }
484
485 /* Return a column vector holding the position(s) in
486 the strings array @A at which the string @s is
487 matched -- or an empty matrix in case of no matches.
488 */
489
gretl_strings_array_pos(gretl_array * A,const char * s,int * err)490 gretl_matrix *gretl_strings_array_pos (gretl_array *A,
491 const char *s,
492 int *err)
493 {
494 gretl_matrix *ret = NULL;
495 const char *si;
496 int i, np = 0;
497
498 for (i=0; i<A->n; i++) {
499 si = A->data[i] == NULL ? "" : A->data[i];
500 if (strcmp(si, s) == 0) {
501 np++;
502 }
503 }
504
505 if (np == 0) {
506 ret = gretl_null_matrix_new();
507 } else {
508 ret = gretl_matrix_alloc(np, 1);
509 }
510
511 if (ret == NULL) {
512 *err = E_ALLOC;
513 } else if (np > 0) {
514 int j = 0;
515
516 for (i=0; i<A->n; i++) {
517 si = A->data[i] == NULL ? "" : A->data[i];
518 if (strcmp(si, s) == 0) {
519 ret->val[j++] = i+1;
520 }
521 }
522 }
523
524 return ret;
525 }
526
gretl_array_get_element(gretl_array * A,int i,GretlType * type,int * err)527 void *gretl_array_get_element (gretl_array *A, int i,
528 GretlType *type,
529 int *err)
530 {
531 void *ret = NULL;
532
533 /* Note that the data returned here are not "deep copied",
534 we just pass the pointer. It's up to the caller to
535 decide if a copy has to be made, given that the
536 pointer from here should not be modified.
537 */
538
539 if (A == NULL) {
540 *err = E_UNKVAR;
541 } else if (i < 0 || i >= A->n) {
542 *err = E_INVARG;
543 } else if (A->type == GRETL_TYPE_ANY) {
544 *err = E_TYPES;
545 } else {
546 if (type != NULL) {
547 *type = gretl_type_get_singular(A->type);
548 }
549 if (A->type == GRETL_TYPE_STRINGS) {
550 if (A->data[i] == NULL) {
551 A->data[i] = gretl_strdup("");
552 }
553 } else if (A->type == GRETL_TYPE_MATRICES) {
554 if (A->data[i] == NULL) {
555 A->data[i] = gretl_null_matrix_new();
556 }
557 } else if (A->type == GRETL_TYPE_BUNDLES) {
558 if (A->data[i] == NULL) {
559 A->data[i] = gretl_bundle_new();
560 }
561 } else if (A->type == GRETL_TYPE_ARRAYS) {
562 if (A->data[i] == NULL) {
563 A->data[i] = gretl_array_new(GRETL_TYPE_ANY, 0, err);
564 }
565 } else if (A->type == GRETL_TYPE_LISTS) {
566 if (A->data[i] == NULL) {
567 A->data[i] = gretl_list_new(0);
568 }
569 }
570 ret = A->data[i];
571 if (ret == NULL) {
572 *err = E_ALLOC;
573 }
574 }
575
576 return ret;
577 }
578
579 /* Note: no type-checking, the caller is supposed to
580 be on the ball. Use with caution.
581 */
582
gretl_array_get_data(gretl_array * A,int i)583 void *gretl_array_get_data (gretl_array *A, int i)
584 {
585 if (A == NULL || i < 0 || i >= A->n) {
586 return NULL;
587 } else {
588 return A->data[i];
589 }
590 }
591
gretl_array_set_data(gretl_array * A,int i,void * ptr)592 int gretl_array_set_data (gretl_array *A, int i, void *ptr)
593 {
594 if (A == NULL || i < 0 || i >= A->n) {
595 return E_DATA;
596 } else {
597 A->data[i] = ptr;
598 return 0;
599 }
600 }
601
check_list_bounds(int * list,int arrdim)602 static int check_list_bounds (int *list, int arrdim)
603 {
604 int i;
605
606 for (i=1; i<=list[0]; i++) {
607 if (list[i] <= 0 || list[i] > arrdim) {
608 return 0;
609 }
610 }
611
612 return 1;
613 }
614
gretl_array_copy_subspec(gretl_array * A,int * list,int * err)615 gretl_array *gretl_array_copy_subspec (gretl_array *A,
616 int *list,
617 int *err)
618 {
619 gretl_array *C = NULL;
620
621 if (A == NULL) {
622 *err = E_DATA;
623 } else if (!check_list_bounds(list, A->n)) {
624 *err = E_INVARG;
625 } else {
626 int i, k, m = list[0];
627
628 C = gretl_array_new(A->type, m, err);
629
630 for (i=0; i<m && !*err; i++) {
631 k = list[i+1] - 1;
632 if (A->data[k] != NULL) {
633 if (A->type == GRETL_TYPE_STRINGS) {
634 C->data[i] = gretl_strdup(A->data[k]);
635 } else if (A->type == GRETL_TYPE_MATRICES) {
636 C->data[i] = gretl_matrix_copy(A->data[k]);
637 } else if (A->type == GRETL_TYPE_BUNDLES) {
638 C->data[i] = gretl_bundle_copy(A->data[k], err);
639 } else if (A->type == GRETL_TYPE_ARRAYS) {
640 C->data[i] = gretl_array_copy(A->data[k], err);
641 } else if (A->type == GRETL_TYPE_LISTS) {
642 C->data[i] = gretl_list_copy(A->data[k]);
643 }
644 if (!*err && C->data[i] == NULL) {
645 *err = E_ALLOC;
646 }
647 }
648 }
649 }
650
651 if (*err && C != NULL) {
652 gretl_array_destroy(C);
653 C = NULL;
654 }
655
656 return C;
657 }
658
gretl_array_get_bundle(gretl_array * A,int i)659 gretl_bundle *gretl_array_get_bundle (gretl_array *A, int i)
660 {
661 gretl_bundle *b = NULL;
662
663 /* The bundle returned here is not "deep copied",
664 we just pass the pointer. It's up to the caller to
665 decide if a copy has to be made, given that the
666 pointer from here should not be modified.
667 */
668
669 if (A != NULL && i >= 0 && i < A->n &&
670 A->type == GRETL_TYPE_BUNDLES) {
671 b = A->data[i];
672 }
673
674 return b;
675 }
676
677 /* "flatten" an array of matrices, yielding a single matrix,
678 by either horizontal or vertical concatenation. By
679 default the concatenation is horizontal but if @vcat is
680 non-zero it's vertical. An error is flagged if the
681 matrices are not conformable for the operation.
682 */
683
gretl_matrix_array_flatten(gretl_array * A,int vcat,int * err)684 gretl_matrix *gretl_matrix_array_flatten (gretl_array *A,
685 int vcat,
686 int *err)
687 {
688 gretl_matrix *ret = NULL;
689 gretl_matrix *m;
690 int common_r = 1;
691 int common_c = 1;
692 int sum_r = 0;
693 int sum_c = 0;
694 int r0 = 0, c0 = 0;
695 int cmplx = 0;
696 int real = 0;
697 int i;
698
699 if (A->type != GRETL_TYPE_MATRICES) {
700 *err = E_TYPES;
701 return NULL;
702 }
703
704 for (i=0; i<A->n; i++) {
705 m = A->data[i];
706 if (!gretl_is_null_matrix(m)) {
707 if (m->is_complex) {
708 cmplx = 1;
709 } else {
710 real = 1;
711 }
712 }
713 }
714
715 for (i=0; i<A->n; i++) {
716 m = A->data[i];
717 if (!gretl_is_null_matrix(m)) {
718 if (c0 == 0) {
719 r0 = m->rows;
720 c0 = m->cols;
721 } else {
722 if (m->rows != r0) {
723 common_r = 0;
724 }
725 if (m->cols != c0) {
726 common_c = 0;
727 }
728 if (!common_r && !common_c) {
729 *err = E_NONCONF;
730 break;
731 }
732 }
733 sum_r += m->rows;
734 sum_c += m->cols;
735 }
736 }
737
738 if (!*err) {
739 if ((vcat && !common_c) || (!vcat && !common_r)) {
740 *err = E_NONCONF;
741 }
742 }
743
744 if (!*err && sum_r == 0) {
745 ret = gretl_null_matrix_new();
746 if (ret == NULL) {
747 *err = E_ALLOC;
748 }
749 }
750
751 if (*err || ret != NULL) {
752 return ret;
753 }
754
755 if (vcat) {
756 if (cmplx) {
757 ret = gretl_cmatrix_new(sum_r, c0);
758 } else {
759 ret = gretl_matrix_alloc(sum_r, c0);
760 }
761 } else {
762 if (cmplx) {
763 ret = gretl_cmatrix_new(r0, sum_c);
764 } else {
765 ret = gretl_matrix_alloc(r0, sum_c);
766 }
767 }
768
769 if (ret == NULL) {
770 *err = E_ALLOC;
771 } else if (vcat) {
772 /* vertical concatenation */
773 int ii, j, k, rpos = 0;
774 double complex z;
775 double x;
776
777 for (k=0; k<A->n; k++) {
778 m = A->data[k];
779 if (!gretl_is_null_matrix(m)) {
780 for (j=0; j<c0; j++) {
781 for (i=0, ii=rpos; i<m->rows; i++, ii++) {
782 if (cmplx && !m->is_complex) {
783 z = gretl_matrix_get(m, i, j);
784 gretl_cmatrix_set(ret, ii, j, z);
785 } else if (cmplx) {
786 z = gretl_cmatrix_get(m, i, j);
787 gretl_cmatrix_set(ret, ii, j, z);
788 } else {
789 x = gretl_matrix_get(m, i, j);
790 gretl_matrix_set(ret, ii, j, x);
791 }
792 }
793 }
794 rpos += m->rows;
795 }
796 }
797 } else if (cmplx && real) {
798 /* horizontal concatenation: mixed matrices */
799 double complex *dest = ret->z;
800 int n, k = 0;
801
802 for (i=0; i<A->n; i++) {
803 m = A->data[i];
804 if (!gretl_is_null_matrix(m)) {
805 n = m->rows * m->cols;
806 if (m->is_complex) {
807 memcpy(dest, m->z, n * sizeof *dest);
808 } else {
809 real_to_complex_fill(ret, m, 0, k);
810 }
811 dest += n;
812 k += m->cols;
813 }
814 }
815 } else {
816 /* horizontal concatenation: the easy case */
817 double *dest = ret->val;
818 int n, p = cmplx ? 2 : 1;
819
820 for (i=0; i<A->n; i++) {
821 m = A->data[i];
822 if (!gretl_is_null_matrix(m)) {
823 n = p * m->rows * m->cols;
824 memcpy(dest, m->val, n * sizeof *dest);
825 dest += n;
826 }
827 }
828 }
829
830 return ret;
831 }
832
split_matrix_by_chunks(gretl_array * A,int n,const gretl_matrix * X,int chunk,int colwise)833 static int split_matrix_by_chunks (gretl_array *A, int n,
834 const gretl_matrix *X,
835 int chunk, int colwise)
836 {
837 int rows = colwise ? X->rows : chunk;
838 int cols = colwise ? chunk : X->cols;
839 gretl_matrix *tmp;
840 int i, err = 0;
841
842 /* allocate the matrices */
843 for (i=0; i<n && !err; i++) {
844 tmp = gretl_matrix_alloc(rows, cols);
845 if (tmp == NULL) {
846 err = E_ALLOC;
847 } else {
848 gretl_array_set_element(A, i, tmp, GRETL_TYPE_MATRIX, 0);
849 }
850 }
851
852 /* fill the matrices */
853 if (!err && colwise) {
854 int nelem = rows * cols;
855 size_t csize = nelem * sizeof *X->val;
856 const double *src = X->val;
857
858 for (i=0; i<n; i++) {
859 tmp = A->data[i];
860 memcpy(tmp->val, src, csize);
861 src += nelem;
862 }
863 } else if (!err) {
864 int k, j, ii = 0;
865 double x;
866
867 for (k=0; k<n; k++) {
868 tmp = A->data[k];
869 for (j=0; j<cols; j++) {
870 for (i=0; i<rows; i++) {
871 x = gretl_matrix_get(X, ii+i, j);
872 gretl_matrix_set(tmp, i, j, x);
873 }
874 }
875 ii += rows;
876 }
877 }
878
879 return err;
880 }
881
split_matrix_by_vector(gretl_array * A,int n,const gretl_matrix * X,int dim,int colwise,gretl_matrix * vals,const double * sel)882 static int split_matrix_by_vector (gretl_array *A, int n,
883 const gretl_matrix *X,
884 int dim, int colwise,
885 gretl_matrix *vals,
886 const double *sel)
887 {
888 int *nj = NULL;
889 gretl_matrix *tmp;
890 int rows, cols;
891 int i, j, k;
892 int err = 0;
893
894 /* How many rows or columns will each matrix need? */
895 nj = calloc(n, sizeof *nj);
896 if (nj == NULL) {
897 err = E_ALLOC;
898 } else {
899 for (i=0; i<dim; i++) {
900 j = sel[i] - 1;
901 nj[j] += 1;
902 }
903 }
904 for (i=0; i<n && !err; i++) {
905 if (nj[i] > 0) {
906 rows = colwise ? X->rows : nj[i];
907 cols = colwise ? nj[i] : X->cols;
908 tmp = gretl_matrix_alloc(rows, cols);
909 if (tmp == NULL) {
910 err = E_ALLOC;
911 } else {
912 gretl_array_set_element(A, i, tmp, GRETL_TYPE_MATRIX, 0);
913 /* @nj will serve as an array of counters below */
914 nj[i] = 0;
915 }
916 }
917 }
918
919 /* fill the individual matrices */
920 if (!err && colwise) {
921 size_t csize = X->rows * sizeof *X->val;
922 const double *src = X->val;
923 double *targ;
924
925 for (i=0; i<X->cols; i++) {
926 k = sel[i] - 1;
927 tmp = A->data[k];
928 targ = tmp->val + nj[k];
929 memcpy(targ, src, csize);
930 /* advance the read and write positions */
931 src += X->rows;
932 nj[k] += X->rows;
933 }
934 } else if (!err) {
935 double x;
936 int jj;
937
938 for (i=0; i<X->rows; i++) {
939 k = sel[i] - 1;
940 tmp = A->data[k];
941 jj = 0;
942 for (j=0; j<X->cols; j++) {
943 x = gretl_matrix_get(X, i, j);
944 gretl_matrix_set(tmp, nj[k], jj++, x);
945 }
946 /* advance the write position */
947 nj[k] += 1;
948 }
949 }
950
951 free(nj);
952
953 return err;
954 }
955
gretl_matrix_split_by(const gretl_matrix * X,const gretl_matrix * v,int colwise,int * err)956 gretl_array *gretl_matrix_split_by (const gretl_matrix *X,
957 const gretl_matrix *v,
958 int colwise, int *err)
959 {
960 gretl_array *ret = NULL;
961 int i, dim, nm = 0;
962 int chunk = 0;
963 gretl_matrix *vals = NULL;
964 const double *sel;
965 double x;
966
967 dim = colwise ? X->cols : X->rows;
968
969 if (gretl_vector_get_length(v) == 1) {
970 /* the chunk-size variant */
971 chunk = v->val[0];
972 if (chunk <= 0 || chunk > dim) {
973 *err = E_INVARG;
974 } else if (dim % chunk != 0) {
975 *err = E_NONCONF;
976 }
977 } else if (gretl_vector_get_length(v) == dim) {
978 /* vector of indices: only positive integers allowed */
979 for (i=0; i<dim; i++) {
980 x = v->val[i];
981 if (x != floor(x) || x <= 0 || x >= INT_MAX) {
982 *err = E_INVARG;
983 break;
984 }
985 }
986 } else {
987 *err = E_INVARG;
988 }
989
990 if (*err) {
991 return NULL;
992 }
993
994 /* How many matrices do we need ? */
995 if (chunk > 0) {
996 nm = dim / chunk;
997 } else {
998 sel = v->val;
999 vals = gretl_matrix_values(sel, dim, OPT_NONE, err);
1000 if (!*err) {
1001 /* get the maximum index value */
1002 for (i=0; i<vals->rows; i++) {
1003 nm = vals->val[i] > nm ? vals->val[i] : nm;
1004 }
1005 }
1006 }
1007
1008 if (!*err) {
1009 ret = gretl_array_new(GRETL_TYPE_MATRICES, nm, err);
1010 }
1011
1012 if (!*err && chunk > 0) {
1013 /* the easier case */
1014 *err = split_matrix_by_chunks(ret, nm, X, chunk, colwise);
1015 } else if (!*err) {
1016 /* the fiddly but general one */
1017 *err = split_matrix_by_vector(ret, nm, X, dim, colwise, vals, sel);
1018 }
1019
1020 gretl_matrix_free(vals);
1021
1022 if (*err && ret != NULL) {
1023 gretl_array_destroy(ret);
1024 ret = NULL;
1025 }
1026
1027 return ret;
1028 }
1029
gretl_array_set_type(gretl_array * A,GretlType type)1030 int gretl_array_set_type (gretl_array *A, GretlType type)
1031 {
1032 int err = 0;
1033
1034 if (A == NULL) {
1035 err = E_DATA;
1036 } else if (type != GRETL_TYPE_STRINGS &&
1037 type != GRETL_TYPE_MATRICES &&
1038 type != GRETL_TYPE_BUNDLES &&
1039 type != GRETL_TYPE_LISTS &&
1040 type != GRETL_TYPE_ARRAYS) {
1041 err = E_TYPES;
1042 } else if (type == A->type) {
1043 /* no-op */
1044 return 0;
1045 } else if (A->n > 0) {
1046 /* we can (re-)set the type only if no data have
1047 been entered already
1048 */
1049 int i;
1050
1051 for (i=0; i<A->n; i++) {
1052 if (A->data[i] != NULL) {
1053 err = E_DATA;
1054 break;
1055 }
1056 }
1057 }
1058
1059 if (!err) {
1060 A->type = type;
1061 }
1062
1063 return err;
1064 }
1065
gretl_array_get_type(gretl_array * A)1066 GretlType gretl_array_get_type (gretl_array *A)
1067 {
1068 return (A != NULL)? A->type : GRETL_TYPE_NONE;
1069 }
1070
gretl_array_get_content_type(gretl_array * A)1071 GretlType gretl_array_get_content_type (gretl_array *A)
1072 {
1073 return (A != NULL)? gretl_type_get_singular(A->type) : GRETL_TYPE_NONE;
1074 }
1075
gretl_array_get_length(gretl_array * A)1076 int gretl_array_get_length (gretl_array *A)
1077 {
1078 return (A != NULL)? A->n : 0;
1079 }
1080
1081 /* Return the 0-based index of the first empty slot
1082 in @A, or -1 on failure (if @A is NULL or all its
1083 slots are already filled).
1084 */
1085
gretl_array_get_next_index(gretl_array * A)1086 int gretl_array_get_next_index (gretl_array *A)
1087 {
1088 int ret = -1;
1089
1090 if (A != NULL) {
1091 int i;
1092
1093 for (i=0; i<A->n; i++) {
1094 if (A->data[i] == NULL) {
1095 ret = i;
1096 break;
1097 }
1098 }
1099 }
1100
1101 return ret;
1102 }
1103
set_string(gretl_array * A,int i,char * s,int copy)1104 static int set_string (gretl_array *A, int i,
1105 char *s, int copy)
1106 {
1107 int err = 0;
1108
1109 if (copy) {
1110 A->data[i] = gretl_strdup(s);
1111 if (A->data[i] == NULL) {
1112 err = E_ALLOC;
1113 }
1114 } else {
1115 A->data[i] = s;
1116 }
1117
1118 return err;
1119 }
1120
1121 /* The static set_*() functions assume that error-checking
1122 has already been done.
1123 */
1124
set_matrix(gretl_array * A,int i,gretl_matrix * m,int copy)1125 static int set_matrix (gretl_array *A, int i,
1126 gretl_matrix *m, int copy)
1127 {
1128 int err = 0;
1129
1130 if (copy) {
1131 A->data[i] = gretl_matrix_copy(m);
1132 if (A->data[i] == NULL) {
1133 err = E_ALLOC;
1134 }
1135 } else {
1136 A->data[i] = m;
1137 }
1138
1139 return err;
1140 }
1141
set_bundle(gretl_array * A,int i,gretl_bundle * b,int copy)1142 static int set_bundle (gretl_array *A, int i,
1143 gretl_bundle *b, int copy)
1144 {
1145 int err = 0;
1146
1147 if (copy) {
1148 A->data[i] = gretl_bundle_copy(b, &err);
1149 } else {
1150 A->data[i] = b;
1151 }
1152
1153 return err;
1154 }
1155
set_array(gretl_array * A,int i,gretl_array * a,int copy)1156 static int set_array (gretl_array *A, int i,
1157 gretl_array *a, int copy)
1158 {
1159 int err = 0;
1160
1161 if (copy) {
1162 A->data[i] = gretl_array_copy(a, &err);
1163 } else {
1164 A->data[i] = a;
1165 }
1166
1167 return err;
1168 }
1169
set_list(gretl_array * A,int i,int * L,int copy)1170 static int set_list (gretl_array *A, int i,
1171 int *L, int copy)
1172 {
1173 int err = 0;
1174
1175 if (copy) {
1176 A->data[i] = gretl_list_copy(L);
1177 if (A->data[i] == NULL) {
1178 err = E_ALLOC;
1179 }
1180 } else {
1181 A->data[i] = L;
1182 }
1183
1184 return err;
1185 }
1186
set_type_error(gretl_array * A,GretlType required)1187 static int set_type_error (gretl_array *A,
1188 GretlType required)
1189 {
1190 if (A->type == GRETL_TYPE_ANY) {
1191 A->type = required;
1192 return 0;
1193 } else if (A->type != required) {
1194 GretlType reqt = gretl_type_get_singular(required);
1195
1196 gretl_errmsg_sprintf("Cannot add %s to array of %s",
1197 gretl_type_get_name(reqt),
1198 gretl_type_get_name(A->type));
1199 return 1;
1200 } else {
1201 return 0;
1202 }
1203 }
1204
1205 /* In the functions below we assume the @copy parameter
1206 will be set appropriately by "genr": if the incoming
1207 object is a named variable in its own right it should
1208 be copied, but if it's on on-the-fly thing there's
1209 no need to copy it, just "donate" it to the array.
1210 */
1211
1212 /* respond to A[i] = s */
1213
gretl_array_set_string(gretl_array * A,int i,char * s,int copy)1214 int gretl_array_set_string (gretl_array *A, int i,
1215 char *s, int copy)
1216 {
1217 int err = 0;
1218
1219 if (A == NULL) {
1220 err = E_DATA;
1221 } else if (set_type_error(A, GRETL_TYPE_STRINGS)) {
1222 err = E_TYPES;
1223 } else if (i < 0 || i >= A->n) {
1224 gretl_errmsg_sprintf(_("Index value %d is out of bounds"), i+1);
1225 err = E_DATA;
1226 } else if (s != A->data[i]) {
1227 free(A->data[i]);
1228 err = set_string(A, i, s, copy);
1229 }
1230
1231 return err;
1232 }
1233
1234 /* respond to A += s */
1235
gretl_array_append_string(gretl_array * A,char * s,int copy)1236 int gretl_array_append_string (gretl_array *A,
1237 char *s,
1238 int copy)
1239 {
1240 int err = 0;
1241
1242 if (A == NULL) {
1243 err = E_DATA;
1244 } else if (set_type_error(A, GRETL_TYPE_STRINGS)) {
1245 err = E_TYPES;
1246 } else {
1247 err = array_extend_content(A, 1);
1248 if (!err) {
1249 err = set_string(A, A->n - 1, s, copy);
1250 }
1251 }
1252
1253 return err;
1254 }
1255
1256 /* respond to A[i] = m */
1257
gretl_array_set_matrix(gretl_array * A,int i,gretl_matrix * m,int copy)1258 int gretl_array_set_matrix (gretl_array *A, int i,
1259 gretl_matrix *m,
1260 int copy)
1261 {
1262 int err = 0;
1263
1264 if (A == NULL) {
1265 err = E_DATA;
1266 } else if (set_type_error(A, GRETL_TYPE_MATRICES)) {
1267 err = E_TYPES;
1268 } else if (i < 0 || i >= A->n) {
1269 gretl_errmsg_sprintf(_("Index value %d is out of bounds"), i+1);
1270 err = E_DATA;
1271 } else if (m != A->data[i]) {
1272 gretl_matrix_free(A->data[i]);
1273 err = set_matrix(A, i, m, copy);
1274 }
1275
1276 return err;
1277 }
1278
1279 /* respond to A += m */
1280
gretl_array_append_matrix(gretl_array * A,gretl_matrix * m,int copy)1281 int gretl_array_append_matrix (gretl_array *A,
1282 gretl_matrix *m,
1283 int copy)
1284 {
1285 int err = 0;
1286
1287 if (A == NULL) {
1288 err = E_DATA;
1289 } else if (set_type_error(A, GRETL_TYPE_MATRICES)) {
1290 err = E_TYPES;
1291 } else {
1292 err = array_extend_content(A, 1);
1293 if (!err) {
1294 err = set_matrix(A, A->n - 1, m, copy);
1295 }
1296 }
1297
1298 return err;
1299 }
1300
1301 /* respond to A[i] = b */
1302
gretl_array_set_bundle(gretl_array * A,int i,gretl_bundle * b,int copy)1303 int gretl_array_set_bundle (gretl_array *A, int i,
1304 gretl_bundle *b,
1305 int copy)
1306 {
1307 int err = 0;
1308
1309 if (A == NULL) {
1310 err = E_DATA;
1311 } else if (set_type_error(A, GRETL_TYPE_BUNDLES)) {
1312 err = E_TYPES;
1313 } else if (i < 0 || i >= A->n) {
1314 gretl_errmsg_sprintf(_("Index value %d is out of bounds"), i+1);
1315 err = E_DATA;
1316 } else if (b != A->data[i]) {
1317 gretl_bundle_destroy(A->data[i]);
1318 err = set_bundle(A, i, b, copy);
1319 }
1320
1321 return err;
1322 }
1323
1324 /* respond to A[i] = a */
1325
gretl_array_set_array(gretl_array * A,int i,gretl_array * a,int copy)1326 int gretl_array_set_array (gretl_array *A, int i,
1327 gretl_array *a,
1328 int copy)
1329 {
1330 int err = 0;
1331
1332 if (A == NULL) {
1333 err = E_DATA;
1334 } else if (set_type_error(A, GRETL_TYPE_ARRAYS)) {
1335 err = E_TYPES;
1336 } else if (i < 0 || i >= A->n) {
1337 gretl_errmsg_sprintf(_("Index value %d is out of bounds"), i+1);
1338 err = E_DATA;
1339 } else if (a != A->data[i]) {
1340 gretl_array_destroy(A->data[i]);
1341 err = set_array(A, i, a, copy);
1342 }
1343
1344 return err;
1345 }
1346
1347 /* respond to A += b */
1348
gretl_array_append_bundle(gretl_array * A,gretl_bundle * b,int copy)1349 int gretl_array_append_bundle (gretl_array *A,
1350 gretl_bundle *b,
1351 int copy)
1352 {
1353 int err = 0;
1354
1355 if (A == NULL) {
1356 err = E_DATA;
1357 } else if (set_type_error(A, GRETL_TYPE_BUNDLES)) {
1358 err = E_TYPES;
1359 } else {
1360 err = array_extend_content(A, 1);
1361 if (!err) {
1362 err = set_bundle(A, A->n - 1, b, copy);
1363 }
1364 }
1365
1366 return err;
1367 }
1368
1369 /* respond to A += a */
1370
gretl_array_append_array(gretl_array * A,gretl_array * a,int copy)1371 int gretl_array_append_array (gretl_array *A,
1372 gretl_array *a,
1373 int copy)
1374 {
1375 int err = 0;
1376
1377 if (A == NULL) {
1378 err = E_DATA;
1379 } else if (set_type_error(A, GRETL_TYPE_ARRAYS)) {
1380 err = E_TYPES;
1381 } else {
1382 err = array_extend_content(A, 1);
1383 if (!err) {
1384 err = set_array(A, A->n - 1, a, copy);
1385 }
1386 }
1387
1388 return err;
1389 }
1390
1391 /* respond to A[i] = L */
1392
gretl_array_set_list(gretl_array * A,int i,int * L,int copy)1393 int gretl_array_set_list (gretl_array *A, int i,
1394 int *L, int copy)
1395 {
1396 int err = 0;
1397
1398 if (A == NULL) {
1399 err = E_DATA;
1400 } else if (set_type_error(A, GRETL_TYPE_LISTS)) {
1401 err = E_TYPES;
1402 } else if (i < 0 || i >= A->n) {
1403 gretl_errmsg_sprintf(_("Index value %d is out of bounds"), i+1);
1404 err = E_DATA;
1405 } else if (L != A->data[i]) {
1406 free(A->data[i]);
1407 err = set_list(A, i, L, copy);
1408 }
1409
1410 return err;
1411 }
1412
1413 /* respond to A += L */
1414
gretl_array_append_list(gretl_array * A,int * L,int copy)1415 int gretl_array_append_list (gretl_array *A,
1416 int *L, int copy)
1417 {
1418 int err = 0;
1419
1420 if (A == NULL) {
1421 err = E_DATA;
1422 } else if (set_type_error(A, GRETL_TYPE_LISTS)) {
1423 err = E_TYPES;
1424
1425 } else {
1426 err = array_extend_content(A, 1);
1427 if (!err) {
1428 err = set_list(A, A->n - 1, L, copy);
1429 }
1430 }
1431
1432 return err;
1433 }
1434
gretl_array_set_element(gretl_array * A,int i,void * ptr,GretlType type,int copy)1435 int gretl_array_set_element (gretl_array *A, int i,
1436 void *ptr, GretlType type,
1437 int copy)
1438 {
1439 int err = 0;
1440
1441 if (type == GRETL_TYPE_MATRIX) {
1442 err = gretl_array_set_matrix(A, i, ptr, copy);
1443 } else if (type == GRETL_TYPE_STRING) {
1444 err = gretl_array_set_string(A, i, ptr, copy);
1445 } else if (type == GRETL_TYPE_BUNDLE) {
1446 err = gretl_array_set_bundle(A, i, ptr, copy);
1447 } else if (type == GRETL_TYPE_LIST) {
1448 err = gretl_array_set_list(A, i, ptr, copy);
1449 } else if (type == GRETL_TYPE_ARRAY) {
1450 err = gretl_array_set_array(A, i, ptr, copy);
1451 }
1452
1453 return err;
1454 }
1455
free_array_element(gretl_array * A,int i)1456 static void free_array_element (gretl_array *A, int i)
1457 {
1458 if (A->type == GRETL_TYPE_STRINGS ||
1459 A->type == GRETL_TYPE_LISTS) {
1460 free(A->data[i]);
1461 } else if (A->type == GRETL_TYPE_MATRICES) {
1462 gretl_matrix_free(A->data[i]);
1463 } else if (A->type == GRETL_TYPE_BUNDLES) {
1464 gretl_bundle_destroy(A->data[i]);
1465 } else if (A->type == GRETL_TYPE_ARRAYS) {
1466 gretl_array_destroy(A->data[i]);
1467 }
1468 }
1469
gretl_array_delete_element(gretl_array * A,int i)1470 int gretl_array_delete_element (gretl_array *A, int i)
1471 {
1472 if (A == NULL) {
1473 return E_DATA;
1474 } else if (i < 0 || i >= A->n) {
1475 return E_INVARG;
1476 } else {
1477 int j;
1478
1479 if (A->data[i] != NULL) {
1480 free_array_element(A, i);
1481 }
1482 /* shift the higher-numbered elements down */
1483 for (j=i; j<A->n-1; j++) {
1484 A->data[j] = A->data[j+1];
1485 }
1486 /* decrement the element count */
1487 A->n -= 1;
1488
1489 return 0;
1490 }
1491 }
1492
1493 /* Drop any/all occurrences of string @s from array @A */
1494
gretl_array_drop_string(gretl_array * A,const char * s)1495 int gretl_array_drop_string (gretl_array *A, const char *s)
1496 {
1497 if (A->type != GRETL_TYPE_STRINGS) {
1498 return E_TYPES;
1499 } else {
1500 int i, j, rem = A->n;
1501 int n_orig = A->n;
1502 size_t sz;
1503
1504 for (i=0; ; ) {
1505 if (A->data[i] != NULL && !strcmp(A->data[i], s)) {
1506 free(A->data[i]);
1507 j = i + 1;
1508 while (A->data[j] != NULL && !strcmp(A->data[j], s)) {
1509 free(A->data[j++]);
1510 }
1511 rem = A->n - j;
1512 sz = rem * sizeof *A->data;
1513 memmove(A->data + i, A->data + j, sz);
1514 A->n -= j - i;
1515 i = j;
1516 } else {
1517 i++;
1518 }
1519 if (i == A->n || rem == 0) {
1520 break;
1521 }
1522 }
1523 if (A->n == 0) {
1524 free(A->data);
1525 A->data = NULL;
1526 } else if (A->n < n_orig) {
1527 A->data = realloc(A->data, A->n * sizeof(void *));
1528 }
1529 }
1530
1531 return 0;
1532 }
1533
1534 /* @ptr must be pre-checked as matching the array type */
1535
gretl_array_append_object(gretl_array * A,void * ptr,int copy)1536 int gretl_array_append_object (gretl_array *A,
1537 void *ptr,
1538 int copy)
1539 {
1540 int err = 0;
1541
1542 if (A == NULL) {
1543 err = E_DATA;
1544 } else if (A->type == GRETL_TYPE_MATRICES) {
1545 gretl_array_append_matrix(A, ptr, copy);
1546 } else if (A->type == GRETL_TYPE_STRINGS) {
1547 gretl_array_append_string(A, ptr, copy);
1548 } else if (A->type == GRETL_TYPE_BUNDLES) {
1549 gretl_array_append_bundle(A, ptr, copy);
1550 } else if (A->type == GRETL_TYPE_LISTS) {
1551 gretl_array_append_list(A, ptr, copy);
1552 } else if (A->type == GRETL_TYPE_ARRAYS) {
1553 gretl_array_append_array(A, ptr, copy);
1554 }
1555
1556 return err;
1557 }
1558
1559 static int
gretl_array_copy_content(gretl_array * Acpy,const gretl_array * A,int write_offset)1560 gretl_array_copy_content (gretl_array *Acpy, const gretl_array *A,
1561 int write_offset)
1562 {
1563 int i, j, err = 0;
1564
1565 for (i=0; i<A->n && !err; i++) {
1566 if (A->data[i] != NULL) {
1567 j = i + write_offset;
1568 if (A->type == GRETL_TYPE_STRINGS) {
1569 Acpy->data[j] = gretl_strdup(A->data[i]);
1570 } else if (A->type == GRETL_TYPE_MATRICES) {
1571 Acpy->data[j] = gretl_matrix_copy(A->data[i]);
1572 } else if (A->type == GRETL_TYPE_BUNDLES) {
1573 Acpy->data[j] = gretl_bundle_copy(A->data[i], &err);
1574 } else if (A->type == GRETL_TYPE_ARRAYS) {
1575 Acpy->data[j] = gretl_array_copy(A->data[i], &err);
1576 } else if (A->type == GRETL_TYPE_LISTS) {
1577 Acpy->data[j] = gretl_list_copy(A->data[i]);
1578 } else {
1579 err = E_TYPES;
1580 }
1581 if (!err && Acpy->data[j] == NULL) {
1582 err = E_ALLOC;
1583 }
1584 }
1585 }
1586
1587 return err;
1588 }
1589
gretl_array_copy(const gretl_array * A,int * err)1590 gretl_array *gretl_array_copy (const gretl_array *A,
1591 int *err)
1592 {
1593 gretl_array *Acpy = NULL;
1594
1595 if (A != NULL) {
1596 Acpy = gretl_array_new(A->type, A->n, err);
1597 if (!*err) {
1598 *err = gretl_array_copy_content(Acpy, A, 0);
1599 }
1600 }
1601
1602 return Acpy;
1603 }
1604
compare_strings(const void * a,const void * b)1605 static int compare_strings (const void *a, const void *b)
1606 {
1607 const char **sa = (const char **) a;
1608 const char **sb = (const char **) b;
1609
1610 return g_strcmp0(*sa, *sb);
1611 }
1612
inverse_compare_strings(const void * a,const void * b)1613 static int inverse_compare_strings (const void *a, const void *b)
1614 {
1615 const char **sa = (const char **) a;
1616 const char **sb = (const char **) b;
1617
1618 return -g_strcmp0(*sa, *sb);
1619 }
1620
gretl_strings_sort(const gretl_array * A,int descending,int * err)1621 gretl_array *gretl_strings_sort (const gretl_array *A,
1622 int descending,
1623 int *err)
1624 {
1625 gretl_array *Asrt = NULL;
1626
1627 if (A != NULL) {
1628 if (A->type != GRETL_TYPE_STRINGS) {
1629 *err = E_TYPES;
1630 } else {
1631 Asrt = gretl_array_new(A->type, A->n, err);
1632 }
1633 if (!*err) {
1634 *err = gretl_array_copy_content(Asrt, A, 0);
1635 }
1636 if (!*err) {
1637 qsort(Asrt->data, Asrt->n, sizeof *Asrt->data,
1638 descending ? inverse_compare_strings : compare_strings);
1639 }
1640 }
1641
1642 return Asrt;
1643 }
1644
1645 /* respond to A1 += A2 */
1646
gretl_array_copy_into(gretl_array * A1,const gretl_array * A2)1647 int gretl_array_copy_into (gretl_array *A1,
1648 const gretl_array *A2)
1649 {
1650 int old_n = 0, err = 0;
1651
1652 if (A1 == NULL || A2 == NULL) {
1653 err = E_DATA;
1654 } else if (A1->type != A2->type) {
1655 err = E_TYPES;
1656 } else {
1657 old_n = A1->n;
1658 err = array_extend_content(A1, A2->n);
1659 }
1660
1661 if (!err) {
1662 err = gretl_array_copy_content(A1, A2, old_n);
1663 }
1664
1665 return err;
1666 }
1667
1668 /* respond to C = A + B */
1669
gretl_arrays_join(gretl_array * A,gretl_array * B,int * err)1670 gretl_array *gretl_arrays_join (gretl_array *A,
1671 gretl_array *B,
1672 int *err)
1673 {
1674 gretl_array *C = NULL;
1675
1676 if (A == NULL || B == NULL) {
1677 *err = E_DATA;
1678 } else if (A->type != B->type) {
1679 *err = E_TYPES;
1680 } else {
1681 int n = A->n + B->n;
1682
1683 C = gretl_array_new(A->type, n, err);
1684 }
1685
1686 if (!*err) {
1687 *err = gretl_array_copy_content(C, A, 0);
1688 }
1689
1690 if (!*err) {
1691 *err = gretl_array_copy_content(C, B, A->n);
1692 }
1693
1694 if (*err && C != NULL) {
1695 gretl_array_destroy(C);
1696 C = NULL;
1697 }
1698
1699 return C;
1700 }
1701
1702 /* respond to C = A || B */
1703
gretl_arrays_union(gretl_array * A,gretl_array * B,int * err)1704 gretl_array *gretl_arrays_union (gretl_array *A,
1705 gretl_array *B,
1706 int *err)
1707 {
1708 gretl_array *C = NULL;
1709 const char *sa, *sb;
1710 char *copy = NULL;
1711 int i, j, n = 0;
1712
1713 if (A == NULL || B == NULL) {
1714 *err = E_DATA;
1715 } else if (A->type != GRETL_TYPE_STRINGS ||
1716 B->type != GRETL_TYPE_STRINGS) {
1717 *err = E_TYPES;
1718 } else {
1719 if (B->n > 0) {
1720 copy = calloc(1, B->n);
1721 }
1722 n = A->n;
1723 for (j=0; j<B->n; j++) {
1724 sb = B->data[j];
1725 if (sb == NULL || *sb == '\0') {
1726 continue;
1727 }
1728 copy[j] = 1;
1729 for (i=0; i<A->n; i++) {
1730 sa = A->data[i];
1731 if (sa == NULL || *sa == '\0') {
1732 continue;
1733 }
1734 if (strcmp(sa, sb) == 0) {
1735 copy[j] = 0;
1736 break;
1737 }
1738 }
1739 n += copy[j];
1740 }
1741 C = gretl_array_new(A->type, n, err);
1742 }
1743
1744 if (!*err) {
1745 *err = gretl_array_copy_content(C, A, 0);
1746 }
1747
1748 if (!*err && n > A->n) {
1749 i = A->n;
1750 for (j=0; j<B->n; j++) {
1751 if (copy[j]) {
1752 C->data[i++] = gretl_strdup(B->data[j]);
1753 }
1754 }
1755 }
1756 free(copy);
1757
1758 if (*err && C != NULL) {
1759 gretl_array_destroy(C);
1760 C = NULL;
1761 }
1762
1763 return C;
1764 }
1765
1766 /* respond to C = A && B */
1767
gretl_arrays_intersection(gretl_array * A,gretl_array * B,int * err)1768 gretl_array *gretl_arrays_intersection (gretl_array *A,
1769 gretl_array *B,
1770 int *err)
1771 {
1772 gretl_array *C = NULL;
1773 const char *sa, *sb;
1774 char *copy = NULL;
1775 int i, j, n = 0;
1776
1777 if (A == NULL || B == NULL) {
1778 *err = E_DATA;
1779 } else if (A->type != GRETL_TYPE_STRINGS ||
1780 B->type != GRETL_TYPE_STRINGS) {
1781 *err = E_TYPES;
1782 } else {
1783 if (A->n > 0) {
1784 copy = calloc(1, A->n);
1785 }
1786 for (i=0; i<A->n; i++) {
1787 sa = A->data[i];
1788 if (sa == NULL || *sa == '\0') {
1789 continue;
1790 }
1791 for (j=0; j<B->n; j++) {
1792 sb = B->data[j];
1793 if (sb == NULL || *sb == '\0') {
1794 continue;
1795 }
1796 if (strcmp(sa, sb) == 0) {
1797 copy[i] = 1;
1798 break;
1799 }
1800 }
1801 n += copy[i];
1802 }
1803 C = gretl_array_new(A->type, n, err);
1804 }
1805
1806 if (!*err && n > 0) {
1807 j = 0;
1808 for (i=0; i<A->n; i++) {
1809 if (copy[i]) {
1810 C->data[j++] = gretl_strdup(A->data[i]);
1811 }
1812 }
1813 }
1814 free(copy);
1815
1816 if (*err && C != NULL) {
1817 gretl_array_destroy(C);
1818 C = NULL;
1819 }
1820
1821 return C;
1822 }
1823
1824 /**
1825 * gretl_array_copy_as:
1826 * @name: name of source array.
1827 * @copyname: name for copy.
1828 * @copytpe: the type specified for the copied array, or 0.
1829 *
1830 * Look for a saved array specified by @name, and if found,
1831 * make a full copy and save it under @copyname. This is
1832 * called from geneval.c on completion of assignment to a
1833 * array named @copyname, where the returned value on the
1834 * right-hand side is a pre-existing array.
1835 *
1836 * Returns: 0 on success, non-zero code on error.
1837 */
1838
gretl_array_copy_as(const char * name,const char * copyname,GretlType copytype)1839 int gretl_array_copy_as (const char *name, const char *copyname,
1840 GretlType copytype)
1841 {
1842 gretl_array *A0, *A1 = NULL;
1843 user_var *u;
1844 int err = 0;
1845
1846 u = get_user_var_of_type_by_name(name, GRETL_TYPE_ARRAY);
1847 if (u == NULL) {
1848 return E_DATA;
1849 } else {
1850 A0 = user_var_get_value(u);
1851 }
1852
1853 if (copytype > 0 && A0->type != copytype) {
1854 return E_TYPES;
1855 }
1856
1857 /* is there a pre-existing array named @copyname? */
1858 u = get_user_var_of_type_by_name(copyname, GRETL_TYPE_ARRAY);
1859 if (u != NULL) {
1860 A1 = user_var_get_value(u);
1861 }
1862
1863 if (A1 != NULL) {
1864 if (A1->type != A0->type) {
1865 err = E_TYPES;
1866 } else {
1867 gretl_array_void_content(A1);
1868 A1->n = A0->n;
1869 err = array_allocate_storage(A1);
1870 if (!err) {
1871 err = gretl_array_copy_content(A1, A0, 0);
1872 }
1873 }
1874 } else {
1875 A1 = gretl_array_copy(A0, &err);
1876 if (!err) {
1877 err = user_var_add(copyname, A1->type, A1);
1878 }
1879 }
1880
1881 return err;
1882 }
1883
1884 /**
1885 * get_array_by_name:
1886 * @name: the name to look up.
1887 *
1888 * Returns: pointer to a saved array, if found, else NULL.
1889 */
1890
get_array_by_name(const char * name)1891 gretl_array *get_array_by_name (const char *name)
1892 {
1893 gretl_array *a = NULL;
1894
1895 if (name != NULL && *name != '\0') {
1896 user_var *u =
1897 get_user_var_of_type_by_name(name, GRETL_TYPE_ARRAY);
1898
1899 if (u != NULL) {
1900 a = user_var_get_value(u);
1901 }
1902 }
1903
1904 return a;
1905 }
1906
1907 /**
1908 * get_strings_array_by_name:
1909 * @name: the name to look up.
1910 *
1911 * Returns: pointer to a saved array of strings, if found, else NULL.
1912 */
1913
get_strings_array_by_name(const char * name)1914 gretl_array *get_strings_array_by_name (const char *name)
1915 {
1916 gretl_array *ret = NULL;
1917
1918 if (name != NULL && *name != '\0') {
1919 user_var *u =
1920 get_user_var_of_type_by_name(name, GRETL_TYPE_ARRAY);
1921
1922 if (u != NULL) {
1923 ret = user_var_get_value(u);
1924 if (ret->type != GRETL_TYPE_STRINGS) {
1925 ret = NULL;
1926 }
1927 }
1928 }
1929
1930 return ret;
1931 }
1932
gretl_array_pull_from_stack(const char * name,int * err)1933 gretl_array *gretl_array_pull_from_stack (const char *name,
1934 int *err)
1935 {
1936 gretl_array *a = NULL;
1937 user_var *u;
1938
1939 u = get_user_var_of_type_by_name(name, GRETL_TYPE_ARRAY);
1940
1941 if (u != NULL) {
1942 a = user_var_unstack_value(u);
1943 }
1944
1945 if (a == NULL) {
1946 *err = E_DATA;
1947 }
1948
1949 return a;
1950 }
1951
print_array_string(const char * s,PRN * prn)1952 static void print_array_string (const char *s, PRN *prn)
1953 {
1954 int n = strcspn(s, "\r\n");
1955 int m = strlen(s);
1956
1957 if (n > 72) {
1958 pprintf(prn, "\"%.69s...\"\n", s);
1959 } else if (n < m) {
1960 pprintf(prn, "\"%.*s...\"\n", n, s);
1961 } else {
1962 pprintf(prn, "\"%s\"\n", s);
1963 }
1964 }
1965
print_array_elements(gretl_array * A,int imin,int imax,int range,PRN * prn)1966 static void print_array_elements (gretl_array *A,
1967 int imin, int imax,
1968 int range, PRN *prn)
1969 {
1970 int i, lim = MIN(A->n, imax);
1971
1972 for (i=imin; i<lim; i++) {
1973 pprintf(prn, "[%d] ", i+1);
1974 if (A->data[i] == NULL) {
1975 pputs(prn, "null\n");
1976 } else if (A->type == GRETL_TYPE_STRINGS) {
1977 const char *s = A->data[i];
1978
1979 print_array_string(s, prn);
1980 } else if (A->type == GRETL_TYPE_MATRICES) {
1981 const gretl_matrix *m = A->data[i];
1982
1983 pprintf(prn, "%d x %d\n", m->rows, m->cols);
1984 } else if (A->type == GRETL_TYPE_LISTS) {
1985 const int *list = A->data[i];
1986
1987 gretl_list_print(list, NULL, prn);
1988 }
1989 }
1990
1991 if (!range && A->n > lim) {
1992 pputs(prn, "...\n\n");
1993 } else {
1994 pputc(prn, '\n');
1995 }
1996 }
1997
gretl_array_print(gretl_array * A,PRN * prn)1998 int gretl_array_print (gretl_array *A, PRN *prn)
1999 {
2000 if (A != NULL) {
2001 const char *s = gretl_type_get_name(A->type);
2002 int nmax = 10;
2003
2004 pprintf(prn, _("Array of %s, length %d\n"), s, A->n);
2005
2006 if (A->n > 0 &&
2007 A->type != GRETL_TYPE_BUNDLES && A->type != GRETL_TYPE_ARRAYS) {
2008 print_array_elements(A, 0, nmax, 0, prn);
2009 }
2010 }
2011
2012 return 0;
2013 }
2014
gretl_array_print_range(gretl_array * A,int imin,int imax,PRN * prn)2015 int gretl_array_print_range (gretl_array *A, int imin, int imax, PRN *prn)
2016 {
2017 if (A != NULL) {
2018 const char *s = gretl_type_get_name(A->type);
2019
2020 pprintf(prn, _("Array of %s, length %d\n"), s, A->n);
2021
2022 if (A->type != GRETL_TYPE_BUNDLES && A->type != GRETL_TYPE_ARRAYS) {
2023 print_array_elements(A, imin, imax, 1, prn);
2024 }
2025 }
2026
2027 return 0;
2028 }
2029
2030 /* Called from gretl_bundle.c when serializing a bundle
2031 which contains one or more arrays.
2032 */
2033
gretl_array_serialize(gretl_array * A,PRN * prn)2034 void gretl_array_serialize (gretl_array *A, PRN *prn)
2035 {
2036 GretlType type;
2037 const char *subname;
2038 void *ptr;
2039 int i;
2040
2041 type = gretl_type_get_singular(A->type);
2042 subname = gretl_type_get_name(type);
2043
2044 pprintf(prn, "<gretl-array type=\"%s\" length=\"%d\">\n",
2045 gretl_type_get_name(A->type), A->n);
2046
2047 for (i=0; i<A->n; i++) {
2048 ptr = A->data[i];
2049 if (ptr == NULL) {
2050 pprintf(prn, "<%s placeholder=\"true\"/>\n", subname);
2051 } else if (type == GRETL_TYPE_STRING) {
2052 gretl_xml_put_tagged_string("string", ptr, prn);
2053 } else if (type == GRETL_TYPE_MATRIX) {
2054 gretl_matrix_serialize(ptr, NULL, prn);
2055 } else if (type == GRETL_TYPE_BUNDLE) {
2056 gretl_bundle_serialize(ptr, NULL, prn);
2057 } else if (type == GRETL_TYPE_ARRAY) {
2058 gretl_array_serialize(ptr, prn);
2059 } else if (type == GRETL_TYPE_LIST) {
2060 gretl_xml_put_tagged_list("list", ptr, prn);
2061 }
2062 }
2063
2064 pputs(prn, "</gretl-array>\n");
2065 }
2066
name_matches_array_type(char * s,GretlType type)2067 static int name_matches_array_type (char *s, GretlType type)
2068 {
2069 if (!strncmp(s, "gretl-", 6)) {
2070 /* we're expecting "short-form" type strings */
2071 s += 6;
2072 }
2073
2074 return (gretl_type_from_string(s) == type);
2075 }
2076
deserialize_array_elements(gretl_array * A,xmlNodePtr cur,xmlDocPtr doc)2077 static int deserialize_array_elements (gretl_array *A,
2078 xmlNodePtr cur,
2079 xmlDocPtr doc)
2080 {
2081 GretlType type = gretl_type_get_singular(A->type);
2082 int i = 0, err = 0;
2083
2084 while (cur != NULL && !err && i < A->n) {
2085 if (!name_matches_array_type((char *) cur->name, type)) {
2086 fprintf(stderr, "deserialize array: mismatched element '%s'\n",
2087 (char *) cur->name);
2088 err = E_DATA;
2089 } else if (gretl_xml_get_prop_as_bool(cur, "placeholder")) {
2090 ; /* null array element: no-op */
2091 } else if (A->type == GRETL_TYPE_STRINGS) {
2092 A->data[i] = gretl_xml_get_string(cur, doc);
2093 } else if (A->type == GRETL_TYPE_MATRICES) {
2094 A->data[i] = gretl_xml_get_matrix(cur, doc, &err);
2095 } else if (A->type == GRETL_TYPE_BUNDLES) {
2096 A->data[i] = gretl_bundle_deserialize(cur, doc, &err);
2097 } else if (A->type == GRETL_TYPE_ARRAYS) {
2098 A->data[i] = gretl_array_deserialize(cur, doc, &err);
2099 } else if (A->type == GRETL_TYPE_LISTS) {
2100 A->data[i] = gretl_xml_get_list(cur, doc, &err);
2101 }
2102 /* note: arrays of scalars not handled */
2103 i++;
2104 cur = cur->next;
2105 }
2106
2107 if (!err && i != A->n) {
2108 fprintf(stderr, "deserialize array: array is corrupted\n");
2109 err = E_DATA;
2110 }
2111
2112 return err;
2113 }
2114
2115 /* For internal use only: @p1 should be of type xmlNodePtr and @p2
2116 should be an xmlDocPtr. We suppress the actual pointer types in the
2117 prototype so that it's possible for a module to include
2118 gretl_array.h without including the full libxml headers.
2119 */
2120
gretl_array_deserialize(void * p1,void * p2,int * err)2121 gretl_array *gretl_array_deserialize (void *p1, void *p2,
2122 int *err)
2123 {
2124 xmlNodePtr node = p1;
2125 xmlDocPtr doc = p2;
2126 GretlType type = 0;
2127 int n = 0;
2128 gretl_array *A = NULL;
2129
2130 if (xmlStrcmp(node->name, (XUC) "gretl-array")) {
2131 fprintf(stderr, "deserialize array: node is not gretl-array!\n");
2132 *err = E_DATA;
2133 } else {
2134 type = gretl_xml_get_type_property(node);
2135 if (type == 0) {
2136 fprintf(stderr, "deserialize array: couldn't get array type\n");
2137 *err = E_DATA;
2138 }
2139 }
2140
2141 if (!*err && !gretl_xml_get_prop_as_int(node, "length", &n)) {
2142 fprintf(stderr, "deserialize array: couldn't get length\n");
2143 *err = E_DATA;
2144 }
2145
2146 if (!*err) {
2147 A = gretl_array_new(type, n, err);
2148 }
2149
2150 if (A != NULL && n > 0) {
2151 *err = deserialize_array_elements(A, node->xmlChildrenNode, doc);
2152 if (*err) {
2153 gretl_array_destroy(A);
2154 A = NULL;
2155 }
2156 }
2157
2158 return A;
2159 }
2160
2161 /* In case a matrix is too wide for comfortable printing, split it by
2162 column. If there are one or more "leading" columns that should be
2163 displayed with each chunk of the matrix this should be signalled
2164 via a non-zero value for @leadcols. The maximum number of columns
2165 per chunk (including the leading columns, if any) is set by the
2166 @maxcols argument.
2167
2168 The return value is an array of suitably sized matrices. If @m
2169 has column names attached these are distributed to the matrices
2170 in the array.
2171 */
2172
gretl_matrix_col_split(const gretl_matrix * m,int leadcols,int maxcols,int * err)2173 gretl_array *gretl_matrix_col_split (const gretl_matrix *m,
2174 int leadcols, int maxcols,
2175 int *err)
2176 {
2177 gretl_array *a = NULL;
2178 int maincols, nm, rem;
2179
2180 if (gretl_is_null_matrix(m)) {
2181 *err = E_INVARG;
2182 } else {
2183 maincols = m->cols - leadcols;
2184 if (maincols <= 0) {
2185 *err = E_INVARG;
2186 }
2187 }
2188
2189 if (!*err) {
2190 /* how many matrices will we need? */
2191 nm = maincols / (maxcols - leadcols);
2192 rem = maincols % (maxcols - leadcols);
2193 nm += rem > 0;
2194 if (nm == 1) {
2195 /* nothing to be done */
2196 *err = E_INVARG;
2197 }
2198 }
2199
2200 if (!*err) {
2201 a = gretl_array_new(GRETL_TYPE_MATRICES, nm, err);
2202 }
2203
2204 if (!*err) {
2205 const char **S0 = gretl_matrix_get_colnames(m);
2206 char **Si = NULL;
2207 size_t rsize = m->rows * sizeof(double);
2208 const double *src;
2209 double *targ;
2210 gretl_matrix *ai;
2211 int i, j, cols, spos;
2212
2213 /* initial read position for "main" columns */
2214 src = m->val + leadcols * m->rows;
2215 spos = leadcols;
2216
2217 for (i=0; i<nm && !*err; i++) {
2218 cols = (i == nm-1 && rem > 0)? rem + leadcols : maxcols;
2219 ai = gretl_zero_matrix_new(m->rows, cols);
2220 if (ai == NULL) {
2221 *err = E_ALLOC;
2222 } else {
2223 Si = S0 == NULL ? NULL : strings_array_new(cols);
2224 /* initial write position */
2225 targ = ai->val;
2226 if (leadcols > 0) {
2227 memcpy(targ, m->val, leadcols * rsize);
2228 targ += leadcols * m->rows;
2229 if (Si != NULL) {
2230 /* transcribe column names */
2231 for (j=0; j<leadcols; j++) {
2232 Si[j] = gretl_strdup(S0[j]);
2233 }
2234 }
2235 }
2236 /* now handle the "main" columns */
2237 cols -= leadcols;
2238 memcpy(targ, src, cols * rsize);
2239 /* advance the read position */
2240 src += cols * m->rows;
2241 if (Si != NULL) {
2242 for (j=0; j<cols; j++) {
2243 Si[leadcols+j] = gretl_strdup(S0[spos++]);
2244 }
2245 gretl_matrix_set_colnames(ai, Si);
2246 }
2247 /* stick matrix @i into the array */
2248 gretl_array_set_matrix(a, i, ai, 0);
2249 }
2250 }
2251 }
2252
2253 if (*err && a != NULL) {
2254 gretl_array_destroy(a);
2255 a = NULL;
2256 }
2257
2258 return a;
2259 }
2260