Line data Source code
1 : /* Copyright (C) 2000 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : /*******************************************************************/
16 : /* */
17 : /* CONCATENATION */
18 : /* */
19 : /*******************************************************************/
20 : #include "pari.h"
21 : #include "paripriv.h"
22 :
23 : /* assume A or B is a t_LIST */
24 : static GEN
25 21 : listconcat(GEN A, GEN B)
26 : {
27 : long i, l1, lx;
28 : GEN L, z, L1, L2;
29 :
30 21 : if (typ(A) != t_LIST) {
31 7 : if (list_typ(B)!=t_LIST_RAW) pari_err_TYPE("listconcat",B);
32 7 : L2 = list_data(B);
33 7 : if (!L2) return mklistcopy(A);
34 7 : lx = lg(L2) + 1;
35 7 : z = mklist();
36 7 : list_data(z) = L = cgetg(lx, t_VEC);
37 35 : for (i = 2; i < lx; i++) gel(L,i) = gcopy(gel(L2,i-1));
38 7 : gel(L,1) = gcopy(A); return z;
39 14 : } else if (typ(B) != t_LIST) {
40 7 : if (list_typ(A)!=t_LIST_RAW) pari_err_TYPE("listconcat",A);
41 7 : L1 = list_data(A);
42 7 : if (!L1) return mklistcopy(B);
43 7 : lx = lg(L1) + 1;
44 7 : z = mklist();
45 7 : list_data(z) = L = cgetg(lx, t_VEC);
46 35 : for (i = 1; i < lx-1; i++) gel(L,i) = gcopy(gel(L1,i));
47 7 : gel(L,i) = gcopy(B); return z;
48 : }
49 : /* A, B both t_LISTs */
50 7 : if (list_typ(A)!=t_LIST_RAW) pari_err_TYPE("listconcat",A);
51 7 : if (list_typ(B)!=t_LIST_RAW) pari_err_TYPE("listconcat",B);
52 7 : L1 = list_data(A); if (!L1) return listcopy(B);
53 7 : L2 = list_data(B); if (!L2) return listcopy(A);
54 :
55 7 : l1 = lg(L1);
56 7 : lx = l1-1 + lg(L2);
57 7 : z = mklist();
58 7 : list_data(z) = L = cgetg(lx, t_VEC);
59 7 : L2 -= l1-1;
60 35 : for (i=1; i<l1; i++) gel(L,i) = gcopy(gel(L1,i));
61 35 : for ( ; i<lx; i++) gel(L,i) = gcopy(gel(L2,i));
62 7 : return z;
63 : }
64 :
65 : /* assume A or B is a t_STR */
66 : static GEN
67 385 : strconcat(GEN x, GEN y)
68 : {
69 : size_t l, lx;
70 385 : char *sx = GENtostr_unquoted(x);
71 385 : char *sy = GENtostr_unquoted(y), *str;
72 385 : lx = strlen(sx);
73 385 : l = nchar2nlong(lx + strlen(sy) + 1);
74 385 : x = cgetg(l + 1, t_STR); str = GSTR(x);
75 385 : strcpy(str, sx);
76 385 : strcpy(str+lx,sy); return x;
77 : }
78 :
79 : /* concat A and B vertically. Internal */
80 : GEN
81 20850997 : vconcat(GEN A, GEN B)
82 : {
83 : long la, ha, hb, hc, i, j, T;
84 : GEN M, a, b, c;
85 :
86 20850997 : if (!A) return B;
87 20804693 : if (!B) return A;
88 20804693 : la = lg(A); if (la==1) return B;
89 20744353 : T = typ(gel(A,1)); /* t_COL or t_VECSMALL */
90 20744353 : ha = lgcols(A); M = cgetg(la,t_MAT);
91 20744513 : hb = lgcols(B); hc = ha+hb-1;
92 261730800 : for (j=1; j<la; j++)
93 : {
94 240985356 : c = cgetg(hc, T); gel(M, j) = c;
95 240970231 : a = gel(A,j);
96 240970231 : b = gel(B,j);
97 1074681855 : for (i=1; i<ha; i++) *++c = *++a;
98 1068050289 : for (i=1; i<hb; i++) *++c = *++b;
99 : }
100 20745444 : return M;
101 : }
102 :
103 : static void
104 49 : err_cat(GEN x, GEN y) { pari_err_OP("concatenation",x,y); }
105 :
106 : GEN
107 25860222 : shallowconcat(GEN x, GEN y)
108 : {
109 25860222 : long tx=typ(x),ty=typ(y),lx=lg(x),ly=lg(y),i;
110 : GEN z,p1;
111 :
112 25860222 : if (tx==t_STR || ty==t_STR) return strconcat(x,y);
113 25859905 : if (tx==t_LIST || ty==t_LIST) return listconcat(x,y);
114 :
115 25859880 : if (tx==t_MAT && lx==1)
116 : {
117 199203 : if (ty!=t_VEC) return gtomat(y);
118 0 : if (ly==1) return cgetg(1, t_MAT);
119 0 : err_cat(x,y);
120 : }
121 25660677 : if (ty==t_MAT && ly==1)
122 : {
123 170176 : if (tx!=t_VEC) return gtomat(x);
124 0 : if (lx==1) return cgetg(1, t_MAT);
125 0 : err_cat(x,y);
126 : }
127 :
128 25490977 : if (tx == ty)
129 : {
130 16936620 : if (tx == t_MAT)
131 13036283 : { if (lgcols(x) != lgcols(y)) err_cat(x,y); }
132 : else
133 3900337 : if (!is_matvec_t(tx) && tx != t_VECSMALL) return mkvec2(x, y);
134 16936555 : z=cgetg(lx+ly-1,tx);
135 181965187 : for (i=1; i<lx; i++) z[i] = x[i];
136 86912141 : for (i=1; i<ly; i++) z[lx+i-1]= y[i];
137 16936473 : return z;
138 : }
139 :
140 8554357 : if (! is_matvec_t(tx))
141 : {
142 20851 : if (! is_matvec_t(ty)) return mkvec2(x, y);
143 20851 : z=cgetg(ly+1,ty);
144 20851 : if (ty != t_MAT) p1 = x;
145 : else
146 : {
147 0 : if (lgcols(y)!=2) err_cat(x,y);
148 0 : p1 = mkcol(x);
149 : }
150 67642 : for (i=2; i<=ly; i++) z[i] = y[i-1];
151 20851 : gel(z, 1) = p1; return z;
152 : }
153 8533508 : if (! is_matvec_t(ty))
154 : {
155 1523884 : z=cgetg(lx+1,tx);
156 1523884 : if (tx != t_MAT) p1 = y;
157 : else
158 : {
159 0 : if (lgcols(x)!=2) err_cat(x,y);
160 0 : p1 = mkcol(y);
161 : }
162 39764574 : for (i=1; i<lx; i++) z[i]=x[i];
163 1523884 : gel(z, lx) = p1; return z;
164 : }
165 :
166 7009576 : switch(tx)
167 : {
168 16751 : case t_VEC:
169 : switch(ty)
170 : {
171 16751 : case t_COL:
172 16751 : if (lx<=2) return (lx==1)? y: shallowconcat(gel(x,1),y);
173 0 : if (ly>=3) break;
174 0 : return (ly==1)? x: shallowconcat(x,gel(y,1));
175 0 : case t_MAT:
176 0 : z=cgetg(ly,t_MAT); if (lx != ly) break;
177 0 : for (i=1; i<ly; i++) gel(z,i) = shallowconcat(gel(x,i),gel(y,i));
178 0 : return z;
179 : }
180 0 : break;
181 :
182 109126 : case t_COL:
183 : switch(ty)
184 : {
185 428 : case t_VEC:
186 428 : if (lx<=2) return (lx==1)? y: shallowconcat(gel(x,1), y);
187 190 : if (ly>=3) break;
188 190 : return (ly==1)? x: shallowconcat(x, gel(y,1));
189 108698 : case t_MAT:
190 108698 : if (lx != lgcols(y)) break;
191 108698 : z=cgetg(ly+1,t_MAT); gel(z,1) = x;
192 684120 : for (i=2; i<=ly; i++) gel(z,i) = gel(y,i-1);
193 108698 : return z;
194 : }
195 0 : break;
196 :
197 6883720 : case t_MAT:
198 : switch(ty)
199 : {
200 0 : case t_VEC:
201 0 : z=cgetg(lx, t_MAT); if (ly != lx) break;
202 0 : for (i=1; i<lx; i++) gel(z,i) = shallowconcat(gel(x,i), gel(y,i));
203 0 : return z;
204 6883712 : case t_COL:
205 6883712 : if (ly != lgcols(x)) break;
206 6883714 : z=cgetg(lx+1,t_MAT); gel(z,lx) = y;
207 24818075 : for (i=1; i<lx; i++) z[i]=x[i];
208 6883883 : return z;
209 : }
210 8 : break;
211 : }
212 0 : err_cat(x,y);
213 : return NULL; /* LCOV_EXCL_LINE */
214 : }
215 :
216 : /* see catmany() */
217 : static GEN
218 20797 : catmanyMAT(GEN y1, GEN y2)
219 : {
220 20797 : long i, h = 0, L = 1;
221 : GEN z, y;
222 71494 : for (y = y2; y >= y1; y--)
223 : {
224 50697 : GEN c = gel(y,0);
225 50697 : long nc = lg(c)-1;
226 50697 : if (nc == 0) continue;
227 50669 : if (h != lgcols(c))
228 : {
229 20790 : if (h) err_cat(gel(y2,0), c);
230 20790 : h = lgcols(c);
231 : }
232 50669 : L += nc;
233 50669 : z = new_chunk(nc) - 1;
234 181602 : for (i=1; i<=nc; i++) gel(z,i) = gel(c,i);
235 : }
236 20797 : z = new_chunk(1);
237 20797 : *z = evaltyp(t_MAT) | evallg(L);
238 20797 : return z;
239 : }
240 : static GEN
241 147 : catmanySTR(GEN y1, GEN y2)
242 : {
243 147 : long L = 1; /* final \0 */
244 : GEN z, y;
245 : char *s;
246 7364 : for (y = y1; y <= y2; y++)
247 : {
248 7217 : char *c = GSTR( gel(y,0) );
249 7217 : L += strlen(c);
250 : }
251 147 : z = cgetg(nchar2nlong(L)+1, t_STR);
252 147 : s = GSTR(z);
253 7364 : for (y = y1; y <= y2; y++)
254 : {
255 7217 : char *c = GSTR( gel(y,0) );
256 7217 : long nc = strlen(c);
257 7217 : if (nc) { (void)memcpy(s, c, nc); s += nc; }
258 : }
259 147 : *s = 0; return z;
260 : }
261 :
262 : /* all entries in y have the same type t = t_VEC, COL, MAT or VECSMALL
263 : * concatenate y[k1..k2], with yi = y + ki, k1 <= k2 */
264 : static GEN
265 2277841 : catmany(GEN y1, GEN y2, long t)
266 : {
267 : long i, L;
268 : GEN z, y;
269 2277841 : if (y1 == y2) return gel(y1,0);
270 2275741 : if (t == t_MAT) return catmanyMAT(y1, y2);
271 2254944 : if (t == t_STR) return catmanySTR(y1, y2);
272 2254797 : L = 1;
273 8363313 : for (y = y2; y >= y1; y--)
274 : {
275 6108516 : GEN c = gel(y,0);
276 6108516 : long nc = lg(c)-1;
277 6108516 : if (nc == 0) continue;
278 5537410 : L += nc;
279 5537410 : z = new_chunk(nc) - 1;
280 17818742 : for (i=1; i<=nc; i++) gel(z,i) = gel(c,i);
281 : }
282 2254797 : z = new_chunk(1);
283 2254827 : *z = evaltyp(t) | evallg(L);
284 2254830 : return z;
285 : }
286 :
287 : static long
288 322 : RgMdim(long m, long n)
289 : {
290 322 : ulong mn = itou_or_0(muluu(n, m));
291 322 : if (!mn || (mn & ~LGBITS)) pari_err_OVERFLOW("lg()");
292 322 : return (long)mn;
293 : }
294 :
295 : GEN
296 322 : RgM_flatten_RgC(GEN x)
297 : {
298 322 : long i, j, k, m, n = lg(x)-1;
299 : GEN V;
300 322 : if (n == 0) return cgetg(1, t_COL);
301 322 : if (n == 1) return gel(x,1);
302 322 : m = nbrows(x); /* m x n matrix */
303 322 : if (m == 0) return cgetg(1, t_COL);
304 322 : V = cgetg(RgMdim(m,n) + 1, t_COL);
305 966 : for (i = k = 1; i <= n;i++)
306 1932 : for (j = 1; j <= m ; j++) gel(V,k++) = gcoeff(x,j,i);
307 322 : return V;
308 : }
309 :
310 : GEN
311 0 : RgM_flatten_RgV(GEN x)
312 : {
313 0 : long i, j, k, m, n = lg(x)-1;
314 : GEN V;
315 0 : if (n == 0) return cgetg(1, t_VEC);
316 0 : m = nbrows(x); /* m x n matrix */
317 0 : if (m == 0) return cgetg(1, t_VEC);
318 0 : V = cgetg(RgMdim(m,n) + 1, t_VEC);
319 0 : for (i = k = 1; i <= n; i++)
320 0 : for (j = 1; j <= m; j++) gel(V,k++) = gcoeff(x,i,j);
321 0 : return V;
322 : }
323 :
324 : GEN
325 8262196 : shallowconcat1(GEN x)
326 : {
327 8262196 : pari_sp av = avma;
328 : long lx, t, i;
329 : GEN z;
330 8262196 : switch(typ(x))
331 : {
332 8262192 : case t_VEC: case t_COL:
333 8262192 : lx = lg(x);
334 8262192 : break;
335 21 : case t_LIST:
336 21 : if (list_typ(x)!=t_LIST_RAW) pari_err_TYPE("concat",x);
337 21 : if (!list_data(x)) pari_err_DOMAIN("concat","vector","=",x,x);
338 7 : x = list_data(x); lx = lg(x);
339 7 : break;
340 0 : default:
341 0 : pari_err_TYPE("concat",x);
342 : return NULL; /* LCOV_EXCL_LINE */
343 : }
344 8262199 : if (lx==1) pari_err_DOMAIN("concat","vector","=",x,x);
345 8262241 : if (lx==2) return gel(x,1);
346 2277882 : z = gel(x,1); t = typ(z); i = 2;
347 2277882 : if (is_matvec_t(t) || t == t_VECSMALL || t == t_STR)
348 : { /* detect a "homogeneous" object: catmany is faster */
349 6168559 : for (; i<lx; i++)
350 3893021 : if (typ(gel(x,i)) != t) break;
351 2277862 : z = catmany(x + 1, x + i-1, t);
352 : }
353 2280814 : for (; i<lx; i++) {
354 2926 : z = shallowconcat(z, gel(x,i));
355 2926 : if (gc_needed(av,3))
356 : {
357 0 : if (DEBUGMEM>1) pari_warn(warnmem,"concat: i = %ld", i);
358 0 : z = gc_GEN(av, z);
359 : }
360 : }
361 2277888 : return z;
362 : }
363 :
364 : GEN
365 854 : gconcat1(GEN x)
366 : {
367 854 : pari_sp av = avma;
368 854 : return gc_GEN(av, shallowconcat1(x));
369 : }
370 :
371 : /* fill M[xoff+i, yoff+j] with the contents of c ( c * Id_n if scalar ) */
372 : static void
373 17026118 : matfill(GEN M, GEN c, long xoff, long yoff, long n)
374 : {
375 : long i, j, h, l;
376 17026118 : l = lg(c); if (l == 1) return;
377 16998559 : switch(typ(c))
378 : {
379 44324 : case t_VEC:
380 1033032 : for (i = 1; i < l; i++)
381 988708 : gcoeff(M,xoff+1,yoff+i) = gel(c,i);
382 44324 : break;
383 162094 : case t_COL:
384 1189852 : for (i = 1; i < l; i++)
385 1027758 : gcoeff(M,xoff+i,yoff+1) = gel(c,i);
386 162094 : break;
387 9656797 : case t_MAT:
388 9656797 : h = lgcols(c);
389 28584453 : for (j = 1; j < l; j++)
390 76357402 : for (i = 1; i < h; i++) gcoeff(M,xoff+i,yoff+j) = gcoeff(c,i,j);
391 9656794 : break;
392 7135344 : default:
393 16103867 : for (i = 1; i <= n; i++)
394 8968523 : gcoeff(M, xoff+i, yoff+i) = c;
395 7135344 : break;
396 : }
397 : }
398 :
399 : static GEN
400 19389228 : _matsize(GEN x)
401 : {
402 19389228 : long t = typ(x), L = lg(x) - 1;
403 19389228 : switch(t)
404 : { /* matsize */
405 88662 : case t_VEC: return mkvecsmall2(1, L);
406 324132 : case t_COL: return mkvecsmall2(L, 1);
407 11839658 : case t_MAT: return mkvecsmall2(L? nbrows(x): 0, L);
408 7136776 : default:
409 7136776 : if (is_noncalc_t(t)) pari_err_TYPE("_matsize", x);
410 7136787 : return mkvecsmall2(1, 1);
411 : }
412 : }
413 :
414 : GEN
415 3833017 : shallowmatconcat(GEN v)
416 : {
417 3833017 : long i, j, h, l = lg(v), L = 0, H = 0;
418 : GEN M, maxh, maxl;
419 3833017 : if (l == 1) return cgetg(1,t_MAT);
420 3827886 : switch(typ(v))
421 : {
422 1120943 : case t_VEC:
423 3437891 : for (i = 1; i < l; i++)
424 : {
425 2316964 : GEN c = gel(v,i);
426 2316964 : GEN s = _matsize(c);
427 2316957 : H = maxss(H, s[1]);
428 2316948 : L += s[2];
429 : }
430 1120927 : M = zeromatcopy(H, L);
431 1120952 : L = 0;
432 3437949 : for (i = 1; i < l; i++)
433 : {
434 2316998 : GEN c = gel(v,i);
435 2316998 : GEN s = _matsize(c);
436 2317000 : matfill(M, c, 0, L, 1);
437 2316997 : L += s[2];
438 : }
439 1120951 : return M;
440 :
441 3703 : case t_COL:
442 49903 : for (i = 1; i < l; i++)
443 : {
444 46200 : GEN c = gel(v,i);
445 46200 : GEN s = _matsize(c);
446 46200 : H += s[1];
447 46200 : L = maxss(L, s[2]);
448 : }
449 3703 : M = zeromatcopy(H, L);
450 3703 : H = 0;
451 49903 : for (i = 1; i < l; i++)
452 : {
453 46200 : GEN c = gel(v,i);
454 46200 : GEN s = _matsize(c);
455 46200 : matfill(M, c, H, 0, 1);
456 46200 : H += s[1];
457 : }
458 3703 : return M;
459 2703240 : case t_MAT:
460 2703240 : h = lgcols(v);
461 2703240 : maxh = zero_zv(h-1);
462 2703239 : maxl = zero_zv(l-1);
463 8879687 : for (j = 1; j < l; j++)
464 20839359 : for (i = 1; i < h; i++)
465 : {
466 14662913 : GEN c = gcoeff(v,i,j);
467 14662913 : GEN s = _matsize(c);
468 14662912 : if (s[1] > maxh[i]) maxh[i] = s[1];
469 14662912 : if (s[2] > maxl[j]) maxl[j] = s[2];
470 : }
471 8879695 : for (i = 1, H = 0; i < h; i++) H += maxh[i];
472 8879688 : for (j = 1, L = 0; j < l; j++) L += maxl[j];
473 2703240 : M = zeromatcopy(H, L);
474 8879685 : for (j = 1, L = 0; j < l; j++)
475 : {
476 20839368 : for (i = 1, H = 0; i < h; i++)
477 : {
478 14662922 : GEN c = gcoeff(v,i,j);
479 14662922 : matfill(M, c, H, L, minss(maxh[i], maxl[j]));
480 14662922 : H += maxh[i];
481 : }
482 6176446 : L += maxl[j];
483 : }
484 2703239 : return M;
485 0 : default:
486 0 : pari_err_TYPE("shallowmatconcat", v);
487 : return NULL;/*LCOV_EXCL_LINE*/
488 : }
489 : }
490 : GEN
491 76580 : matconcat(GEN v)
492 : {
493 76580 : pari_sp av = avma;
494 76580 : return gc_GEN(av, shallowmatconcat(v));
495 : }
496 :
497 : GEN
498 19436982 : gconcat(GEN x, GEN y)
499 : {
500 : long tx, lx,ty,ly,i;
501 : GEN z,p1;
502 :
503 19436982 : if (!y) return gconcat1(x);
504 19436128 : tx = typ(x);
505 19436128 : ty = typ(y);
506 19436128 : if (tx==t_STR || ty==t_STR)
507 : {
508 7 : pari_sp av = avma;
509 7 : return gc_leaf(av, strconcat(x,y));
510 : }
511 19436121 : if (tx==t_LIST || ty==t_LIST) return listconcat(x,y);
512 19436100 : lx=lg(x); ly=lg(y);
513 :
514 19436100 : if (tx==t_MAT && lx==1)
515 : {
516 588 : if (ty!=t_VEC) return gtomat(y);
517 21 : if (ly==1) return cgetg(1, t_MAT);
518 7 : err_cat(x,y);
519 : }
520 19435512 : if (ty==t_MAT && ly==1)
521 : {
522 21 : if (tx!=t_VEC) return gtomat(x);
523 14 : if (lx==1) return cgetg(1, t_MAT);
524 7 : err_cat(x,y);
525 : }
526 :
527 19435491 : if (tx == ty)
528 : {
529 653466 : if (tx == t_MAT && lgcols(x) != lgcols(y)) err_cat(x,y);
530 653466 : if (!is_matvec_t(tx))
531 : {
532 210 : if (tx != t_VECSMALL) return mkvec2copy(x, y);
533 203 : z = cgetg(lx+ly-1,t_VECSMALL);
534 301 : for (i=1; i<lx; i++) z[i] = x[i];
535 294 : for (i=1; i<ly; i++) z[lx+i-1]= y[i];
536 203 : return z;
537 : }
538 653256 : z=cgetg(lx+ly-1,tx);
539 3301642 : for (i=1; i<lx; i++) gel(z,i) = gcopy(gel(x,i));
540 2529715 : for (i=1; i<ly; i++) gel(z,lx+i-1)= gcopy(gel(y,i));
541 653256 : return z;
542 : }
543 :
544 18782025 : if (! is_matvec_t(tx))
545 : {
546 168 : if (! is_matvec_t(ty)) return mkvec2copy(x, y);
547 168 : z=cgetg(ly+1,ty);
548 168 : if (ty != t_MAT) p1 = gcopy(x);
549 : else
550 : {
551 14 : if (lgcols(y)!=2) err_cat(x,y);
552 7 : p1 = mkcolcopy(x);
553 : }
554 3514 : for (i=2; i<=ly; i++) gel(z,i) = gcopy(gel(y,i-1));
555 161 : gel(z,1) = p1; return z;
556 : }
557 18781857 : if (! is_matvec_t(ty))
558 : {
559 18781759 : z=cgetg(lx+1,tx);
560 18781759 : if (tx != t_MAT) p1 = gcopy(y);
561 : else
562 : {
563 14 : if (lgcols(x)!=2) err_cat(x,y);
564 7 : p1 = mkcolcopy(y);
565 : }
566 2547690282 : for (i=1; i<lx; i++) gel(z,i) = gcopy(gel(x,i));
567 18781752 : gel(z,lx) = p1; return z;
568 : }
569 :
570 98 : switch(tx)
571 : {
572 35 : case t_VEC:
573 : switch(ty)
574 : {
575 28 : case t_COL:
576 28 : if (lx<=2) return (lx==1)? gcopy(y): gconcat(gel(x,1),y);
577 28 : if (ly>=3) break;
578 14 : return (ly==1)? gcopy(x): gconcat(x,gel(y,1));
579 7 : case t_MAT:
580 7 : z=cgetg(ly,t_MAT); if (lx != ly) break;
581 21 : for (i=1; i<ly; i++) gel(z,i) = gconcat(gel(x,i),gel(y,i));
582 7 : return z;
583 : }
584 14 : break;
585 :
586 49 : case t_COL:
587 : switch(ty)
588 : {
589 42 : case t_VEC:
590 42 : if (lx<=2) return (lx==1)? gcopy(y): gconcat(gel(x,1),y);
591 28 : if (ly>=3) break;
592 21 : return (ly==1)? gcopy(x): gconcat(x,gel(y,1));
593 7 : case t_MAT:
594 7 : if (lx != lgcols(y)) break;
595 7 : z=cgetg(ly+1,t_MAT); gel(z,1) = gcopy(x);
596 14 : for (i=2; i<=ly; i++) gel(z,i) = gcopy(gel(y,i-1));
597 7 : return z;
598 : }
599 7 : break;
600 :
601 14 : case t_MAT:
602 : switch(ty)
603 : {
604 7 : case t_VEC:
605 7 : z=cgetg(lx,t_MAT); if (ly != lx) break;
606 21 : for (i=1; i<lx; i++) gel(z,i) = gconcat(gel(x,i),gel(y,i));
607 7 : return z;
608 7 : case t_COL:
609 7 : if (ly != lgcols(x)) break;
610 7 : z=cgetg(lx+1,t_MAT); gel(z,lx) = gcopy(y);
611 14 : for (i=1; i<lx; i++) gel(z,i) = gcopy(gel(x,i));
612 7 : return z;
613 : }
614 0 : break;
615 : }
616 21 : err_cat(x,y);
617 : return NULL; /* LCOV_EXCL_LINE */
618 : }
|