/*
 * splitbits - split an integer into list on bit boundardies of a fixed size
 *
 * Copyright (C) 2018,2023  Landon Curt Noll
 *
 * Calc is open software; you can redistribute it and/or modify it under
 * the terms of the version 2.1 of the GNU Lesser General Public License
 * as published by the Free Software Foundation.
 *
 * Calc is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU Lesser General
 * Public License for more details.
 *
 * A copy of version 2.1 of the GNU Lesser General Public License is
 * distributed with calc under the filename COPYING-LGPL.  You should have
 * received a copy with calc; if not, write to Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Under source code control:	2006/06/07 14:10:11
 * File existed as early as:	2006
 *
 * chongo <was here> /\oo/\	http://www.isthe.com/chongo/
 * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/
 */


/*
 * setup splitbits errors
 */
static E_SPLITBITS_1, E_SPLITBITS_2, E_SPLITBITS_3;
if (! iserror(E_SPLITBITS_1)) E_SPLITBITS_1 = newerror("1st argument to splitbits must be an integer");
if (! iserror(E_SPLITBITS_2)) E_SPLITBITS_2 = newerror("2nd argument to splitbits must be an integer");
if (! iserror(E_SPLITBITS_3)) E_SPLITBITS_3 = newerror("2nd argument must be an integer > 0");


/*
 * define splitbits function
 */
define splitbits(x, b)
{
    local ret;		/* list to return */
    local mask;		/* 2^b-1 */
    local x_is_reg = 0;	/* true if x < 0 */

    /* firewall */
    if (! isint(x)) {
	return error(E_SPLITBITS_1);
    }
    if (! isint(b)) {
	return error(E_SPLITBITS_2);
    }
    if (b <= 0) {
	return error(E_SPLITBITS_3);
    }

    /* special case: x == 0 */
    if (x == 0) {
	return list(0);
    }

    /* setup for splitting x */
    ret = list();
    mask = 2^b-1;
    if (x < 0) {
	x_is_reg = 1;
	x = abs(x);
    }

    /* split x */
    while (x > 0) {
	printf("%d %x\n", size(ret), x);
	if (x_is_reg) {
	    append(ret, xor(x & mask, mask));
	} else {
	    append(ret, x & mask);
	}
	x >>= b;
    }

    /* return list */
    return ret;
}
