1 /*
2  * byteswap - byte swapping routines
3  *
4  * Copyright (C) 1999,2021  Landon Curt Noll
5  *
6  * Calc is open software; you can redistribute it and/or modify it under
7  * the terms of the version 2.1 of the GNU Lesser General Public License
8  * as published by the Free Software Foundation.
9  *
10  * Calc is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU Lesser General
13  * Public License for more details.
14  *
15  * A copy of version 2.1 of the GNU Lesser General Public License is
16  * distributed with calc under the filename COPYING-LGPL.  You should have
17  * received a copy with calc; if not, write to Free Software Foundation, Inc.
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  *
20  * Under source code control:	1995/10/11 04:44:01
21  * File existed as early as:	1995
22  *
23  * chongo <was here> /\oo/\	http://www.isthe.com/chongo/
24  * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/
25  */
26 
27 
28 #include "cmath.h"
29 #include "byteswap.h"
30 
31 
32 #include "banned.h"	/* include after system header <> includes */
33 
34 
35 /*
36  * swap_b8_in_HALFs - swap 8 and if needed, 16 bits in an array of HALFs
37  *
38  * given:
39  *	dest	- pointer to where the swapped src will be put or
40  *		  NULL to allocate the storage
41  *	src	- pointer to a HALF array to swap
42  *	len	- length of the src HALF array
43  *
44  * returns:
45  *	pointer to where the swapped src has been put
46  */
47 HALF *
swap_b8_in_HALFs(HALF * dest,HALF * src,LEN len)48 swap_b8_in_HALFs(HALF *dest, HALF *src, LEN len)
49 {
50 	HALF *ret;
51 	LEN i;
52 
53 	/*
54 	 * allocate storage if needed
55 	 */
56 	if (dest == NULL) {
57 		dest = alloc(len);
58 	}
59 	ret = dest;
60 
61 	/*
62 	 * swap the array
63 	 */
64 	for (i=0; i < len; ++i, ++dest, ++src) {
65 		SWAP_B8_IN_HALF(dest, src);
66 	}
67 
68 	/*
69 	 * return the result
70 	 */
71 	return ret;
72 }
73 
74 
75 /*
76  * swap_b8_in_ZVALUE - swap 8 and if needed, 16 bits in a ZVALUE
77  *
78  * given:
79  *	dest	- pointer to where the swapped src will be put or
80  *		  NULL to allocate the storage
81  *	src	- pointer to a ZVALUE to swap
82  *	all	- TRUE => swap every element, FALSE => swap only the
83  *		  multi-precision storage
84  *
85  * returns:
86  *	pointer to where the swapped src has been put
87  *
88  * This macro will either switch to the opposite byte sex (Big Endian vs.
89  * Little Endian) the elements of a ZVALUE.
90  */
91 ZVALUE *
swap_b8_in_ZVALUE(ZVALUE * dest,ZVALUE * src,BOOL all)92 swap_b8_in_ZVALUE(ZVALUE *dest, ZVALUE *src, BOOL all)
93 {
94 	/*
95 	 * allocate storage if needed
96 	 */
97 	if (dest == NULL) {
98 
99 		/*
100 		 * allocate the storage
101 		 */
102 		dest = malloc(sizeof(ZVALUE));
103 		if (dest == NULL) {
104 			math_error("swap_b8_in_ZVALUE: swap_b8_in_ZVALUE: "
105 				    "Not enough memory");
106 			/*NOTREACHED*/
107 		}
108 
109 		/*
110 		 * allocate (by forcing swap_b8_in_ZVALUE) and swap storage
111 		 */
112 		dest->v = swap_b8_in_HALFs(NULL, src->v, src->len);
113 
114 	} else {
115 
116 		/*
117 		 * swap storage
118 		 */
119 		if (dest->v != NULL) {
120 			zfree(*dest);
121 		}
122 		dest->v = swap_b8_in_HALFs(NULL, src->v, src->len);
123 	}
124 
125 	/*
126 	 * swap or copy the rest of the ZVALUE elements
127 	 */
128 	if (all) {
129 		SWAP_B8_IN_LEN(&dest->len, &src->len);
130 		SWAP_B8_IN_BOOL(&dest->sign, &src->sign);
131 	} else {
132 		dest->len = src->len;
133 		dest->sign = src->sign;
134 	}
135 
136 	/*
137 	 * return the result
138 	 */
139 	return dest;
140 }
141 
142 
143 /*
144  * swap_b8_in_NUMBER - swap 8 and if needed, 16 bits in a NUMBER
145  *
146  * given:
147  *	dest	- pointer to where the swapped src will be put or
148  *		  NULL to allocate the storage
149  *	src	- pointer to a NUMBER to swap
150  *	all	- TRUE => swap every element, FALSE => swap only the
151  *		  multi-precision storage
152  *
153  * returns:
154  *	pointer to where the swapped src has been put
155  *
156  * This macro will either switch to the opposite byte sex (Big Endian vs.
157  * Little Endian) the elements of a NUMBER.
158  */
159 NUMBER *
swap_b8_in_NUMBER(NUMBER * dest,NUMBER * src,BOOL all)160 swap_b8_in_NUMBER(NUMBER *dest, NUMBER *src, BOOL all)
161 {
162 	/*
163 	 * allocate storage if needed
164 	 */
165 	if (dest == NULL) {
166 
167 		/*
168 		 * allocate the storage
169 		 */
170 		dest = malloc(sizeof(NUMBER));
171 		if (dest == NULL) {
172 			math_error("swap_b8_in_NUMBER: Not enough memory");
173 			/*NOTREACHED*/
174 		}
175 
176 		/*
177 		 * allocate (by forcing swap_b8_in_ZVALUE) and swap storage
178 		 */
179 		dest->num = *swap_b8_in_ZVALUE(NULL, &src->num, all);
180 		dest->den = *swap_b8_in_ZVALUE(NULL, &src->den, all);
181 
182 	} else {
183 
184 		/*
185 		 * swap storage
186 		 */
187 		dest->num = *swap_b8_in_ZVALUE(&dest->num, &src->num, all);
188 		dest->den = *swap_b8_in_ZVALUE(&dest->den, &src->den, all);
189 	}
190 
191 	/*
192 	 * swap or copy the rest of the NUMBER elements
193 	 */
194 	if (all) {
195 		SWAP_B8_IN_LONG(&dest->links, &src->links);
196 	} else {
197 		dest->links = src->links;
198 	}
199 
200 	/*
201 	 * return the result
202 	 */
203 	return dest;
204 }
205 
206 
207 /*
208  * swap_b8_in_COMPLEX - swap 8 and if needed, 16 bits in a COMPLEX
209  *
210  * given:
211  *	dest	- pointer to where the swapped src will be put or
212  *		  NULL to allocate the storage
213  *	src	- pointer to a COMPLEX to swap
214  *	all	- TRUE => swap every element, FALSE => swap only the
215  *		  multi-precision storage
216  *
217  * returns:
218  *	pointer to where the swapped src has been put
219  *
220  * This macro will either switch to the opposite byte sex (Big Endian vs.
221  * Little Endian) the elements of a COMPLEX.
222  */
223 COMPLEX *
swap_b8_in_COMPLEX(COMPLEX * dest,COMPLEX * src,BOOL all)224 swap_b8_in_COMPLEX(COMPLEX *dest, COMPLEX *src, BOOL all)
225 {
226 	/*
227 	 * allocate storage if needed
228 	 */
229 	if (dest == NULL) {
230 
231 		/*
232 		 * allocate the storage
233 		 */
234 		dest = malloc(sizeof(COMPLEX));
235 		if (dest == NULL) {
236 			math_error("swap_b8_in_COMPLEX: Not enough memory");
237 			/*NOTREACHED*/
238 		}
239 
240 		/*
241 		 * allocate (by forcing swap_b8_in_ZVALUE) and swap storage
242 		 */
243 		dest->real = swap_b8_in_NUMBER(NULL, src->real, all);
244 		dest->imag = swap_b8_in_NUMBER(NULL, src->imag, all);
245 
246 	} else {
247 
248 		/*
249 		 * swap storage
250 		 */
251 		dest->real = swap_b8_in_NUMBER(dest->real, src->real, all);
252 		dest->imag = swap_b8_in_NUMBER(dest->imag, src->imag, all);
253 	}
254 
255 	/*
256 	 * swap or copy the rest of the NUMBER elements
257 	 */
258 	if (all) {
259 		SWAP_B8_IN_LONG(&dest->links, &src->links);
260 	} else {
261 		dest->links = src->links;
262 	}
263 
264 	/*
265 	 * return the result
266 	 */
267 	return dest;
268 }
269 
270 
271 /*
272  * swap_b16_in_HALFs - swap 16 bits in an array of HALFs
273  *
274  * given:
275  *	dest	- pointer to where the swapped src will be put or
276  *		  NULL to allocate the storage
277  *	src	- pointer to a HALF array to swap
278  *	len	- length of the src HALF array
279  *
280  * returns:
281  *	pointer to where the swapped src has been put
282  */
283 HALF *
swap_b16_in_HALFs(HALF * dest,HALF * src,LEN len)284 swap_b16_in_HALFs(HALF *dest, HALF *src, LEN len)
285 {
286 	HALF *ret;
287 	LEN i;
288 
289 	/*
290 	 * allocate storage if needed
291 	 */
292 	if (dest == NULL) {
293 		dest = alloc(len);
294 	}
295 	ret = dest;
296 
297 	/*
298 	 * swap the array
299 	 */
300 	for (i=0; i < len; ++i, ++dest, ++src) {
301 		SWAP_B16_IN_HALF(dest, src);
302 	}
303 
304 	/*
305 	 * return the result
306 	 */
307 	return ret;
308 }
309 
310 
311 /*
312  * swap_b16_in_ZVALUE - swap 16 bits in a ZVALUE
313  *
314  * given:
315  *	dest	- pointer to where the swapped src will be put or
316  *		  NULL to allocate the storage
317  *	src	- pointer to a ZVALUE to swap
318  *	all	- TRUE => swap every element, FALSE => swap only the
319  *		  multi-precision storage
320  *
321  * returns:
322  *	pointer to where the swapped src has been put
323  *
324  * This macro will either switch to the opposite byte sex (Big Endian vs.
325  * Little Endian) the elements of a ZVALUE.
326  */
327 ZVALUE *
swap_b16_in_ZVALUE(ZVALUE * dest,ZVALUE * src,BOOL all)328 swap_b16_in_ZVALUE(ZVALUE *dest, ZVALUE *src, BOOL all)
329 {
330 	/*
331 	 * allocate storage if needed
332 	 */
333 	if (dest == NULL) {
334 
335 		/*
336 		 * allocate the storage
337 		 */
338 		dest = malloc(sizeof(ZVALUE));
339 		if (dest == NULL) {
340 			math_error("swap_b16_in_ZVALUE: Not enough memory");
341 			/*NOTREACHED*/
342 		}
343 
344 		/*
345 		 * allocate (by forcing swap_b16_in_ZVALUE) and swap storage
346 		 */
347 		dest->v = swap_b16_in_HALFs(NULL, src->v, src->len);
348 
349 	} else {
350 
351 		/*
352 		 * swap storage
353 		 */
354 		if (dest->v != NULL) {
355 			zfree(*dest);
356 		}
357 		dest->v = swap_b16_in_HALFs(NULL, src->v, src->len);
358 	}
359 
360 	/*
361 	 * swap or copy the rest of the ZVALUE elements
362 	 */
363 	if (all) {
364 		SWAP_B16_IN_LEN(&dest->len, &src->len);
365 		SWAP_B16_IN_BOOL(&dest->sign, &src->sign);
366 	} else {
367 		dest->len = src->len;
368 		dest->sign = src->sign;
369 	}
370 
371 	/*
372 	 * return the result
373 	 */
374 	return dest;
375 }
376 
377 
378 /*
379  * swap_b16_in_NUMBER - swap 16 bits in a NUMBER
380  *
381  * given:
382  *	dest	- pointer to where the swapped src will be put or
383  *		  NULL to allocate the storage
384  *	src	- pointer to a NUMBER to swap
385  *	all	- TRUE => swap every element, FALSE => swap only the
386  *		  multi-precision storage
387  *
388  * returns:
389  *	pointer to where the swapped src has been put
390  *
391  * This macro will either switch to the opposite byte sex (Big Endian vs.
392  * Little Endian) the elements of a NUMBER.
393  */
394 NUMBER *
swap_b16_in_NUMBER(NUMBER * dest,NUMBER * src,BOOL all)395 swap_b16_in_NUMBER(NUMBER *dest, NUMBER *src, BOOL all)
396 {
397 	/*
398 	 * allocate storage if needed
399 	 */
400 	if (dest == NULL) {
401 
402 		/*
403 		 * allocate the storage
404 		 */
405 		dest = malloc(sizeof(NUMBER));
406 		if (dest == NULL) {
407 			math_error("swap_b16_in_NUMBER: Not enough memory");
408 			/*NOTREACHED*/
409 		}
410 
411 		/*
412 		 * allocate (by forcing swap_b16_in_ZVALUE) and swap storage
413 		 */
414 		dest->num = *swap_b16_in_ZVALUE(NULL, &src->num, all);
415 		dest->den = *swap_b16_in_ZVALUE(NULL, &src->den, all);
416 
417 	} else {
418 
419 		/*
420 		 * swap storage
421 		 */
422 		dest->num = *swap_b16_in_ZVALUE(&dest->num, &src->num, all);
423 		dest->den = *swap_b16_in_ZVALUE(&dest->den, &src->den, all);
424 	}
425 
426 	/*
427 	 * swap or copy the rest of the NUMBER elements
428 	 */
429 	if (all) {
430 		SWAP_B16_IN_LONG(&dest->links, &src->links);
431 	} else {
432 		dest->links = src->links;
433 	}
434 
435 	/*
436 	 * return the result
437 	 */
438 	return dest;
439 }
440 
441 
442 /*
443  * swap_b16_in_COMPLEX - swap 16 bits in a COMPLEX
444  *
445  * given:
446  *	dest	- pointer to where the swapped src will be put or
447  *		  NULL to allocate the storage
448  *	src	- pointer to a COMPLEX to swap
449  *	all	- TRUE => swap every element, FALSE => swap only the
450  *		  multi-precision storage
451  *
452  * returns:
453  *	pointer to where the swapped src has been put
454  *
455  * This macro will either switch to the opposite byte sex (Big Endian vs.
456  * Little Endian) the elements of a COMPLEX.
457  */
458 COMPLEX *
swap_b16_in_COMPLEX(COMPLEX * dest,COMPLEX * src,BOOL all)459 swap_b16_in_COMPLEX(COMPLEX *dest, COMPLEX *src, BOOL all)
460 {
461 	/*
462 	 * allocate storage if needed
463 	 */
464 	if (dest == NULL) {
465 
466 		/*
467 		 * allocate the storage
468 		 */
469 		dest = malloc(sizeof(COMPLEX));
470 		if (dest == NULL) {
471 			math_error("swap_b16_in_COMPLEX: Not enough memory");
472 			/*NOTREACHED*/
473 		}
474 
475 		/*
476 		 * allocate (by forcing swap_b16_in_ZVALUE) and swap storage
477 		 */
478 		dest->real = swap_b16_in_NUMBER(NULL, src->real, all);
479 		dest->imag = swap_b16_in_NUMBER(NULL, src->imag, all);
480 
481 	} else {
482 
483 		/*
484 		 * swap storage
485 		 */
486 		dest->real = swap_b16_in_NUMBER(dest->real, src->real, all);
487 		dest->imag = swap_b16_in_NUMBER(dest->imag, src->imag, all);
488 	}
489 
490 	/*
491 	 * swap or copy the rest of the NUMBER elements
492 	 */
493 	if (all) {
494 		SWAP_B16_IN_LONG(&dest->links, &src->links);
495 	} else {
496 		dest->links = src->links;
497 	}
498 
499 	/*
500 	 * return the result
501 	 */
502 	return dest;
503 }
504 
505 
506 /*
507  * swap_HALF_in_ZVALUE - swap HALFs in a ZVALUE
508  *
509  * given:
510  *	dest	- pointer to where the swapped src will be put or
511  *		  NULL to allocate the storage
512  *	src	- pointer to a ZVALUE to swap
513  *	all	- TRUE => swap every element, FALSE => swap only the
514  *		  multi-precision storage
515  *
516  * returns:
517  *	pointer to where the swapped src has been put
518  *
519  * This macro will either switch to the opposite byte sex (Big Endian vs.
520  * Little Endian) the elements of a ZVALUE.
521  */
522 ZVALUE *
swap_HALF_in_ZVALUE(ZVALUE * dest,ZVALUE * src,BOOL all)523 swap_HALF_in_ZVALUE(ZVALUE *dest, ZVALUE *src, BOOL all)
524 {
525 	/*
526 	 * allocate storage if needed
527 	 */
528 	if (dest == NULL) {
529 
530 		/*
531 		 * allocate the storage
532 		 */
533 		dest = malloc(sizeof(ZVALUE));
534 		if (dest == NULL) {
535 			math_error("swap_HALF_in_ZVALUE: Not enough memory");
536 			/*NOTREACHED*/
537 		}
538 
539 		/*
540 		 * copy storage because we are dealing with HALFs
541 		 */
542 		dest->v = (HALF *) zcopyval(*src, *dest);
543 
544 	} else {
545 
546 		/*
547 		 * copy storage because we are dealing with HALFs
548 		 */
549 		if (dest->v != NULL) {
550 			zfree(*dest);
551 			dest->v = alloc(src->len);
552 		}
553 		zcopyval(*src, *dest);
554 	}
555 
556 	/*
557 	 * swap or copy the rest of the ZVALUE elements
558 	 */
559 	if (all) {
560 		SWAP_HALF_IN_LEN(&dest->len, &src->len);
561 		SWAP_HALF_IN_BOOL(&dest->sign, &src->sign);
562 	} else {
563 		dest->len = src->len;
564 		dest->sign = src->sign;
565 	}
566 
567 	/*
568 	 * return the result
569 	 */
570 	return dest;
571 }
572 
573 
574 /*
575  * swap_HALF_in_NUMBER - swap HALFs in a NUMBER
576  *
577  * given:
578  *	dest	- pointer to where the swapped src will be put or
579  *		  NULL to allocate the storage
580  *	src	- pointer to a NUMBER to swap
581  *	all	- TRUE => swap every element, FALSE => swap only the
582  *		  multi-precision storage
583  *
584  * returns:
585  *	pointer to where the swapped src has been put
586  *
587  * This macro will either switch to the opposite byte sex (Big Endian vs.
588  * Little Endian) the elements of a NUMBER.
589  */
590 NUMBER *
swap_HALF_in_NUMBER(NUMBER * dest,NUMBER * src,BOOL all)591 swap_HALF_in_NUMBER(NUMBER *dest, NUMBER *src, BOOL all)
592 {
593 	/*
594 	 * allocate storage if needed
595 	 */
596 	if (dest == NULL) {
597 
598 		/*
599 		 * allocate the storage
600 		 */
601 		dest = malloc(sizeof(NUMBER));
602 		if (dest == NULL) {
603 			math_error("swap_HALF_in_NUMBER: Not enough memory");
604 			/*NOTREACHED*/
605 		}
606 
607 		/*
608 		 * allocate (by forcing swap_HALF_in_ZVALUE) and swap storage
609 		 */
610 		dest->num = *swap_HALF_in_ZVALUE(NULL, &src->num, all);
611 		dest->den = *swap_HALF_in_ZVALUE(NULL, &src->den, all);
612 
613 	} else {
614 
615 		/*
616 		 * swap storage
617 		 */
618 		dest->num = *swap_HALF_in_ZVALUE(&dest->num, &src->num, all);
619 		dest->den = *swap_HALF_in_ZVALUE(&dest->den, &src->den, all);
620 	}
621 
622 	/*
623 	 * swap or copy the rest of the NUMBER elements
624 	 */
625 	if (all) {
626 		SWAP_HALF_IN_LONG(&dest->links, &src->links);
627 	} else {
628 		dest->links = src->links;
629 	}
630 
631 	/*
632 	 * return the result
633 	 */
634 	return dest;
635 }
636 
637 
638 /*
639  * swap_HALF_in_COMPLEX - swap HALFs in a COMPLEX
640  *
641  * given:
642  *	dest	- pointer to where the swapped src will be put or
643  *		  NULL to allocate the storage
644  *	src	- pointer to a COMPLEX to swap
645  *	all	- TRUE => swap every element, FALSE => swap only the
646  *		  multi-precision storage
647  *
648  * returns:
649  *	pointer to where the swapped src has been put
650  *
651  * This macro will either switch to the opposite byte sex (Big Endian vs.
652  * Little Endian) the elements of a COMPLEX.
653  */
654 COMPLEX *
swap_HALF_in_COMPLEX(COMPLEX * dest,COMPLEX * src,BOOL all)655 swap_HALF_in_COMPLEX(COMPLEX *dest, COMPLEX *src, BOOL all)
656 {
657 	/*
658 	 * allocate storage if needed
659 	 */
660 	if (dest == NULL) {
661 
662 		/*
663 		 * allocate the storage
664 		 */
665 		dest = malloc(sizeof(COMPLEX));
666 		if (dest == NULL) {
667 			math_error("swap_HALF_in_COMPLEX: Not enough memory");
668 			/*NOTREACHED*/
669 		}
670 
671 		/*
672 		 * allocate (by forcing swap_HALF_in_ZVALUE) and swap storage
673 		 */
674 		dest->real = swap_HALF_in_NUMBER(NULL, src->real, all);
675 		dest->imag = swap_HALF_in_NUMBER(NULL, src->imag, all);
676 
677 	} else {
678 
679 		/*
680 		 * swap storage
681 		 */
682 		dest->real = swap_HALF_in_NUMBER(dest->real, src->real, all);
683 		dest->imag = swap_HALF_in_NUMBER(dest->imag, src->imag, all);
684 	}
685 
686 	/*
687 	 * swap or copy the rest of the NUMBER elements
688 	 */
689 	if (all) {
690 		SWAP_HALF_IN_LONG(&dest->links, &src->links);
691 	} else {
692 		dest->links = src->links;
693 	}
694 
695 	/*
696 	 * return the result
697 	 */
698 	return dest;
699 }
700