From 48e5d8bb385ba5b431a5dfd4039771c24da72551 Mon Sep 17 00:00:00 2001 From: m0_56903617 Date: Thu, 20 May 2021 21:44:42 +0800 Subject: [PATCH] 202105202144 --- bignumber/include/bignumber.h | 4 +- bignumber/src/bignumber.c | 99 +++++++++++++++++++++++--- examples/testbignumber/testbignumber.c | 10 ++- 3 files changed, 101 insertions(+), 12 deletions(-) diff --git a/bignumber/include/bignumber.h b/bignumber/include/bignumber.h index 90c40be..e30cd6f 100644 --- a/bignumber/include/bignumber.h +++ b/bignumber/include/bignumber.h @@ -50,7 +50,7 @@ DEFINE_GUID(IID_BIGNUMBER, 0x80dc5305, 0x1ca6, 0x4678, 0xbf, 0xc3, 0xd0, 0x1b, 0 typedef struct sIBigNumber { OBJECT_INTERFACE int (*GetBitsCount)(HOBJECT object); - + int (*SetBitsCount)(HOBJECT object, int count); int (*GetInt)(HOBJECT object, int* pvalue); int (*GetInt64)(HOBJECT object, long long* pvalue); int (*GetFloat)(HOBJECT object, float* pvalue); @@ -93,6 +93,7 @@ typedef struct sIBigNumber { #define BIGNUMBER_FUNCDECLARE(_obj, _clsid, _localstruct) \ static int _obj##_bn_GetBitsCount(HOBJECT object); \ + static int _obj##_bn_SetBitsCount(HOBJECT object, int count); \ static int _obj##_bn_GetInt(HOBJECT object, int* pvalue); \ static int _obj##_bn_GetInt64(HOBJECT object, long long* pvalue); \ static int _obj##_bn_GetFloat(HOBJECT object, float* pvalue); \ @@ -125,6 +126,7 @@ typedef struct sIBigNumber { static const IBigNumber _obj##_bn_interface = { \ INTERFACE_HEADER(_obj, IBigNumber, _localstruct) \ _obj##_bn_GetBitsCount, \ + _obj##_bn_SetBitsCount, \ _obj##_bn_GetInt, \ _obj##_bn_GetInt64, \ _obj##_bn_GetFloat, \ diff --git a/bignumber/src/bignumber.c b/bignumber/src/bignumber.c index 0397a5e..e65d35a 100644 --- a/bignumber/src/bignumber.c +++ b/bignumber/src/bignumber.c @@ -91,13 +91,13 @@ static int actualwidth(unsigned int n) { unsigned int c = 1; int ret = 1; - if (c & 0x80000000) + if (n & 0x80000000) return 32; - while (c < n) { + while (c <= n) { c <<= 1; ret++; } - return ret; + return ret-1; } static void bigintDestroy(HOBJECT object) @@ -134,6 +134,25 @@ static int bigint_bn_GetBitsCount(HOBJECT object) return 0; } +static int bigint_bn_SetBitsCount(HOBJECT object, int count) +{ + int i, bc; + sBigInteger* pobj; + pobj = (sBigInteger*)objectThis(object); + if (count <= 0) { + memset(pobj->buf, 0, pobj->buflen * 4); + return 0; + } + bc = bigint_bn_GetBitsCount(pobj); + if (count >= bc) + return 0; + for (i = (count+31) / 32; i < pobj->buflen; i++) { + pobj->buf[i] = 0; + } + pobj->buf[count / 32] &= 0xffffffff >> (32 - (count & 31)); + return 0; +} + static int bigint_bn_GetInt(HOBJECT object, int* pvalue) { sBigInteger* pobj; @@ -180,6 +199,10 @@ static int bigint_bn_GetStr(HOBJECT object, int base, char* str, int buflen) pobj = (sBigInteger*)objectThis(object); str[0] = 0; bc = bigint_bn_GetBitsCount(object); + if (bc == 0) { + strcpy(str, "0"); + return 0; + } sprintf(str, "%d'h", bc); i = ((bc + 31) / 32) - 1; ac = actualwidth(pobj->buf[i]); @@ -554,21 +577,79 @@ static int bigint_bn_Div(HOBJECT object, HOBJECT src) static int bigint_bn_SHL(HOBJECT object, int bits) { sBigInteger* pobj; - int bc; + int bc, blen; + int ifrom, ito, i; + unsigned long long current, next; + unsigned int* buf; pobj = (sBigInteger*)objectThis(object); + if (bits == 0) + return 0; + if (bits < 0) + return bigint_bn_SHR(object, -bits); bc = bigint_bn_GetBitsCount(object); - while (bc + bits > pobj->buflen * 32) { - if (bigint_expandbuf(pobj) != 0) - return -1; + blen = (bc + bits + 31) / 32; + buf = (unsigned int*)malloc(blen * 4); + if (buf == NULL) + return -1; + ito = bits / 32; + if (ito > 0) { + memset(buf, 0, ito * 4); } - /* fixed me */ + bits -= ito * 32; + ifrom = 0; + current = pobj->buf[0]; + current <<= bits; + for (i = 1; i < (bc + 31) / 32; i++) { + buf[ito++] = (unsigned int)(current & 0xffffffff); + current >>= 32; + next = pobj->buf[i]; + next <<= bits; + current |= next; + } + buf[ito] = (unsigned int)(current & 0xffffffff); + free(pobj->buf); + pobj->buf = buf; + pobj->buflen = blen; return 0; } static int bigint_bn_SHR(HOBJECT object, int bits) -{ +{ sBigInteger* pobj; + int bc; + int ifrom, ito, i, zerolen; + unsigned long long current, next; pobj = (sBigInteger*)objectThis(object); + if (bits == 0) + return 0; + if (bits < 0) + return bigint_bn_SHL(object, -bits); + ito = 0; + ifrom = bits / 32; + if (ifrom >= pobj->buflen) { + memset(pobj->buf, 0, pobj->buflen * 4); + return 0; + } + bits -= ifrom * 32; + if (ifrom+1 < pobj->buflen) { + current = pobj->buf[ifrom+1]; + current <<= 32; + } + else { + current = 0; + } + current |= pobj->buf[ifrom]; + current >>= bits; + for (i = ifrom + 1; i < pobj->buflen-1; i++) { + pobj->buf[ito++] = (unsigned int)(current & 0xffffffff); + current >>= 32; + next = pobj->buf[i + 1]; + next <<= 32-bits; + current |= next; + } + pobj->buf[ito++] = (unsigned int)(current & 0xffffffff); + while (ito < pobj->buflen) + pobj->buf[ito++] = 0; return 0; } diff --git a/examples/testbignumber/testbignumber.c b/examples/testbignumber/testbignumber.c index dbcefc8..b0adc4c 100644 --- a/examples/testbignumber/testbignumber.c +++ b/examples/testbignumber/testbignumber.c @@ -34,11 +34,11 @@ #include "object.h" #include "bignumber.h" -const char* testnumber = "43, 4, 128'b0101011111011010100011000101010101010100010101010101010001, 'h94397afc4343, 5'd98"; +const char* testnumber = "77'h4137489137419837408139048137908791875841983274987132, 43, 4, 128'b0101011111011010100011000101010101010100010101010101010001, 'h94397afc4343, 5'd98"; int main(int argc, char* argv[]) { - char buf[128]; + char buf[256]; IBigNumber** bignumber = bigintegerCreate(); const char* nstr = testnumber; const char* lstr = testnumber; @@ -47,5 +47,11 @@ int main(int argc, char* argv[]) printf("%s=%s, \nnext=%s\n", lstr, buf, nstr); lstr = nstr; } + objectCall2(bignumber, AssignStr, testnumber, &nstr); + objectCall3(bignumber, GetStr, 16, buf, 256); + printf("n=%s\n", buf); + objectCall1(bignumber, SetBitsCount, 9); + objectCall3(bignumber, GetStr, 16, buf, 256); + printf("n<<68=%s\n", buf); return 0; } \ No newline at end of file -- GitLab