void M_4_byte_multiply(UCHAR *r, UCHAR *a, UCHAR *b) { int b0, jj; UCHAR *cp1, *cp2, numdiv, numrem; memset(r, 0, 8); /* zero out 8 byte result */ jj = 3; /* loop for one number [b], un-roll the inner 'loop' [a] */ while (1) { b0 = (int)b[jj]; cp1 = r + (3 + jj); cp2 = cp1 + 1; M_get_div_rem((b0 * a[3]), &numdiv, &numrem); *cp2 += numrem; *cp1 += numdiv; if (*cp2 >= 100) { *cp2 -= 100; *cp1 += 1; } cp1--; cp2--; if (*cp2 >= 100) { *cp2 -= 100; *cp1 += 1; } M_get_div_rem((b0 * a[2]), &numdiv, &numrem); *cp2 += numrem; *cp1 += numdiv; if (*cp2 >= 100) { *cp2 -= 100; *cp1 += 1; } cp1--; cp2--; if (*cp2 >= 100) { *cp2 -= 100; *cp1 += 1; } M_get_div_rem((b0 * a[1]), &numdiv, &numrem); *cp2 += numrem; *cp1 += numdiv; if (*cp2 >= 100) { *cp2 -= 100; *cp1 += 1; } cp1--; cp2--; if (*cp2 >= 100) { *cp2 -= 100; *cp1 += 1; } M_get_div_rem((b0 * a[0]), &numdiv, &numrem); *cp2 += numrem; *cp1 += numdiv; if (*cp2 >= 100) { *cp2 -= 100; *cp1 += 1; } if (jj-- == 0) break; } }
void M_fast_mul_fft(UCHAR *ww, UCHAR *uu, UCHAR *vv, int nbytes) { int mflag, i, j, nn2, nn; double carry, nnr, dtemp, *a, *b; UCHAR *w0; unsigned long ul; if (M_size < 0) /* if first time in, setup working arrays */ { if (M_get_sizeof_int() == 2) /* if still using 16 bit compilers */ M_size = 1030; else M_size = 8200; M_aa_array = (double *)MAPM_MALLOC(M_size * sizeof(double)); M_bb_array = (double *)MAPM_MALLOC(M_size * sizeof(double)); if ((M_aa_array == NULL) || (M_bb_array == NULL)) { /* fatal, this does not return */ M_apm_log_error_msg(M_APM_EXIT, "\'M_fast_mul_fft\', Out of memory"); } } nn = nbytes; nn2 = nbytes >> 1; if (nn > M_size) { mflag = TRUE; a = (double *)MAPM_MALLOC((nn + 8) * sizeof(double)); b = (double *)MAPM_MALLOC((nn + 8) * sizeof(double)); if ((a == NULL) || (b == NULL)) { /* fatal, this does not return */ M_apm_log_error_msg(M_APM_EXIT, "\'M_fast_mul_fft\', Out of memory"); } } else { mflag = FALSE; a = M_aa_array; b = M_bb_array; } /* * convert normal base 100 MAPM numbers to base 10000 * for the FFT operation. */ i = 0; for (j=0; j < nn2; j++) { a[j] = (double)((int)uu[i] * 100 + uu[i+1]); b[j] = (double)((int)vv[i] * 100 + vv[i+1]); i += 2; } /* zero fill the second half of the arrays */ for (j=nn2; j < nn; j++) { a[j] = 0.0; b[j] = 0.0; } /* perform the forward Fourier transforms for both numbers */ M_rdft(nn, 1, a); M_rdft(nn, 1, b); /* perform the convolution ... */ b[0] *= a[0]; b[1] *= a[1]; for (j=3; j <= nn; j += 2) { dtemp = b[j-1]; b[j-1] = dtemp * a[j-1] - b[j] * a[j]; b[j] = dtemp * a[j] + b[j] * a[j-1]; } /* perform the inverse transform on the result */ M_rdft(nn, -1, b); /* perform a final pass to release all the carries */ /* we are still in base 10000 at this point */ carry = 0.0; j = nn; nnr = 2.0 / (double)nn; while (1) { dtemp = b[--j] * nnr + carry + 0.5; ul = (unsigned long)(dtemp * 1.0E-4); carry = (double)ul; b[j] = dtemp - carry * 10000.0; if (j == 0) break; } /* copy result to our destination after converting back to base 100 */ w0 = ww; M_get_div_rem((int)ul, w0, (w0 + 1)); for (j=0; j <= (nn - 2); j++) { w0 += 2; M_get_div_rem((int)b[j], w0, (w0 + 1)); } if (mflag) { MAPM_FREE(b); MAPM_FREE(a); } }