Index: Objects/longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.117 diff -c -r1.117 longobject.c *** Objects/longobject.c 23 Apr 2002 20:01:20 -0000 1.117 --- Objects/longobject.c 25 May 2002 00:48:28 -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); *************** *** 1520,1525 **** --- 1497,1641 ---- carry >>= SHIFT; } } + return z; + } + + /* Karatsuba Multiplication (with two helper functions) */ + /* Fast digit split for k_mul */ + static int + kmul_split(PyLongObject *n, PyLongObject **high, PyLongObject **low, long size) + { + PyLongObject *h, *l; + long i, size_n=ABS(n->ob_size); + + if (!(h=_PyLong_New(size_n-size))) return 0; + if (!(l=_PyLong_New(size))) { + Py_DECREF(h); + return 0; + } + + for(i=0; iob_digit[i]=n->ob_digit[i]; + for(i=size; iob_digit[i-size]=n->ob_digit[i]; + *high = h; + *low = l; + return 1; + } + + /* Fast digit join for k_mul */ + static PyLongObject * + kmul_join(PyLongObject *a, PyLongObject *b, PyLongObject *c, long size) + { + PyLongObject *ret=_PyLong_New((size*2)+(a->ob_size)+1); + long i; + digit carry=0; + + 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; + + for(i=0; i < b->ob_size; i++) { + carry += ret->ob_digit[i+size] + b->ob_digit[i]; + ret->ob_digit[i+size] = carry & MASK; + carry >>= SHIFT; + } + while(carry) { + carry += ret->ob_digit[i+size]; + ret->ob_digit[i+size] = carry & MASK; + carry >>= SHIFT; + i++; + } + + for(i=0; i < a->ob_size; i++) { + carry += ret->ob_digit[i+(size*2)] + a->ob_digit[i]; + ret->ob_digit[i+(size*2)] = carry & MASK; + carry >>= SHIFT; + } + for(; carry && i+(size*2) < ret->ob_size; i++) { + carry += ret->ob_digit[i+(size*2)]; + ret->ob_digit[i+(size*2)] = carry & MASK; + carry >>= SHIFT; + } + ret->ob_digit[i+(size*2)]=carry; + + return long_normalize(ret); + } + + /* Karatsuba multiplication */ + 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 smaller number */ + if(ABS(a->ob_size)>ABS(b->ob_size)) { + PyLongObject *hold_a=a; + a=b; + b=hold_a; + } + s=ABS(a->ob_size)/2; + + if(s<=20) return x_mul(a, b); /* Just do gradeschool math if + either number is smaller than + 40 digits */ + + if(!(kmul_split(a, &ah, &al, s))) goto onError; + if(!(kmul_split(b, &bh, &bl, s))) goto onError; + + if(!(asum=x_add(ah, al))) goto onError; + if(!(bsum=x_add(bh, bl))) goto onError; + if(!(z=k_mul(al, bl))) goto onError; + Py_DECREF(al); Py_DECREF(bl); + al=bl=NULL; + if(!(x=k_mul(ah, bh))) goto onError; + Py_DECREF(ah); Py_DECREF(bh); + ah=bh=NULL; + if(!(y=k_mul(asum, bsum))) goto onError; + Py_DECREF(asum); Py_DECREF(bsum); + asum=bsum=NULL; + + if(!(t=x_sub(y, x))) goto onError; + Py_DECREF(y); + if(!(y=x_sub(t, z))) goto onError; + + ret = kmul_join(x, y, z, s); + + onError: + Py_XDECREF(ah); Py_XDECREF(al); Py_XDECREF(bh); Py_XDECREF(bl); + Py_XDECREF(asum); Py_XDECREF(bsum); + Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(z); + Py_XDECREF(t); + return ret; + } + + + static PyObject * + long_mul(PyLongObject *v, PyLongObject *w) + { + PyLongObject *a, *b, *z; + + 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; + } + + 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); if (b->ob_size < 0)