Index: Objects/longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.118 diff -c -r1.118 longobject.c *** Objects/longobject.c 13 Jun 2002 20:33:01 -0000 1.118 --- Objects/longobject.c 9 Jul 2002 22:35:10 -0000 *************** *** 1457,1495 **** return (*v->ob_type->tp_as_sequence->sq_repeat)(v, n); } ! static PyObject * ! long_mul(PyLongObject *v, PyLongObject *w) { ! PyLongObject *a, *b, *z; ! int size_a; ! int size_b; int i; ! ! if (!convert_binop((PyObject *)v, (PyObject *)w, &a, &b)) { ! if (!PyLong_Check(v) && ! v->ob_type->tp_as_sequence && ! v->ob_type->tp_as_sequence->sq_repeat) ! return long_repeat((PyObject *)v, w); ! if (!PyLong_Check(w) && ! w->ob_type->tp_as_sequence && ! w->ob_type->tp_as_sequence->sq_repeat) ! return long_repeat((PyObject *)w, v); ! Py_INCREF(Py_NotImplemented); ! return Py_NotImplemented; ! } ! ! size_a = ABS(a->ob_size); ! size_b = ABS(b->ob_size); ! if (size_a > size_b) { ! /* we are faster with the small object on the left */ ! int hold_sa = size_a; ! PyLongObject *hold_a = a; ! size_a = size_b; ! size_b = hold_sa; ! a = b; ! b = hold_a; ! } ! z = _PyLong_New(size_a + size_b); if (z == NULL) { Py_DECREF(a); Py_DECREF(b); --- 1457,1472 ---- return (*v->ob_type->tp_as_sequence->sq_repeat)(v, n); } ! /* Gradeschool multiplication */ ! static PyLongObject * ! x_mul(PyLongObject *a, PyLongObject *b) { ! PyLongObject *z; ! int size_a=ABS(a->ob_size); ! int size_b=ABS(b->ob_size); int i; ! ! z = _PyLong_New(size_a + size_b); if (z == NULL) { Py_DECREF(a); Py_DECREF(b); *************** *** 1519,1524 **** --- 1496,1654 ---- z->ob_digit[i+j] = (digit) (carry & MASK); carry >>= SHIFT; } + } + return z; + } + + /* Takes a long "n" and an integer "size" representing the place to + split and sets low and high such that abs(n) = (high<ob_size); + int size_l, size_h; + + if(size_n>size) { + size_l=size; + size_h=size_n-size; + } + else { + size_l=size_n; + size_h=0; + } + + if (!(h=_PyLong_New(size_h))) return 0; + if (!(l=_PyLong_New(size_l))) { + Py_DECREF(h); + return 0; + } + + for(i=0; iob_digit[i]=n->ob_digit[i]; + for(; iob_digit[i-size]=n->ob_digit[i]; + *high = h; + *low = l; + return 1; + } + + /* Given a, b, c, and size, returns a<<(2*size)+b<ob_size)+1); + int i, j; + digit carry=0; + + /* set ret = c */ + for(i=0; i < c->ob_size; i++) ret->ob_digit[i]=c->ob_digit[i]; + for(; iob_size; i++) ret->ob_digit[i]=0; + + /* ret += b<ob_size; i++, j++) { + carry += ret->ob_digit[j] + b->ob_digit[i]; + ret->ob_digit[j] = carry & MASK; + carry >>= SHIFT; + } + for(; carry; j++) { + carry += ret->ob_digit[j]; + ret->ob_digit[j] = carry & MASK; + carry >>= SHIFT; + } + + /* ret += a<ob_size; i++, j++) { + carry += ret->ob_digit[j] + a->ob_digit[i]; + ret->ob_digit[j] = carry & MASK; + carry >>= SHIFT; + } + for(; carry && j < ret->ob_size; j++) { + carry += ret->ob_digit[j]; + ret->ob_digit[j] = carry & MASK; + carry >>= SHIFT; + } + ret->ob_digit[j]=carry; + + return long_normalize(ret); + } + + /* Karatsuba multiplication + See Knuth Vol. 2 Chapter 4.3.3 (Pp. 294-295) */ + static PyLongObject * + k_mul(PyLongObject *a, PyLongObject *b) + { + PyLongObject *ah, *al, *bh, *bl; + PyLongObject *asum, *bsum; + PyLongObject *x, *y, *z, *ret; + PyLongObject *t; + int s; + + ah=al=bh=bl=asum=bsum=x=y=z=t=ret=NULL; + + /* We want to split based on the larger number */ + if(ABS(a->ob_size)>ABS(b->ob_size)) { + PyLongObject *hold_a=a; + a=b; + b=hold_a; + } + s=ABS(b->ob_size)/2; + + /* use gradeschool math when either number is smaller than 35 digits */ + if(ABS(a->ob_size)<=35) return x_mul(a, b); + + if(!(kmul_split(a, s, &ah, &al))) goto onError; + if(!(kmul_split(b, s, &bh, &bl))) goto onError; + + /* z=al*bl */ + if(!(z=k_mul(al, bl))) goto onError; + + /* x=ah*bh */ + if(!(x=k_mul(ah, bh))) goto onError; + + /* y=ah*bl+bh*al + =((ah+al)*(bh+bl))-x-z */ + if(!(asum=x_add(ah, al))) goto onError; + if(!(bsum=x_add(bh, bl))) goto onError; + if(!(y=k_mul(asum, bsum))) goto onError; + if(!(t=x_sub(y, x))) goto onError; + Py_DECREF(y); + if(!(y=x_sub(t, z))) goto onError; + + /* ret = x<<(2s)+y<ob_type->tp_as_sequence && + v->ob_type->tp_as_sequence->sq_repeat) + return long_repeat((PyObject *)v, w); + if (!PyLong_Check(w) && + w->ob_type->tp_as_sequence && + w->ob_type->tp_as_sequence->sq_repeat) + return long_repeat((PyObject *)w, v); + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + if(!(z = k_mul(a, b))) { + Py_DECREF(a); + Py_DECREF(b); + return NULL; } if (a->ob_size < 0) z->ob_size = -(z->ob_size);