Very wide multiplication (Anthony Bybell)

This commit is contained in:
steve 2001-10-14 16:36:43 +00:00
parent 9dbcb32808
commit cfbad49d33
2 changed files with 136 additions and 5 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: arith.cc,v 1.11 2001/07/13 00:38:57 steve Exp $"
#ident "$Id: arith.cc,v 1.12 2001/10/14 16:36:43 steve Exp $"
#endif
# include "arith.h"
@ -56,8 +56,7 @@ vvp_arith_mult::vvp_arith_mult(vvp_ipoint_t b, unsigned w)
void vvp_arith_mult::set(vvp_ipoint_t i, functor_t f, bool push)
{
assert(wid_ <= 8*sizeof(unsigned long));
if(wid_ <= 8*sizeof(unsigned long)) {
unsigned long a = 0, b = 0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
@ -96,6 +95,72 @@ void vvp_arith_mult::set(vvp_ipoint_t i, functor_t f, bool push)
else
schedule_functor(ptr, 0);
}
} else { /* long form only used if > machine length long */
unsigned char *a, *b, *sum;
a = new unsigned char[wid_];
b = new unsigned char[wid_];
sum = new unsigned char[wid_];
int mxa = -1;
int mxb = -1;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
functor_t obj = functor_index(ptr);
unsigned ival = obj->ival;
if (ival & 0xaa) {
output_x_(push);
delete[]sum;
delete[]b;
delete[]a;
return;
}
if((a[idx] = ((ival & 0x01) != 0))) mxa=idx;
if((b[idx] = ((ival & 0x04) != 0))) mxb=idx;
sum[idx] = 0;
}
// do "unsigned ZZ sum = a * b" the hard way..
for(int i=0;i<=mxb;i++)
{
if(b[i])
{
unsigned char carry=0;
unsigned char temp;
for(int j=0;j<=mxa;j++)
{
if(i+j>=(int)wid_) break;
temp=sum[i+j]+a[j]+carry;
sum[i+j]=(temp&1);
carry=(temp>>1);
}
}
}
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
functor_t obj = functor_index(ptr);
unsigned oval = sum[idx];
if (obj->oval == oval)
continue;
obj->oval = oval;
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
}
delete[]sum;
delete[]b;
delete[]a;
}
}
vvp_arith_sum::vvp_arith_sum(vvp_ipoint_t b, unsigned w)
@ -509,6 +574,9 @@ void vvp_shiftr::set(vvp_ipoint_t i, functor_t f, bool push)
/*
* $Log: arith.cc,v $
* Revision 1.12 2001/10/14 16:36:43 steve
* Very wide multiplication (Anthony Bybell)
*
* Revision 1.11 2001/07/13 00:38:57 steve
* Remove width restriction on subtraction.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vthread.cc,v 1.55 2001/09/15 18:27:05 steve Exp $"
#ident "$Id: vthread.cc,v 1.56 2001/10/14 16:36:43 steve Exp $"
#endif
# include "vthread.h"
@ -917,7 +917,7 @@ bool of_MOV(vthread_t thr, vvp_code_t cp)
bool of_MUL(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
assert(cp->number <= 8*sizeof(unsigned long));
if(cp->number <= 8*sizeof(unsigned long)) {
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
@ -946,6 +946,66 @@ bool of_MUL(vthread_t thr, vvp_code_t cp)
}
return true;
} else {
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned char *a, *b, *sum;
a = new unsigned char[cp->number];
b = new unsigned char[cp->number];
sum = new unsigned char[cp->number];
int mxa = -1;
int mxb = -1;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lb = thr_get_bit(thr, idx1);
unsigned rb = thr_get_bit(thr, idx2);
if ((lb | rb) & 2)
{
delete[]sum;
delete[]b;
delete[]a;
goto x_out;
}
if((a[idx] = lb)) mxa=idx;
if((b[idx] = rb)) mxb=idx;
sum[idx]=0;
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
// do "unsigned ZZ sum = a * b" the hard way..
for(int i=0;i<=mxb;i++)
{
if(b[i])
{
unsigned char carry=0;
unsigned char temp;
for(int j=0;j<=mxa;j++)
{
if(i+j>=(int)cp->number) break;
temp=sum[i+j]+a[j]+carry;
sum[i+j]=(temp&1);
carry=(temp>>1);
}
}
}
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx1+idx, sum[idx]);
}
delete[]sum;
delete[]b;
delete[]a;
return true;
}
x_out:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
@ -1356,6 +1416,9 @@ bool of_ZOMBIE(vthread_t thr, vvp_code_t)
/*
* $Log: vthread.cc,v $
* Revision 1.56 2001/10/14 16:36:43 steve
* Very wide multiplication (Anthony Bybell)
*
* Revision 1.55 2001/09/15 18:27:05 steve
* Make configure detect malloc.h
*