/* ** HDL4SE: 软件Verilog综合仿真平台 ** Copyright (C) 2021-2021, raoxianhong ** LCOM: 轻量级组件对象模型 ** Copyright (C) 2021-2021, raoxianhong ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are met: ** ** * Redistributions of source code must retain the above copyright notice, ** this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright notice, ** this list of conditions and the following disclaimer in the documentation ** and/or other materials provided with the distribution. ** * The name of the author may be used to endorse or promote products ** derived from this software without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF ** THE POSSIBILITY OF SUCH DAMAGE. */ /* * bignumber.c 202105201110: rxh, initial version 202105260952: rxh, 修改了接口,为verilog语言编译做准备,主要是区分了带符号和不带符号计算 202106130718: rxh, 增加实现了DList接口,支持放在双向链表中 202106190808: rxh, 在数字中增加是否带符号标记 202106251628: rxh, 处理输入和输出宽度不确定的情况 */ #include "stdlib.h" #include "stdio.h" #include "object.h" #include "dlist.h" #include "string.h" #define IMPLEMENT_GUID #include "bignumber.h" #undef IMPLEMENT_GUID #define NOTIMPL printf("bignumber.c %d, %s is not implemented now\n", __LINE__, __FUNCTION__) #define HDL4SEDEBUG 1 #if HDL4SEDEBUG static char __debug_buf[60]; #endif #define CELL_WIDTH 32 #define CELL_MASK 0xffffffff typedef struct _sBigInteger { OBJECT_HEADER INTERFACE_DECLARE(IBigNumber) BIGNUMBER_VARDECLARE DLIST_VARDECLARE int buflen; int width; int isunsigned; unsigned int* buf; }sBigInteger; OBJECT_FUNCDECLARE(bigint, CLSID_BIGINTEGER); BIGNUMBER_FUNCDECLARE(bigint, CLSID_BIGINTEGER, sBigInteger); DLIST_FUNCIMPL(bigint, CLSID_BIGINTEGER, sBigInteger); OBJECT_FUNCIMPL(bigint, sBigInteger, CLSID_BIGINTEGER); QUERYINTERFACE_BEGIN(bigint, CLSID_BIGINTEGER) QUERYINTERFACE_ITEM(IID_BIGNUMBER, IBigNumber, sBigInteger) QUERYINTERFACE_ITEM(IID_DLIST, IDList, sBigInteger) QUERYINTERFACE_END static const char* bigintModuleInfo() { return "1.0.1-20210625.1628 Big integer library"; } static int bigintCreate(const PARAMITEM* pParams, int paramcount, HOBJECT* pObject) { sBigInteger* pobj; int i; pobj = (sBigInteger*)malloc(sizeof(sBigInteger)); if (pobj == NULL) return -1; *pObject = 0; BIGNUMBER_VARINIT(pobj, CLSID_BIGINTEGER); INTERFACE_INIT(IBigNumber, pobj, bigint, bn); DLIST_VARINIT(pobj, bigint); pobj->width = 64; for (i = 0; i < paramcount; i++) { if (pParams[i].name == PARAMID_BIGINTEGERWIDTH) pobj->width = pParams[i].i32value; } if (pobj->width <= 0) pobj->width = 64; pobj->isunsigned = -1; pobj->buflen = (pobj->width + CELL_WIDTH - 1) / CELL_WIDTH; if (pobj->buflen < 2) pobj->buflen = 2; pobj->buf = malloc(pobj->buflen * sizeof(unsigned int)); if (pobj->buf == NULL) return -1; for (i = 0;ibuflen;i++) pobj->buf[i] = 0; /* 返回生成的对象 */ OBJECT_RETURN_GEN(bigint, pobj, pObject, CLSID_BIGINTEGER); return EIID_OK; } static int actualwidth(unsigned int n) { unsigned int c = 1; int ret = 1; if (n & 0x80000000) return CELL_WIDTH; while (c <= n) { c <<= 1; ret++; } return ret-1; } static void bigintDestroy(HOBJECT object) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); free(pobj->buf); free(pobj); } static int bigintValid(HOBJECT object) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); if (pobj == NULL) return 0; if (pobj->buflen < 2) return 0; if (pobj->buflen * CELL_WIDTH < pobj->width) return 0; if (pobj->buf == NULL) return 0; return 1; } static int bigint_bn_GetWidth(HOBJECT object) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); return pobj->width; } static int bigint_bn_SetWidth(HOBJECT object, int width) { int i, bc, blen, sign; sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); if (width <= 0) { return -1; } sign = 0; if (pobj->isunsigned == 0) { bc = (pobj->width - 1) / CELL_WIDTH; sign = pobj->buf[bc] & (1 << ((pobj->width-1) % (CELL_WIDTH-1))); } blen = (width + CELL_WIDTH - 1) / CELL_WIDTH; if (blen < 2) blen = 2; if (pobj->buflen < blen) { unsigned int * buf; buf = (unsigned int *)malloc(blen * (CELL_WIDTH / 8)); if (buf == NULL) return -1; for (i = 0; i < pobj->buflen; i++) buf[i] = pobj->buf[i]; pobj->buflen = blen; free(pobj->buf); pobj->buf = buf; } blen = pobj->width / CELL_WIDTH; if (blen < pobj->buflen) { bc = pobj->width & (CELL_WIDTH - 1); if (sign) pobj->buf[blen] |= CELL_MASK << bc; else pobj->buf[blen] &= CELL_MASK >> (CELL_WIDTH - bc); } for (i = blen + 1; i < pobj->buflen; i++) { pobj->buf[i] = sign ? CELL_MASK : 0; } blen = width / CELL_WIDTH; if (blen < pobj->buflen) { bc = width & (CELL_WIDTH - 1); if (sign) pobj->buf[blen] |= CELL_MASK << bc; else pobj->buf[blen] &= CELL_MASK >> (CELL_WIDTH - bc); } for (i = blen+1; i < pobj->buflen; i++) { pobj->buf[i] = sign ? CELL_MASK : 0; } pobj->width = width; return 0; } static int bigint_bn_IsUnsigned(HOBJECT object) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); return pobj->isunsigned; } static int bigint_bn_SetUnsigned(HOBJECT object, int isunsigned) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); pobj->isunsigned = isunsigned?1:0; bigint_bn_SetWidth(object, pobj->width); return 0; } static int bigint_bn_GetBits32(HOBJECT object, int ind32, unsigned int* pbits) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); if (ind32 < 0 || ind32 >= pobj->buflen) { *pbits = 0; return -1; } *pbits = pobj->buf[ind32]; return 0; } static int bigint_bn_SetBits32(HOBJECT object, int ind32, unsigned int bits) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); if (ind32 < 0 || ind32 >= pobj->buflen) return -1; pobj->buf[ind32] = bits; return 0; } static int bigint_bn_GetBit(HOBJECT object, int indbit) { sBigInteger* pobj; int ind32; pobj = (sBigInteger*)objectThis(object); if (indbit < 0 || indbit >= pobj->width) return -1; ind32 = indbit / 32; return pobj->buf[ind32] & (1 << (indbit & 31)); } static int bigint_bn_SetBit(HOBJECT object, int indbit, int bit) { sBigInteger* pobj; int ind32; pobj = (sBigInteger*)objectThis(object); if (indbit < 0 || indbit >= pobj->width) return -1; ind32 = indbit / 32; if (bit != 0) pobj->buf[ind32] |= (1 << (indbit & 31)); else pobj->buf[ind32] &= ~(1 << (indbit & 31)); return 0; } static int bigint_bn_GetInt32(HOBJECT object, int* pvalue) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); *(unsigned int*)pvalue = pobj->buf[0]; return 0; } static int bigint_bn_GetInt64(HOBJECT object, long long* pvalue) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); ((unsigned int *)pvalue)[0] = pobj->buf[0]; ((unsigned int *)pvalue)[1] = pobj->buf[1]; return 0; } static int bigint_bn_GetUint32(HOBJECT object, unsigned int* pvalue) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); *(unsigned int*)pvalue = pobj->buf[0]; return 0; } static int bigint_bn_GetUint64(HOBJECT object, unsigned long long* pvalue) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); ((unsigned int*)pvalue)[0] = pobj->buf[0]; ((unsigned int*)pvalue)[1] = pobj->buf[1]; return 0; } static int bigint_bn_GetStr2(sBigInteger* pobj, char* str, int buflen) { int i; if (pobj->width < buflen - 1) { buflen = pobj->width; } for (i = 0; i < buflen; i++) { str[buflen - 1 - i] = (pobj->buf[i / CELL_WIDTH] & (1 << (i & (CELL_WIDTH-1))))? '1' : '0'; } str[buflen] = '\0'; return 0; } static int bigint_bn_GetStr10(sBigInteger* pobj, char* str, int buflen) { int i; int len; unsigned int value; int sign = 0; int v; if (pobj->width > 30) { return -1; } v = pobj->buf[0]; if (v < 0 && pobj->isunsigned == 0) { sign = 1; value = -v; } else { value = pobj->buf[0]; } i = 0; while (value > 0) { int num = value % 10; value /= 10; str[i++] = num + '0'; } if (i == 0) str[i++] = '0'; if (sign) str[i++] = '-'; str[i] = 0; len = i; for (i = 0;iisunsigned) sprintf(str, "%d'h", bc); else sprintf(str, "%d'sh", bc); i = ((bc + (CELL_WIDTH-1)) / CELL_WIDTH) - 1; ac = actualwidth(pobj->buf[i]); ac = (ac + 7) / 8; sprintf(fmt, "%%%dx", ac); sprintf(buf, fmt, pobj->buf[i]); strcat(str, buf); for (i = ((bc + (CELL_WIDTH-1)) / CELL_WIDTH)-2; i >= 0; i--) { sprintf(buf, "%08x", pobj->buf[i]); strcat(str, buf); } return 0; } static int bigint_bn_AssignInt32(HOBJECT object, int value) { int i; sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); for (i = 1; i < pobj->buflen; i++) pobj->buf[i] = 0; pobj->buf[0] = *(unsigned int*)&value; if (pobj->isunsigned == -1) pobj->isunsigned = 0; bigint_bn_SetWidth(object, pobj->width); return 0; } static int bigint_bn_AssignInt64(HOBJECT object, long long value) { int i; sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); for (i = 2; i < pobj->buflen; i++) pobj->buf[i] = 0; pobj->buf[0] = (*(unsigned long long*)(&value)) & CELL_MASK; pobj->buf[1] = ((*(unsigned long long*)(&value)) >> CELL_WIDTH) & CELL_MASK; if (pobj->isunsigned == -1) pobj->isunsigned = 0; bigint_bn_SetWidth(object, pobj->width); return 0; } static int bigint_bn_AssignUint32(HOBJECT object, unsigned int value) { int i; sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); for (i = 1; i < pobj->buflen; i++) pobj->buf[i] = 0; pobj->buf[0] = *(unsigned int*)&value; if (pobj->isunsigned == -1) pobj->isunsigned = 1; bigint_bn_SetWidth(object, pobj->width); return 0; } static int bigint_bn_AssignUint64(HOBJECT object, unsigned long long value) { int i; sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); for (i = 2; i < pobj->buflen; i++) pobj->buf[i] = 0; pobj->buf[0] = (*(unsigned long long*)(&value)) & CELL_MASK; pobj->buf[1] = ((*(unsigned long long*)(&value)) >> CELL_WIDTH) & CELL_MASK; if (pobj->isunsigned == -1) pobj->isunsigned = 0; bigint_bn_SetWidth(object, pobj->width); return 0; } enum TOKEN_STATE { TOKEN_INITIAL, TOKEN_NUM, TOKEN_BASE, TOKEN_BIN, TOKEN_OCT, TOKEN_DEC, TOKEN_HEX }; #define MAXNUMWIDTH (1 << 30) static int bigint_bn_AssignStr(HOBJECT object, const char* str, const char **nstr, int autowidth) { int width, objwidth; enum TOKEN_STATE state; const char* strt = str; int numvalid = 0; sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); width = -1; objwidth = pobj->width; if (autowidth == 0 && objwidth <= 0) return -1; pobj->isunsigned = 1; bigint_bn_SetWidth(object, 32); state = TOKEN_INITIAL; if (nstr != NULL) *nstr = strt; while (*strt != 0) { int ch = *strt; switch (state) { case TOKEN_INITIAL: { if (ch == '\'') { state = TOKEN_BASE; } else if (ch >= '0' && ch <= '9') { bigint_bn_AssignInt32(object, ch - '0'); numvalid = 1; state = TOKEN_NUM; } } break; case TOKEN_NUM: { if (ch >= '0' && ch <= '9') { if (pobj->buf[pobj->buflen - 1] > (1 << 27)) { int w; w = pobj->width * 2; if (w > MAXNUMWIDTH) { w = MAXNUMWIDTH; } if (0 != bigint_bn_SetWidth(object, w)) { if (nstr != NULL) *nstr = strt; return -1; } } bigint_bn_MulInt32(object, object, 10); bigint_bn_AddInt32(object, object, ch - '0'); } else if (ch == '\'') { int i; for (i = pobj->buflen - 1; i > 0; i--) { if (pobj->buf[i] != 0) { /* too large width of a number */ width = MAXNUMWIDTH; break; } } if (width == -1) { if (pobj->buf[0] > MAXNUMWIDTH) { width = MAXNUMWIDTH; } else { width = pobj->buf[0]; } } pobj->isunsigned = 1; state = TOKEN_BASE; if (width == 0) width = -1; else if (0 != bigint_bn_SetWidth(object, width)) { if (nstr != NULL) *nstr = strt; } objwidth = width; numvalid = 0; } else { pobj->isunsigned = 0; goto lastnum; } }break; case TOKEN_BASE: { if (ch == 's' || ch == 'S') { pobj->isunsigned = 0; } else if (ch == 'b' || ch == 'B') { bigint_bn_AssignInt32(object, 0); state = TOKEN_BIN; } else if (ch == 'h' || ch == 'H') { bigint_bn_AssignInt32(object, 0); state = TOKEN_HEX; } else if (ch == 'o' || ch == 'O') { bigint_bn_AssignInt32(object, 0); state = TOKEN_OCT; } else if (ch == 'd' || ch == 'D') { bigint_bn_AssignInt32(object, 0); state = TOKEN_DEC; } else if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') { } else { if (nstr != NULL) *nstr = strt; return -1; } }break; case TOKEN_BIN: { if (ch == '0' || ch == '1') { if (autowidth && (width == -1)) { if (pobj->buf[pobj->buflen - 1] > (1 << 27)) { int w; w = pobj->width * 2; if (w > MAXNUMWIDTH) { w = MAXNUMWIDTH; } if (0 != bigint_bn_SetWidth(object, w)) { if (nstr != NULL) *nstr = strt; return -1; } } } bigint_bn_MulUint32(object, object, 2); bigint_bn_AddUint32(object, object, ch - '0'); numvalid = 1; } else if (ch == '_') { } else { goto lastnum; } }break; case TOKEN_OCT: { if (ch >= '0' && ch <= '7') { if (autowidth && (width == -1)) { if (pobj->buf[pobj->buflen - 1] > (1 << 27)) { int w; w = pobj->width * 2; if (w > MAXNUMWIDTH) { w = MAXNUMWIDTH; } if (0 != bigint_bn_SetWidth(object, w)) { if (nstr != NULL) *nstr = strt; return -1; } } } bigint_bn_MulUint32(object, object, 8); bigint_bn_AddUint32(object, object, ch - '0'); numvalid = 1; } else if (ch == '_') { } else { goto lastnum; } }break; case TOKEN_DEC: { if (ch >= '0' && ch <= '9') { if (autowidth && (width == -1)) { if (pobj->buf[pobj->buflen - 1] > (1 << 27)) { int w; w = pobj->width * 2; if (w > MAXNUMWIDTH) { w = MAXNUMWIDTH; } if (0 != bigint_bn_SetWidth(object, w)) { if (nstr != NULL) *nstr = strt; return -1; } } } bigint_bn_MulUint32(object, object, 10); bigint_bn_AddUint32(object, object, ch - '0'); numvalid = 1; } else { goto lastnum; } }break; case TOKEN_HEX: { if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) { numvalid = 1; if (autowidth && (width == -1)) { if (pobj->buf[pobj->buflen - 1] > (1 << 27)) { int w; w = pobj->width * 2; if (w > MAXNUMWIDTH) { w = MAXNUMWIDTH; } if (0 != bigint_bn_SetWidth(object, w)) { if (nstr != NULL) *nstr = strt; return -1; } } } bigint_bn_MulUint32(object, object, 16); if (ch > '0' && ch <= '9') bigint_bn_AddUint32(object, object, ch - '0'); else if (ch >= 'a' && ch <= 'f') bigint_bn_AddUint32(object, object, ch - 'a' + 10); else if (ch >= 'A' && ch <= 'F') bigint_bn_AddUint32(object, object, ch - 'A' + 10); } else if (ch == '_') { } else { goto lastnum; } }break; } strt++; } if (numvalid == 0) { if (nstr != NULL) *nstr = strt; return -1; } lastnum: if (nstr != NULL) *nstr = strt; if (autowidth && (width == -1)) { int i; width = 0; for (i = pobj->buflen - 1; i >= 0; i--) { if (pobj->buf[i] != 0) { width = actualwidth(pobj->buf[i]); width += i * CELL_WIDTH; break; } } if (width == 0) width = 1; // if (pobj->isunsigned == 0) width++; } else { width = objwidth; } bigint_bn_SetWidth(object, width); return 0; } static int bigint_bn_Clone(HOBJECT object, HOBJECT src) { sBigInteger* pobj; IBigNumber** numsrc; int i; int width; int buflen; pobj = (sBigInteger*)objectThis(object); if (EIID_OK != objectQueryInterface(src, IID_BIGNUMBER, (void**)&numsrc)) return -1; width = objectCall0(numsrc, GetWidth); if (width <= 0) { objectRelease(numsrc); return -1; } buflen = (width + CELL_WIDTH - 1) / CELL_WIDTH; if (buflen < 2) buflen = 2; if (pobj->buflen < buflen) { unsigned int* buf; buf = (unsigned int*)malloc(buflen * (CELL_WIDTH / 8)); if (buf == NULL) { objectRelease(numsrc); return -2; } free(pobj->buf); pobj->buf = buf; } pobj->buflen = buflen; pobj->width = width; pobj->isunsigned = objectCall0(numsrc, IsUnsigned); for (i = 0; i < pobj->buflen; i++) { objectCall2(numsrc, GetBits32, i, &pobj->buf[i]); } objectRelease(numsrc); return 0; } static int bigint_bn_CloneSubBits(HOBJECT object, HOBJECT src, int from, int width) { if (from < 0 || width <= 0) return -1; #if HDL4SEDEBUG char buf[60]; bigint_bn_GetStr(src, 16, buf, 60); #endif bigint_bn_SetUnsigned(object, 1); bigint_bn_SetWidth(object, width); bigint_bn_SHR(object, src, from); #if HDL4SEDEBUG bigint_bn_GetStr(object, 16, buf, 60); #endif bigint_bn_SetWidth(object, width); #if HDL4SEDEBUG bigint_bn_GetStr(object, 16, buf, 60); #endif return 0; } static int bigint_bn_Assign(HOBJECT object, HOBJECT src) { int width, isunsigned; width = bigint_bn_GetWidth(object); isunsigned = bigint_bn_IsUnsigned(object); bigint_bn_Clone(object, src); bigint_bn_SetUnsigned(object, isunsigned); bigint_bn_SetWidth(object, width); return 0; } static int bigint_bn_AssignSubBits(HOBJECT object, HOBJECT src, int from, int width) { int objwidth; #if HDL4SEDEBUG char buf[60]; bigint_bn_GetStr(src, 16, buf, 60); #endif objwidth = bigint_bn_GetWidth(object); bigint_bn_CloneSubBits(object, src, from, width); bigint_bn_SetWidth(object, objwidth); #if HDL4SEDEBUG bigint_bn_GetStr(object, 16, buf, 60); #endif return 0; } static int bigint_bn_AddInt32(HOBJECT object, HOBJECT src, int value) { unsigned long long temp; int ind; unsigned int v, vs, widthsrc, width; int objunsigned, srcunsigned; sBigInteger* pobj; IBigNumber** numsrc; pobj = (sBigInteger*)objectThis(object); if (EIID_OK != objectQueryInterface(src, IID_BIGNUMBER, (void**)&numsrc)) return -1; widthsrc = objectCall0(numsrc, GetWidth); srcunsigned = objectCall0(numsrc, IsUnsigned); objunsigned = pobj->isunsigned; width = pobj->width; if (width < widthsrc) width = widthsrc; //objectCall1(numsrc, SetUnsigned, 0); objectCall1(numsrc, SetWidth, width); //bigint_bn_SetUnsigned(object, 0); bigint_bn_SetWidth(object, width); objectCall2(numsrc, GetBits32, 0, &vs); temp = vs; temp += *(unsigned int*)&value; pobj->buf[0] = temp & CELL_MASK; temp >>= CELL_WIDTH; ind = 1; v = 0; if (value < 0) v = CELL_MASK; while (ind < pobj->buflen) { temp += v; if (0 != objectCall2(numsrc, GetBits32, ind, &vs)) vs = CELL_MASK; temp += vs; pobj->buf[ind] = temp & CELL_MASK; temp >>= CELL_WIDTH; ind++; } objectCall1(numsrc, SetUnsigned, srcunsigned); objectCall1(numsrc, SetWidth, widthsrc); bigint_bn_SetUnsigned(object, objunsigned); bigint_bn_SetWidth(object, pobj->width); return 0; } static int bigint_bn_SubInt32(HOBJECT object, HOBJECT src, int value) { return bigint_bn_AddInt32(object, src, -value); } static int bigint_bn_MulInt32(HOBJECT object, HOBJECT src, int value) { IBigNumber ** temp; temp = bigintegerCreate(32); bigint_bn_SetUnsigned(temp, 0); bigint_bn_AssignInt32(temp, value); bigint_bn_Mul(object, src, temp); objectRelease(temp); return 0; } static int bigint_bn_DivInt32(HOBJECT object, HOBJECT src, int value) { IBigNumber** temp; temp = bigintegerCreate(32); bigint_bn_SetUnsigned(temp, 0); bigint_bn_AssignInt32(temp, value); bigint_bn_Div(object, src, temp); objectRelease(temp); return 0; } static int bigint_bn_ModInt32(HOBJECT object, HOBJECT src, int value) { IBigNumber** temp; temp = bigintegerCreate(32); bigint_bn_SetUnsigned(temp, 0); bigint_bn_AssignInt32(temp, value); bigint_bn_Mod(object, src, temp); objectRelease(temp); return 0; } static int bigint_bn_PowInt32(HOBJECT object, HOBJECT src, int value) { IBigNumber** temp; temp = bigintegerCreate(32); bigint_bn_SetUnsigned(temp, 0); bigint_bn_AssignInt32(temp, value); bigint_bn_Pow(object, src, temp); objectRelease(temp); return 0; } static int bigint_bn_AddUint32(HOBJECT object, HOBJECT src, unsigned int value) { return bigint_bn_AddInt32(object, src, value); } static int bigint_bn_SubUint32(HOBJECT object, HOBJECT src, unsigned int value) { bigint_bn_AssignUint32(object, value); bigint_bn_Neg(object, object); bigint_bn_Add(object, object, src); return 0; } static int bigint_bn_MulUint32(HOBJECT object, HOBJECT src, unsigned int value) { IBigNumber** temp; temp = bigintegerCreate(32); bigint_bn_SetUnsigned(temp, 1); bigint_bn_AssignUint32(temp, value); bigint_bn_Mul(object, src, temp); objectRelease(temp); return 0; } static int bigint_bn_DivUint32(HOBJECT object, HOBJECT src, unsigned int value) { IBigNumber** temp; temp = bigintegerCreate(32); bigint_bn_SetUnsigned(temp, 1); bigint_bn_AssignUint32(temp, value); bigint_bn_Div(object, src, temp); objectRelease(temp); return 0; } static int bigint_bn_ModUint32(HOBJECT object, HOBJECT src, unsigned int value) { IBigNumber** temp; temp = bigintegerCreate(32); bigint_bn_SetUnsigned(temp, 1); bigint_bn_AssignUint32(temp, value); bigint_bn_Mod(object, src, temp); objectRelease(temp); return 0; } static int bigint_bn_PowUint32(HOBJECT object, HOBJECT src, unsigned int value) { IBigNumber** temp; temp = bigintegerCreate(32); bigint_bn_SetUnsigned(temp, 1); bigint_bn_AssignUint32(temp, value); bigint_bn_Pow(object, src, temp); objectRelease(temp); return 0; } static int bigint_bn_Add(HOBJECT object, HOBJECT src0, HOBJECT src1) { unsigned long long temp; sBigInteger* pobj; IBigNumber** psrc0; IBigNumber** psrc1; int widthobj, widthsrc0, widthsrc1, width; int objunsigned, src0unsigned, src1unsigned; int i; pobj = (sBigInteger*)objectThis(object); if (EIID_OK != objectQueryInterface(src0, IID_BIGNUMBER, (void**)&psrc0)) { return -1; } if (EIID_OK != objectQueryInterface(src1, IID_BIGNUMBER, (void**)&psrc1)) { objectRelease(psrc0); return -1; } widthobj = pobj->width; widthsrc0 = objectCall0(psrc0, GetWidth); widthsrc1 = objectCall0(psrc1, GetWidth); objunsigned = pobj->isunsigned; src0unsigned = objectCall0(psrc0, IsUnsigned); src1unsigned = objectCall0(psrc1, IsUnsigned); // bigint_bn_SetUnsigned(object, 0); // objectCall1(psrc0, SetUnsigned, 0); // objectCall1(psrc1, SetUnsigned, 0); width = widthsrc0; if (width < widthsrc1) width = widthsrc1; if (width < widthobj) width = widthobj; objectCall1(psrc0, SetWidth, width); objectCall1(psrc1, SetWidth, width); bigint_bn_SetWidth(object, width); temp = 0; for (i = 0; i < pobj->buflen; i++) { unsigned int src0value, src1value; objectCall2(psrc0, GetBits32, i, &src0value); objectCall2(psrc1, GetBits32, i, &src1value); temp += src0value; temp += src1value; pobj->buf[i] = temp & CELL_MASK; temp >>= CELL_WIDTH; } bigint_bn_SetUnsigned(object, objunsigned); objectCall1(psrc0, SetUnsigned, src0unsigned); objectCall1(psrc1, SetUnsigned, src1unsigned); bigint_bn_SetWidth(object, widthobj); objectCall1(psrc0, SetWidth, widthsrc0); objectCall1(psrc1, SetWidth, widthsrc1); objectRelease(psrc0); objectRelease(psrc1); return 0; } static int bigint_bn_Sub(HOBJECT object, HOBJECT src0, HOBJECT src1) { IBigNumber** temp = NULL; int ret; temp = bigintegerCreate(32); sBigInteger* pobj, * psrc0, * psrc1, * ptemp; pobj = objectThis(object); psrc0 = objectThis(src0); psrc1 = objectThis(src1); ptemp = objectThis(temp); objectCall1(temp, Clone, src1); objectCall1(temp, SetUnsigned, 0); if (EIID_OK != bigint_bn_Neg(temp, temp)) return -1; ret = bigint_bn_Add(object, src0, temp); retresult: return ret; } static int bigint_bn_Mul(HOBJECT object, HOBJECT src0, HOBJECT src1) { sBigInteger* pobj; IBigNumber** psrc0; IBigNumber** psrc1; unsigned int* buf; int widthobj, widthsrc0, widthsrc1, width; int objunsigned, src0unsigned, src1unsigned; int i, j; pobj = (sBigInteger*)objectThis(object); if (EIID_OK != objectQueryInterface(src0, IID_BIGNUMBER, (void**)&psrc0)) { return -1; } if (EIID_OK != objectQueryInterface(src1, IID_BIGNUMBER, (void**)&psrc1)) { objectRelease(psrc0); return -1; } widthobj = pobj->width; widthsrc0 = objectCall0(psrc0, GetWidth); widthsrc1 = objectCall0(psrc1, GetWidth); objunsigned = pobj->isunsigned; src0unsigned = objectCall0(psrc0, IsUnsigned); src1unsigned = objectCall0(psrc1, IsUnsigned); // bigint_bn_SetUnsigned(object, 0); // objectCall1(psrc0, SetUnsigned, 0); // objectCall1(psrc1, SetUnsigned, 0); width = widthobj; if (width < widthsrc0) width = widthsrc0; if (width < widthsrc1) width = widthsrc1; objectCall1(psrc0, SetWidth, width); objectCall1(psrc1, SetWidth, width); bigint_bn_SetWidth(object,width); buf = (unsigned int *)malloc(pobj->buflen * sizeof(unsigned int)); if (buf == NULL) return -1; for (i = 0; i < pobj->buflen; i++) buf[i] = 0; for (i = 0; i < pobj->buflen; i++) { unsigned long long addin; unsigned long long m0, m1; unsigned int m0s, m1s; addin = 0; objectCall2(psrc0, GetBits32, i, &m0s); m0 = m0s; for (j = 0; j < pobj->buflen - i; j++) { objectCall2(psrc1, GetBits32, j, &m1s); m1 = m1s; m1 = m0 * m1 + addin + buf[i + j]; buf[i + j] = m1 & CELL_MASK; addin = m1 >> CELL_WIDTH; } } free(pobj->buf); pobj->buf = buf; bigint_bn_SetUnsigned(object, objunsigned); objectCall1(psrc0, SetUnsigned, src0unsigned); objectCall1(psrc1, SetUnsigned, src1unsigned); bigint_bn_SetWidth(object, widthobj); objectCall1(psrc0, SetWidth, widthsrc0); objectCall1(psrc1, SetWidth, widthsrc1); objectRelease(psrc0); objectRelease(psrc1); return 0; } static int bigint_bn_Div(HOBJECT object, HOBJECT src0, HOBJECT src1) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); NOTIMPL; return 0; } static int bigint_bn_Mod(HOBJECT object, HOBJECT src0, HOBJECT src1) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); NOTIMPL; return 0; } static int bigint_bn_Pow(HOBJECT object, HOBJECT src0, HOBJECT src1) { sBigInteger* pobj; pobj = (sBigInteger*)objectThis(object); NOTIMPL; return 0; } static int bigint_bn_Neg(HOBJECT object, HOBJECT src) { /* 反码加一 */ bigint_bn_Not(object, src); bigint_bn_AddInt32(object, object, 1); return 0; } static int bigint_bn_Abs(HOBJECT object, HOBJECT src) { if (bigint_bn_IsNeg(src)) bigint_bn_Neg(object, src); else bigint_bn_Assign(object, src); return 0; } static int bigint_bn_IsGT(HOBJECT object, HOBJECT src) { return !bigint_bn_IsLE(object, src); } static int bigint_bn_IsGE(HOBJECT object, HOBJECT src) { return !bigint_bn_IsLT(object, src); } static int bigint_bn_IsLT(HOBJECT object, HOBJECT src) { IBigNumber** numobj; IBigNumber** numsrc; IBigNumber** numsub; int ret; int i, buflen, widthobj, widthsrc, width, isunsignedobj, isunsignedsrc; sBigInteger* pobj, * psrc; pobj = objectThis(object); psrc = objectThis(src); #if HDL4SEDEBUG bigint_bn_GetStr(object, 16, __debug_buf, sizeof(__debug_buf)); bigint_bn_GetStr(src, 16, __debug_buf, sizeof(__debug_buf)); #endif if (0 != objectQueryInterface(object, IID_BIGNUMBER, &numobj)) return -1; if (0 != objectQueryInterface(src, IID_BIGNUMBER, &numsrc)) { objectRelease(numobj); return -1; } widthobj = objectCall0(numobj, GetWidth); widthsrc = objectCall0(numsrc, GetWidth); isunsignedobj = objectCall0(numobj, IsUnsigned); isunsignedsrc = objectCall0(numsrc, IsUnsigned); width = widthobj; if (width < widthsrc) width = widthsrc; numsub = bigintegerCreate(width); objectCall1(numsub, SetUnsigned, 0); objectCall2(numsub, Sub, object, src); #if HDL4SEDEBUG bigint_bn_GetStr(numsub, 16, __debug_buf, sizeof(__debug_buf)); bigint_bn_GetStr(object, 16, __debug_buf, sizeof(__debug_buf)); #endif ret = objectCall0(numsub, IsNeg); retresult: objectCall1(numobj, SetUnsigned, isunsignedobj); objectCall1(numobj, SetWidth, widthobj); objectCall1(numsrc, SetUnsigned, isunsignedsrc); objectCall1(numsrc, SetWidth, widthsrc); objectRelease(numobj); objectRelease(numsrc); objectRelease(numsub); return ret; } static int bigint_bn_IsLE(HOBJECT object, HOBJECT src) { if (bigint_bn_IsLT(object, src)) return 1; if (bigint_bn_IsEQ(object, src)) return 1; return 0; } static int bigint_bn_IsEQ(HOBJECT object, HOBJECT src) { IBigNumber** numobj; IBigNumber** numsrc; int ret; int i, buflen, widthobj, widthsrc, width, isunsignedobj, isunsignedsrc; if (0 != objectQueryInterface(object, IID_BIGNUMBER, &numobj)) return -1; if (0 != objectQueryInterface(src, IID_BIGNUMBER, &numsrc)) { objectRelease(numobj); return -1; } widthobj = objectCall0(numobj, GetWidth); widthsrc = objectCall0(numsrc, GetWidth); isunsignedobj = objectCall0(numobj, IsUnsigned); isunsignedsrc = objectCall0(numsrc, IsUnsigned); width = widthobj; if (width < widthsrc) width = widthsrc; // objectCall1(numobj, SetUnsigned, 0); objectCall1(numobj, SetWidth, width); // objectCall1(numsrc, SetUnsigned, 0); objectCall1(numsrc, SetWidth, width); buflen = (width + 31) / 32; for (i = 0; i < buflen; i++) { unsigned int srcdata, objdata; objectCall2(numobj, GetBits32, i, &objdata); objectCall2(numsrc, GetBits32, i, &srcdata); if (objdata != srcdata) { ret = 0; goto retresult; } } ret = 1; retresult: objectCall1(numobj, SetUnsigned, isunsignedobj); objectCall1(numobj, SetWidth, widthobj); objectCall1(numsrc, SetUnsigned, isunsignedsrc); objectCall1(numsrc, SetWidth, widthsrc); objectRelease(numobj); objectRelease(numsrc); return ret; } static int bigint_bn_IsNE(HOBJECT object, HOBJECT src) { return !bigint_bn_IsEQ(object, src); } static int bigint_bn_IsZero(HOBJECT object) { sBigInteger* pobj; int i; pobj = (sBigInteger*)objectThis(object); for (i = 0; i < pobj->buflen; i++) if (pobj->buf[i] != 0) return 0; return 1; } static int bigint_bn_IsNotZero(HOBJECT object) { sBigInteger* pobj; int i; pobj = (sBigInteger*)objectThis(object); for (i = 0; i < pobj->buflen; i++) if (pobj->buf[i] != 0) return 1; return 0; } static int bigint_bn_IsNeg(HOBJECT object) { sBigInteger* pobj; int bc, sign, signpos; if (bigint_bn_IsZero(object)) return 0; pobj = (sBigInteger*)objectThis(object); if (pobj->isunsigned) return 0; bc = (pobj->width - 1) / CELL_WIDTH; signpos = (pobj->width - 1) % CELL_WIDTH; sign = pobj->buf[bc] & (1 << signpos); return sign ? 1 : 0; } static int bigint_bn_AndL(HOBJECT object, HOBJECT src) { int o, s; o = bigint_bn_IsNotZero(object); s = bigint_bn_IsNotZero(src); return o && s; } static int bigint_bn_OrL(HOBJECT object, HOBJECT src) { int o, s; o = bigint_bn_IsNotZero(object); s = bigint_bn_IsNotZero(src); return o || s; } static int bigint_bn_NotL(HOBJECT object) { int o; o = bigint_bn_IsNotZero(object); return !o; } static int bigint_bn_And(HOBJECT object, HOBJECT src0, HOBJECT src1) { IBigNumber** numobj; IBigNumber** numsrc0; IBigNumber** numsrc1; int widthobj, widthsrc0, widthsrc1, isunsignedobj, isunsignedsrc0, isunsignedsrc1, width; int i, buflen; if (EIID_OK != objectQueryInterface(object, IID_BIGNUMBER, (void**)&numobj)) { return -1; } if (EIID_OK != objectQueryInterface(src0, IID_BIGNUMBER, (void**)&numsrc0)) { objectRelease(numobj); return -1; } if (EIID_OK != objectQueryInterface(src1, IID_BIGNUMBER, (void**)&numsrc1)) { objectRelease(numobj); objectRelease(numsrc0); return -1; } widthobj = objectCall0(numobj, GetWidth); widthsrc0 = objectCall0(numsrc0, GetWidth); widthsrc1 = objectCall0(numsrc1, GetWidth); isunsignedobj = objectCall0(numobj, IsUnsigned); isunsignedsrc0 = objectCall0(numsrc0, IsUnsigned); isunsignedsrc1 = objectCall0(numsrc1, IsUnsigned); width = widthobj; if (width < widthsrc0) width = widthsrc0; if (width < widthsrc1) width = widthsrc1; // objectCall1(numobj, SetUnsigned, 0); // objectCall1(numsrc0, SetUnsigned, 0); // objectCall1(numsrc1, SetUnsigned, 0); objectCall1(numobj, SetWidth, width); objectCall1(numsrc0, SetWidth, width); objectCall1(numsrc1, SetWidth, width); buflen = (width + CELL_WIDTH - 1) / CELL_WIDTH; for (i = 0; i < buflen; i++) { unsigned int src0value, src1value; objectCall2(numsrc0, GetBits32, i, &src0value); objectCall2(numsrc1, GetBits32, i, &src1value); objectCall2(numobj, SetBits32, i, src0value & src1value); } objectCall1(numobj, SetUnsigned, isunsignedobj); objectCall1(numsrc0, SetUnsigned, isunsignedsrc0); objectCall1(numsrc1, SetUnsigned, isunsignedsrc1); objectCall1(numobj, SetWidth, widthobj); objectCall1(numsrc0, SetWidth, widthsrc0); objectCall1(numsrc1, SetWidth, widthsrc1); objectRelease(numobj); objectRelease(numsrc0); objectRelease(numsrc1); return 0; } static int bigint_bn_Or(HOBJECT object, HOBJECT src0, HOBJECT src1) { IBigNumber** numobj; IBigNumber** numsrc0; IBigNumber** numsrc1; int widthobj, widthsrc0, widthsrc1, isunsignedobj, isunsignedsrc0, isunsignedsrc1, width; int i, buflen; if (EIID_OK != objectQueryInterface(object, IID_BIGNUMBER, (void**)&numobj)) { return -1; } if (EIID_OK != objectQueryInterface(src0, IID_BIGNUMBER, (void**)&numsrc0)) { objectRelease(numobj); return -1; } if (EIID_OK != objectQueryInterface(src1, IID_BIGNUMBER, (void**)&numsrc1)) { objectRelease(numobj); objectRelease(numsrc0); return -1; } widthobj = objectCall0(numobj, GetWidth); widthsrc0 = objectCall0(numsrc0, GetWidth); widthsrc1 = objectCall0(numsrc1, GetWidth); isunsignedobj = objectCall0(numobj, IsUnsigned); isunsignedsrc0 = objectCall0(numsrc0, IsUnsigned); isunsignedsrc1 = objectCall0(numsrc1, IsUnsigned); width = widthobj; if (width < widthsrc0) width = widthsrc0; if (width < widthsrc1) width = widthsrc1; // objectCall1(numobj, SetUnsigned, 0); // objectCall1(numsrc0, SetUnsigned, 0); // objectCall1(numsrc1, SetUnsigned, 0); objectCall1(numobj, SetWidth, width); objectCall1(numsrc0, SetWidth, width); objectCall1(numsrc1, SetWidth, width); buflen = (width + CELL_WIDTH - 1) / CELL_WIDTH; for (i = 0; i < buflen; i++) { unsigned int src0value, src1value; objectCall2(numsrc0, GetBits32, i, &src0value); objectCall2(numsrc1, GetBits32, i, &src1value); objectCall2(numobj, SetBits32, i, src0value | src1value); } objectCall1(numobj, SetUnsigned, isunsignedobj); objectCall1(numsrc0, SetUnsigned, isunsignedsrc0); objectCall1(numsrc1, SetUnsigned, isunsignedsrc1); objectCall1(numobj, SetWidth, widthobj); objectCall1(numsrc0, SetWidth, widthsrc0); objectCall1(numsrc1, SetWidth, widthsrc1); objectRelease(numobj); objectRelease(numsrc0); objectRelease(numsrc1); return 0; } static int bigint_bn_Xor(HOBJECT object, HOBJECT src0, HOBJECT src1) { IBigNumber** numobj; IBigNumber** numsrc0; IBigNumber** numsrc1; int widthobj, widthsrc0, widthsrc1, isunsignedobj, isunsignedsrc0, isunsignedsrc1, width; int i, buflen; if (EIID_OK != objectQueryInterface(object, IID_BIGNUMBER, (void**)&numobj)) { return -1; } if (EIID_OK != objectQueryInterface(src0, IID_BIGNUMBER, (void**)&numsrc0)) { objectRelease(numobj); return -1; } if (EIID_OK != objectQueryInterface(src1, IID_BIGNUMBER, (void**)&numsrc1)) { objectRelease(numobj); objectRelease(numsrc0); return -1; } widthobj = objectCall0(numobj, GetWidth); widthsrc0 = objectCall0(numsrc0, GetWidth); widthsrc1 = objectCall0(numsrc1, GetWidth); isunsignedobj = objectCall0(numobj, IsUnsigned); isunsignedsrc0 = objectCall0(numsrc0, IsUnsigned); isunsignedsrc1 = objectCall0(numsrc1, IsUnsigned); width = widthobj; if (width < widthsrc0) width = widthsrc0; if (width < widthsrc1) width = widthsrc1; // objectCall1(numobj, SetUnsigned, 0); // objectCall1(numsrc0, SetUnsigned, 0); // objectCall1(numsrc1, SetUnsigned, 0); objectCall1(numobj, SetWidth, width); objectCall1(numsrc0, SetWidth, width); objectCall1(numsrc1, SetWidth, width); buflen = (width + CELL_WIDTH - 1) / CELL_WIDTH; for (i = 0; i < buflen; i++) { unsigned int src0value, src1value; objectCall2(numsrc0, GetBits32, i, &src0value); objectCall2(numsrc1, GetBits32, i, &src1value); objectCall2(numobj, SetBits32, i, src0value ^ src1value); } objectCall1(numobj, SetUnsigned, isunsignedobj); objectCall1(numsrc0, SetUnsigned, isunsignedsrc0); objectCall1(numsrc1, SetUnsigned, isunsignedsrc1); objectCall1(numobj, SetWidth, widthobj); objectCall1(numsrc0, SetWidth, widthsrc0); objectCall1(numsrc1, SetWidth, widthsrc1); objectRelease(numobj); objectRelease(numsrc0); objectRelease(numsrc1); return 0; } static int bigint_bn_Not(HOBJECT object, HOBJECT src) { IBigNumber** numobj; IBigNumber** numsrc; int widthobj, widthsrc, isunsignedobj, isunsignedsrc, width; int i, buflen; if (EIID_OK != objectQueryInterface(object, IID_BIGNUMBER, (void**)&numobj)) { return -1; } if (EIID_OK != objectQueryInterface(src, IID_BIGNUMBER, (void**)&numsrc)) { objectRelease(numobj); return -1; } widthobj = objectCall0(numobj, GetWidth); widthsrc = objectCall0(numsrc, GetWidth); isunsignedobj = objectCall0(numobj, IsUnsigned); isunsignedsrc = objectCall0(numsrc, IsUnsigned); width = widthobj; if (width < widthsrc) width = widthsrc; // objectCall1(numobj, SetUnsigned, 0); // objectCall1(numsrc, SetUnsigned, 0); objectCall1(numobj, SetWidth, width); objectCall1(numsrc, SetWidth, width); buflen = (width + CELL_WIDTH - 1) / CELL_WIDTH; for (i = 0; i < buflen; i++) { unsigned int srcvalue; objectCall2(numsrc, GetBits32, i, &srcvalue); objectCall2(numobj, SetBits32, i, ~srcvalue); } objectCall1(numobj, SetUnsigned, isunsignedobj); objectCall1(numsrc, SetUnsigned, isunsignedsrc); objectCall1(numobj, SetWidth, widthobj); objectCall1(numsrc, SetWidth, widthsrc); objectRelease(numobj); objectRelease(numsrc); return 0; } static int bigint_bn_uAnd(HOBJECT object, HOBJECT src) { sBigInteger* pobj; IBigNumber** numsrc; IBigNumber** temp; int width; pobj = (sBigInteger*)objectThis(object); if (EIID_OK != objectQueryInterface(src, IID_BIGNUMBER, (void**)&numsrc)) { return -1; } width = objectCall0(numsrc, GetWidth); temp = bigintegerCreate(width); objectCall1(temp, SetUnsigned, 1); objectCall1(temp, Not, src); if (objectCall0(temp, IsZero)) { bigint_bn_AssignUint32(object, 1); } else { bigint_bn_AssignUint32(object, 0); } objectRelease(numsrc); objectRelease(temp); return 0; } static int bigint_bn_uAndNot(HOBJECT object, HOBJECT src) { bigint_bn_uAnd(object, src); if (bigint_bn_IsZero(object)) { bigint_bn_AssignUint32(object, 1); } else { bigint_bn_AssignUint32(object, 0); } return 0; } static int bigint_bn_uOr(HOBJECT object, HOBJECT src) { sBigInteger* pobj; IBigNumber** psrc; pobj = (sBigInteger*)objectThis(object); if (EIID_OK != objectQueryInterface(src, IID_BIGNUMBER, (void**)&psrc)) { return -1; } if (objectCall0(psrc, IsZero)) { bigint_bn_AssignUint32(object, 0); } else { bigint_bn_AssignUint32(object, 1); } objectRelease(psrc); return 0; } static int bigint_bn_uOrNot(HOBJECT object, HOBJECT src) { bigint_bn_uOr(object, src); if (bigint_bn_IsZero(object)) { bigint_bn_AssignUint32(object, 1); } else { bigint_bn_AssignUint32(object, 0); } return 0; } static int bigint_bn_uXor(HOBJECT object, HOBJECT src) { bigint_bn_uAnd(object, src); if (bigint_bn_IsNotZero(object)) { bigint_bn_AssignInt32(object, 0); return 0; } bigint_bn_uOr(object, src); if (bigint_bn_IsZero(object)) { bigint_bn_AssignInt32(object, 0); return 0; } bigint_bn_AssignInt32(object, 1); return 0; } static int bigint_bn_uXorNot(HOBJECT object, HOBJECT src) { bigint_bn_uXor(object, src); if (bigint_bn_IsZero(object)) { bigint_bn_AssignUint32(object, 1); } else { bigint_bn_AssignUint32(object, 0); } return 0; } static int bigint_bn_SHL(HOBJECT object, HOBJECT src, int bits) { sBigInteger* pobj; IBigNumber** psrc; int widthobj, widthsrc; int ifrom, ito, i; unsigned long long current, next; if (bits == 0) { bigint_bn_Assign(object, src); return 0; } if (bits < 0) return bigint_bn_SHR(object, src, -bits); pobj = (sBigInteger*)objectThis(object); if (EIID_OK != objectQueryInterface(src, IID_BIGNUMBER, (void**)&psrc)) { return -1; } widthobj = pobj->width; widthsrc = objectCall0(psrc, GetWidth); if (widthsrc < widthobj) { objectCall1(psrc, SetWidth, widthobj); } else { objectCall1(psrc, SetWidth, widthsrc); } ito = bits / CELL_WIDTH; bits -= ito * CELL_WIDTH; ifrom = 0; for (i = pobj->buflen-1; i>=0; i--) { current = 0; if (i >= ito) { unsigned int srcvalue; objectCall2(psrc, GetBits32, i-ito, &srcvalue); current = srcvalue; current <<= CELL_WIDTH; } if (i >= ito+1) { unsigned int srcvalue; objectCall2(psrc, GetBits32, i - ito - 1, &srcvalue); next = srcvalue; current |= next; } current >>= CELL_WIDTH - bits; pobj->buf[i] = (unsigned int)(current & CELL_MASK); } return 0; } static int bigint_bn_SHR(HOBJECT object, HOBJECT src, int bits) { sBigInteger* pobj; IBigNumber** psrc; unsigned int srcvalue; int widthobj, widthsrc; int bc; int ifrom, ito, i, zerolen; unsigned long long current, next; pobj = (sBigInteger*)objectThis(object); if (bits == 0) { bigint_bn_Assign(object, src); return 0; } if (bits < 0) return bigint_bn_SHL(object, src, -bits); if (EIID_OK != objectQueryInterface(src, IID_BIGNUMBER, (void**)&psrc)) { return -1; } widthobj = pobj->width; widthsrc = objectCall0(psrc, GetWidth); if (widthsrc < widthobj) { objectCall1(psrc, SetWidth, widthobj); } else { objectCall1(psrc, SetWidth, widthsrc); } ito = 0; ifrom = bits / CELL_WIDTH; if (bits >= widthsrc) { for (i = 0;ibuflen;i++) pobj->buf[i] = pobj->isunsigned?0:CELL_MASK; return 0; } bits -= ifrom * CELL_WIDTH; if (ifrom+1 < pobj->buflen) { objectCall2(psrc, GetBits32, ifrom + 1, &srcvalue); current = srcvalue; current <<= CELL_WIDTH; } else { current = 0; } objectCall2(psrc, GetBits32, ifrom, &srcvalue); current |= srcvalue; current >>= bits; for (i = ifrom + 1; i < pobj->buflen-1; i++) { pobj->buf[ito++] = (unsigned int)(current & CELL_MASK); current >>= CELL_WIDTH; objectCall2(psrc, GetBits32, ifrom, &srcvalue); next = srcvalue; next <<= CELL_WIDTH-bits; current |= next; } pobj->buf[ito++] = (unsigned int)(current & CELL_MASK); current >>= CELL_WIDTH; while (ito < pobj->buflen) { pobj->buf[ito++] = current; current >>= CELL_WIDTH; } return 0; } static int bigint_bn_SAL(HOBJECT object, HOBJECT src, int bits) { return bigint_bn_SHL(object, src, bits); } static int bigint_bn_SAR(HOBJECT object, HOBJECT src, int bits) { sBigInteger* pobj; IBigNumber** psrc; unsigned int srcvalue; int widthobj, widthsrc; int bc, sign; int ifrom, ito, i, zerolen; unsigned long long current, next; pobj = (sBigInteger*)objectThis(object); if (bits == 0) { if (object != src) return bigint_bn_Clone(object, src); } if (bits < 0) return bigint_bn_SHL(object, src, -bits); if (EIID_OK != objectQueryInterface(src, IID_BIGNUMBER, (void**)&psrc)) { return -1; } widthobj = pobj->width; widthsrc = objectCall0(psrc, GetWidth); if (widthsrc < widthobj) { objectCall1(psrc, SetWidth, widthobj); } else { objectCall1(psrc, SetWidth, widthsrc); } bc = pobj->width / CELL_WIDTH; objectCall2(psrc, GetBits32, bc, &srcvalue); sign = srcvalue & (1 << ((pobj->width-1) & (CELL_WIDTH - 1))); ito = 0; ifrom = bits / CELL_WIDTH; if (ifrom >= pobj->buflen) { for (i = 0;ibuflen;i++) pobj->buf[i] = sign ? CELL_MASK : 0; return 0; } bits -= ifrom * CELL_WIDTH; if (ifrom + 1 < pobj->buflen) { objectCall2(psrc, GetBits32, ifrom+1, &srcvalue); current = srcvalue; current <<= CELL_WIDTH; } else { current = 0; } objectCall2(psrc, GetBits32, ifrom, &srcvalue); current |= srcvalue; current >>= bits; for (i = ifrom + 1; i < pobj->buflen - 1; i++) { pobj->buf[ito++] = (unsigned int)(current & CELL_MASK); current >>= CELL_WIDTH; objectCall2(psrc, GetBits32, i + 1, &srcvalue); next = srcvalue; next <<= CELL_WIDTH - bits; current |= next; } next = sign ? CELL_MASK : 0; next <<= CELL_WIDTH - bits; current |= next; pobj->buf[ito++] = (unsigned int)(current & CELL_MASK); while (ito < pobj->buflen) pobj->buf[ito++] = sign ? CELL_MASK : 0; return 0; } IBigNumber** bigintegerCreate(int width) { int ret; IBigNumber** bn; PARAMITEM param; A_u_t_o_registor_bigint(); param.name = PARAMID_BIGINTEGERWIDTH; param.i32value = width; ret = objectCreateEx(CLSID_BIGINTEGER, ¶m, 1, IID_BIGNUMBER, (const void**)&bn); return bn; }