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