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