diff --git a/CHANGES b/CHANGES index 0e0cd10..01d25b7 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,30 @@ The following are the changes from calc version 2.14.2.0 to date: Ported calc to the s390x IBM Mainframe running RHEL9.1. + Added cal/splitbits.cal: + + splitbits(x, b) + + Given an integer x, split the value into a list of integers, + each of which is at most b bits long. + + The value b must be an integer > 0. + + The number of elements in the returned list is: + + ceil((highbit(x) + 1) / b) + + If x == 0, then a list of 1 element containing 0 is returned. + + If x < 0, then the two's compliment of abs(x) is returned. + Even though calc represents negative integers as positive values + with sign bit, the bits returned by this function are as if + the integer converted as if the integer was a two's compliment value. + + See also the help command: + + ; help resource + The following are the changes from calc version 2.14.1.5 to 2.14.1.6: diff --git a/cal/Makefile b/cal/Makefile index e093bc4..7105115 100644 --- a/cal/Makefile +++ b/cal/Makefile @@ -267,21 +267,22 @@ TRUE= true # to keep this list in nice sorted order. # CALC_FILES= README alg_config.cal beer.cal bernoulli.cal \ - bernpoly.cal bigprime.cal bindings brentsolve.cal chi.cal chrem.cal \ - comma.cal constants.cal deg.cal dms.cal dotest.cal ellip.cal \ - factorial.cal factorial2.cal gvec.cal hello.cal hms.cal infinities.cal \ - intfile.cal intnum.cal lambertw.cal linear.cal lnseries.cal lucas.cal \ - lucas_chk.cal mersenne.cal mfactor.cal mod.cal natnumset.cal \ - palindrome.cal pell.cal pi.cal pix.cal pollard.cal poly.cal prompt.cal \ - psqrt.cal qtime.cal quat.cal randbitrun.cal randmprime.cal \ - randombitrun.cal randomrun.cal randrun.cal regress.cal repeat.cal \ - screen.cal seedrandom.cal set8700.cal set8700.line smallfactors.cal \ - solve.cal specialfunctions.cal statistics.cal strings.cal sumsq.cal \ - sumtimes.cal surd.cal test1700.cal test2300.cal test2600.cal \ - test2700.cal test3100.cal test3300.cal test3400.cal test3500.cal \ - test4000.cal test4100.cal test4600.cal test5100.cal test5200.cal \ - test8400.cal test8500.cal test8600.cal test8900.cal toomcook.cal \ - unitfrac.cal varargs.cal xx_print.cal zeta2.cal + bernpoly.cal bigprime.cal bindings brentsolve.cal chi.cal \ + chrem.cal comma.cal constants.cal deg.cal dms.cal dotest.cal \ + ellip.cal factorial.cal factorial2.cal gvec.cal hello.cal hms.cal \ + infinities.cal intfile.cal intnum.cal lambertw.cal linear.cal \ + lnseries.cal lucas.cal lucas_chk.cal mersenne.cal mfactor.cal mod.cal \ + natnumset.cal palindrome.cal pell.cal pi.cal pix.cal pollard.cal \ + poly.cal prompt.cal psqrt.cal qtime.cal quat.cal randbitrun.cal \ + randmprime.cal randombitrun.cal randomrun.cal randrun.cal regress.cal \ + repeat.cal screen.cal seedrandom.cal set8700.cal set8700.line \ + smallfactors.cal solve.cal specialfunctions.cal splitbits.cal \ + statistics.cal strings.cal sumsq.cal sumtimes.cal surd.cal \ + test1700.cal test2300.cal test2600.cal test2700.cal test3100.cal \ + test3300.cal test3400.cal test3500.cal test4000.cal test4100.cal \ + test4600.cal test5100.cal test5200.cal test8400.cal test8500.cal \ + test8600.cal test8900.cal toomcook.cal unitfrac.cal varargs.cal \ + xx_print.cal zeta2.cal # These calc files are now obsolete and are removed by the install rule. # diff --git a/cal/README b/cal/README index c456890..1278614 100644 --- a/cal/README +++ b/cal/README @@ -1433,6 +1433,60 @@ specialfunctions.cal on the script zeta2.cal. +splitbits.cal + + splitbits(x, b) + + Given an integer x, split the value into a list of integers, + each of which is at most b bits long. + + The value b must be an integer > 0. + + The number of elements in the returned list is: + + ceil((highbit(x) + 1) / b) + + If x == 0, then a list of 1 element containing 0 is returned. + + If x < 0, then the two's compliment of abs(x) is returned. + Even though calc represents negative integers as positive values + with sign bit, the bits returned by this function are as if + the integer converted as if the integer was a two's compliment + value. For example: + + ; L = splitbits(-1, 8); + ; print L[[0]] + 255 + + ; L = splitbits(-2, 8); + ; print L[[0]] + 254 + + ; L = splitbits(-3, 8); + ; print L[[0]] + 253 + + The first element of the list contains the lowest order bits + of x. The last element of the list contains the highest number + bits of x. + + For example: + + ; x = 2^23209-1 + ; L = splitbits(x, 16); + ; print size(L), L[[0]] + + ; print istype(2, 3i), istype(2, "2"), istype(2, null()) + 0 0 0 + + ; mat a[2] + ; b = list(1,2,3) + ; c = assoc() + ; obj chongo {was, here} d; + ; print istype(a,b), istype(b,c), istype(c,d) + 0 0 0 + + statistics.cal gammaincoctave(z,a) diff --git a/cal/splitbits.cal b/cal/splitbits.cal new file mode 100644 index 0000000..66ac6d5 --- /dev/null +++ b/cal/splitbits.cal @@ -0,0 +1,83 @@ +/* + * 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 /\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; +}