1 /* Steven Andrews, 10/6/2015
2 See documentation called list_doc.doc
3 Copyright 2015 by Steven Andrews. This work is distributed under the terms
4 of the Gnu Lesser General Public License (LGPL). */
5
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include "List.h"
9 #include "string2.h"
10
11
12 /****************************************************************************/
13 /***************************** Internal functions ***************************/
14 /****************************************************************************/
15
16
17 /* ListExpandLI */
ListExpandLI(listptrli list,int spaces)18 int ListExpandLI(listptrli list,int spaces) {
19 long int *newxs;
20 int newmax,i,newn;
21
22 newmax=list->max+spaces;
23 if(newmax==0) {
24 newxs=NULL;
25 newmax=0;
26 newn=0; }
27 else {
28 newxs=(long int*) calloc(newmax,sizeof (long int));
29 if(!newxs) return 1;
30 for(i=0;i<list->n && i<newmax;i++) newxs[i]=list->xs[i];
31 newn=i;
32 for(i=newn;i<newmax;i++) newxs[i]=0; }
33
34 free(list->xs);
35 list->xs=newxs;
36 list->max=newmax;
37 list->n=newn;
38 return 0; }
39
40
41 /* ListExpandV */
ListExpandV(listptrv list,int spaces)42 int ListExpandV(listptrv list,int spaces) {
43 void **newxs;
44 int newmax,i,newn;
45
46 newmax=list->max+spaces;
47 if(newmax==0) {
48 newxs=NULL;
49 newmax=0;
50 newn=0; }
51 else {
52 newxs=(void**) calloc(newmax,sizeof (void*));
53 if(!newxs) return 1;
54 for(i=0;i<list->n && i<newmax;i++) newxs[i]=list->xs[i];
55 newn=i;
56 for(i=newn;i<newmax;i++) newxs[i]=NULL; }
57
58 free(list->xs);
59 list->xs=newxs;
60 list->max=newmax;
61 list->n=newn;
62 return 0; }
63
64
65 /* ListExpandDD */
ListExpandDD(listptrdd list,int addrows,int addcols)66 int ListExpandDD(listptrdd list,int addrows,int addcols) {
67 double *newdata;
68 int newmaxrow,newmaxcol,newnrow,newncol,i,j;
69
70 newmaxrow=list->maxrow+addrows;
71 newmaxcol=list->maxcol+addcols;
72 if(newmaxrow==0 || newmaxcol==0) {
73 newdata=NULL;
74 newmaxrow=0;
75 newmaxcol=0;
76 newnrow=0;
77 newncol=0; }
78 else {
79 newdata=(double*) calloc(newmaxrow*newmaxcol,sizeof (double));
80 if(!newdata) return 1;
81 for(i=0;i<newmaxrow;i++)
82 for(j=0;j<newmaxcol;j++) {
83 if(i<list->nrow && j<list->ncol)
84 newdata[i*newmaxcol+j]=list->data[i*list->maxcol+j];
85 else
86 newdata[i*newmaxcol+j]=0; }
87 newnrow=(list->nrow<=newmaxrow) ? list->nrow:newmaxrow;
88 newncol=(list->ncol<=newmaxcol) ? list->ncol:newmaxcol; }
89
90 free(list->data);
91 list->data=newdata;
92 list->maxrow=newmaxrow;
93 list->maxcol=newmaxcol;
94 list->nrow=newnrow;
95 list->ncol=newncol;
96 if(list->nextcol>=list->maxcol)
97 list->nextcol=list->maxcol-1;
98 return 0; }
99
100
101 /* ListExpandULVD4 */
ListExpandULVD4(listptrULVD4 list,int addrows)102 int ListExpandULVD4(listptrULVD4 list,int addrows) {
103 unsigned long long *newdataul;
104 void **newdatav;
105 double **newdatad4;
106 int newmax,newn,i;
107
108 newmax=list->max+addrows;
109 if(newmax==0) {
110 newdataul=NULL;
111 newdatav=NULL;
112 newdatad4=NULL;
113 newn=0; }
114 else {
115 newdataul=(unsigned long long*) calloc(newmax,sizeof(unsigned long long));
116 newdatav=(void**) calloc(newmax,sizeof(void*));
117 newdatad4=(double**) calloc(newmax,sizeof(double*));
118 if(!newdataul || !newdatav || !newdatad4) return 1;
119 for(i=0;i<list->n && i<newmax;i++) {
120 newdataul[i]=list->dataul[i];
121 newdatav[i]=list->datav[i];
122 newdatad4[i]=list->datad4[i]; }
123 for(;i<newmax;i++) {
124 newdataul[i]=0;
125 newdatav[i]=NULL;
126 newdatad4[i]=NULL; }
127 for(i=list->n;i<newmax;i++) {
128 newdatad4[i]=(double*) calloc(4,sizeof(double));
129 if(!newdatad4[i]) return 1;
130 newdatad4[i][0]=newdatad4[i][1]=newdatad4[i][2]=newdatad4[i][3]=0; }
131 newn=(list->n<=newmax) ? list->n:newmax; }
132
133 free(list->dataul);
134 free(list->datav);
135 if(newmax<list->max) {
136 for(i=newmax;i<list->max;i++)
137 free(list->datad4[i]); }
138 free(list->datad4);
139
140 list->dataul=newdataul;
141 list->datav=newdatav;
142 list->datad4=newdatad4;
143 list->max=newmax;
144 list->n=newn;
145
146 return 0; }
147
148
149 /****************************************************************************/
150 /***************************** Memory management ****************************/
151 /****************************************************************************/
152
153
154 /* ListAllocLI */
ListAllocLI(int max)155 listptrli ListAllocLI(int max) {
156 listptrli list;
157 int er;
158
159 list=(listptrli) malloc(sizeof(struct liststructli));
160 if(!list) return NULL;
161 list->max=0;
162 list->n=0;
163 list->xs=NULL;
164 er=ListExpandLI(list,max);
165 if(er) {
166 ListFreeLI(list);
167 return NULL; }
168 return list; }
169
170
171 /* ListAllocV */
ListAllocV(int max)172 listptrv ListAllocV(int max) {
173 listptrv list;
174 int er;
175
176 list=(listptrv) malloc(sizeof(struct liststructv));
177 if(!list) return NULL;
178 list->max=0;
179 list->n=0;
180 list->xs=NULL;
181 er=ListExpandV(list,max);
182 if(er) {
183 ListFreeV(list);
184 return NULL; }
185 return list; }
186
187
188 /* ListAllocDD */
ListAllocDD(int maxrow,int maxcol)189 listptrdd ListAllocDD(int maxrow,int maxcol) {
190 listptrdd list;
191 int er;
192
193 list=(listptrdd) malloc(sizeof(struct liststructdd));
194 if(!list) return NULL;
195 list->maxrow=0;
196 list->maxcol=0;
197 list->nrow=0;
198 list->ncol=0;
199 list->nextcol=0;
200 list->data=NULL;
201 er=ListExpandDD(list,maxrow,maxcol);
202 if(er) {
203 ListFreeDD(list);
204 return NULL; }
205 return list; }
206
207
208 /* ListAllocULVD4 */
ListAllocULVD4(int max)209 listptrULVD4 ListAllocULVD4(int max) {
210 listptrULVD4 list;
211 int er;
212
213 list=(listptrULVD4) malloc(sizeof(struct liststructULVD4));
214 if(!list) return NULL;
215 list->max=0;
216 list->n=0;
217 list->dataul=NULL;
218 list->datav=NULL;
219 list->datad4=NULL;
220 er=ListExpandULVD4(list,max);
221 if(er) {
222 ListFreeULVD4(list);
223 return NULL; }
224 return list; }
225
226
227 /* ListFreeLI */
ListFreeLI(listptrli list)228 void ListFreeLI(listptrli list) {
229 if(list) {
230 free(list->xs);
231 free(list); }
232 return; }
233
234
235 /* ListFreeV */
ListFreeV(listptrv list)236 void ListFreeV(listptrv list) {
237 if(list) {
238 free(list->xs);
239 free(list); }
240 return; }
241
242
243 /* ListFreeDD */
ListFreeDD(listptrdd list)244 void ListFreeDD(listptrdd list) {
245 if(list) {
246 free(list->data);
247 free(list); }
248 return; }
249
250
251 /* ListFreeULVD4 */
ListFreeULVD4(listptrULVD4 list)252 void ListFreeULVD4(listptrULVD4 list) {
253 int i;
254
255 if(!list) return;
256 for(i=0;i<list->max;i++)
257 free(list->datad4[i]);
258 free(list->dataul);
259 free(list->datav);
260 free(list->datad4);
261 free(list);
262
263 return; }
264
265
266 /****************************************************************************/
267 /******************************* Reading lists ******************************/
268 /****************************************************************************/
269
270
271 /* ListMemberLI */
ListMemberLI(const listptrli list,long int x)272 int ListMemberLI(const listptrli list,long int x) {
273 int i;
274
275 for(i=0;i<list->n;i++)
276 if(list->xs[i]==x) return 1;
277 return 0; }
278
279
280 /****************************************************************************/
281 /************************** Adding elements to lists ************************/
282 /****************************************************************************/
283
284
285 /* ListReadStringLI */
ListReadStringLI(char * string)286 listptrli ListReadStringLI(char *string) {
287 listptrli list;
288 int n,nread;
289
290 n=wordcount(string);
291 list=ListAllocLI(n);
292 if(!list) return NULL;
293 nread=strreadnli(string,n,list->xs,NULL);
294 if(nread!=n) {
295 ListFreeLI(list);
296 return NULL; }
297 list->n=n;
298
299 return list; }
300
301
302 /* ListAppendItemLI */
ListAppendItemLI(listptrli list,long int newitem)303 listptrli ListAppendItemLI(listptrli list,long int newitem) {
304 int er;
305
306 if(!list) {
307 list=ListAllocLI(2);
308 if(!list) return NULL; }
309 else if(list->n==list->max) {
310 er=ListExpandLI(list,list->n+1);
311 if(er) return NULL; }
312
313 list->xs[list->n]=newitem;
314 list->n++;
315
316 return list; }
317
318
319 /* ListAppendItemV */
ListAppendItemV(listptrv list,void * newitem)320 listptrv ListAppendItemV(listptrv list,void *newitem) {
321 int er;
322
323 if(!newitem) return list;
324
325 if(!list) {
326 list=ListAllocV(2);
327 if(!list) return NULL; }
328 else if(list->n==list->max) {
329 er=ListExpandV(list,list->n+1);
330 if(er) return NULL; }
331
332 list->xs[list->n]=newitem;
333 list->n++;
334
335 return list; }
336
337
338 /* ListAppendItemsDDv */
ListAppendItemsDDv(listptrdd list,int newrow,int narg,va_list items)339 listptrdd ListAppendItemsDDv(listptrdd list, int newrow, int narg, va_list items) {
340 int er,i,j,k;
341
342 if(!narg) return list;
343
344 er=0;
345 if(!list) {
346 list=ListAllocDD(1,narg);
347 if(!list) return NULL; }
348 else if(newrow && list->nrow==list->maxrow) // add rows, and columns if needed
349 er=ListExpandDD(list,list->nrow+1,(narg>list->maxcol) ? narg-list->maxcol:0);
350 else if(newrow && narg>list->maxcol) // add columns
351 er=ListExpandDD(list,0,narg-list->maxcol);
352 else if(!newrow && narg+list->nextcol>list->maxcol) // add columns
353 er=ListExpandDD(list,0,narg+list->nextcol-list->maxcol);
354 if(er) return NULL;
355
356 if(newrow || list->nrow==0) {
357 i=list->nrow;
358 j=0;
359 list->nrow++;
360 if(narg>list->ncol) list->ncol=narg;
361 list->nextcol=narg; }
362 else {
363 i=list->nrow-1;
364 j=list->nextcol;
365 if(j+narg>list->ncol) list->ncol=j+narg;
366 list->nextcol+=narg; }
367
368 for(k=0;k<narg;k++)
369 list->data[i*list->maxcol+j+k]=va_arg(items,double);
370
371 return list; }
372
373
374 /* ListAppendItemsDD */
ListAppendItemsDD(listptrdd list,int newrow,int narg,...)375 listptrdd ListAppendItemsDD(listptrdd list, int newrow, int narg, ...) {
376 va_list items;
377
378 va_start(items,narg);
379 list=ListAppendItemsDDv(list,newrow,narg,items);
380 va_end(items);
381 return list; }
382
383
384 /* ListInsertItemULVD4 */
ListInsertItemULVD4(listptrULVD4 list,unsigned long long xdataul,void * xdatav,const double * xdatad4,int mode)385 int ListInsertItemULVD4(listptrULVD4 list,unsigned long long xdataul,void *xdatav,const double *xdatad4,int mode) {
386 int jl,jm,ju,er,inlist;
387 double *temp;
388
389 jl=-1;
390 ju=list->n;
391 while(ju-jl > 1) {
392 jm=(ju+jl)>>1;
393 if(xdataul >= list->dataul[jm]) jl=jm;
394 else ju=jm; } // at the end, jl is the item, or one below where it goes
395
396 inlist=(jl>=0 && list->dataul[jl]==xdataul);
397 if(mode==0) return inlist ? jl:-1;
398 if(mode==1 && inlist) return jl;
399
400 if(list->n==list->max) {
401 er=ListExpandULVD4(list,list->max+1);
402 if(er) return -2; }
403
404 temp=list->datad4[list->n];
405 for(jm=list->n;jm>jl+1;jm--) {
406 list->dataul[jm]=list->dataul[jm-1];
407 list->datav[jm]=list->datav[jm-1];
408 list->datad4[jm]=list->datad4[jm-1]; }
409 list->dataul[jm]=xdataul;
410 list->datav[jm]=xdatav;
411 temp[0]=xdatad4[0];
412 temp[1]=xdatad4[1];
413 temp[2]=xdatad4[2];
414 temp[3]=xdatad4[3];
415 list->datad4[jm]=temp;
416 list->n++;
417
418 return jm; }
419
420
421
422 /****************************************************************************/
423 /***************************** Removing elements ********************/
424 /****************************************************************************/
425
426
427 /* List_CleanULVD4 */
List_CleanULVD4(listptrULVD4 list)428 void List_CleanULVD4(listptrULVD4 list) {
429 int ifrom,ito;
430 double *temp;
431
432 ifrom=0;
433 ito=0;
434 for(ifrom=0;ifrom<list->n;ifrom++) {
435 if(list->datav[ifrom]) {
436 if(ifrom>ito) {
437 list->dataul[ito]=list->dataul[ifrom];
438 list->datav[ito]=list->datav[ifrom];
439 temp=list->datad4[ito];
440 list->datad4[ito]=list->datad4[ifrom];
441 list->dataul[ifrom]=0;
442 list->datav[ifrom]=NULL;
443 temp[0]=temp[1]=temp[2]=temp[3]=0;
444 list->datad4[ifrom]=temp; }
445 ito++; }}
446 list->n=ito;
447
448 return; }
449
450
451 /****************************************************************************/
452 /******************************* Combining lists ****************************/
453 /****************************************************************************/
454
455
456 /* ListAppendListLI */
ListAppendListLI(listptrli list,const listptrli newstuff)457 listptrli ListAppendListLI(listptrli list,const listptrli newstuff) {
458 int spaces,i,newn,er;
459
460 if(!newstuff || newstuff->n==0) return list;
461
462 newn=newstuff->n;
463 if(!list) {
464 list=ListAllocLI(newn);
465 if(!list) return NULL; }
466 else {
467 spaces=newn-(list->max-list->n); // number of spaces to allocate
468 if(spaces>0) {
469 er=ListExpandLI(list,spaces);
470 if(er) return NULL; }}
471
472 for(i=0;i<newn;i++)
473 list->xs[list->n+i]=newstuff->xs[i];
474 list->n+=newn;
475
476 return list; }
477
478
479 /* ListRemoveListLI */
ListRemoveListLI(listptrli list,const listptrli remove)480 int ListRemoveListLI(listptrli list,const listptrli remove) {
481 int i,i2,j,count;
482
483 if(!remove || remove->n==0) return 0;
484
485 count=0;
486 for(j=0;j<remove->n;j++)
487 for(i=list->n-1;i>=0;i--)
488 if(list->xs[i]==remove->xs[j]) {
489 for(i2=i;i2<list->n-1;i2++)
490 list->xs[i2]=list->xs[i2+1];
491 list->n--;
492 count++;
493 break; }
494 return count; }
495
496
497 /* ListClearDD */
ListClearDD(listptrdd list)498 void ListClearDD(listptrdd list) {
499 list->nrow=0;
500 list->ncol=0;
501 list->nextcol=0;
502 return; }
503
504
505 /**************************************************/
506 /****** List output ***************************/
507 /************************************************/
508
509 /* ListPrintDD */
ListPrintDD(listptrdd list)510 void ListPrintDD(listptrdd list) {
511 int i,j;
512
513 printf("\n---- List -----\n");
514 if(!list) {
515 printf("No list\n");
516 return; }
517 printf("List type: dd\n");
518 printf("Allocated for %i rows and %i columns\n",list->maxrow,list->maxcol);
519 printf("Currently %i rows and %i columns\n",list->nrow,list->ncol);
520 printf("Next column for adding to: %i\n",list->nextcol);
521 printf("Data:\n");
522 if(list->data)
523 for(i=0;i<list->nrow;i++) {
524 for(j=0;j<list->ncol;j++)
525 printf(" %.3g",list->data[i*list->maxcol+j]);
526 printf("\n"); }
527 else
528 printf("Data element is NULL\n");
529 printf("--------------\n");
530 return; }
531