M_APM m_apm_init() { static int firsttime = TRUE; M_APM atmp; if (firsttime) { firsttime = FALSE; M_init_util_data(); M_init_trig_globals(); } if ((atmp = MAPM_MALLOC(sizeof(struct M_APM_struct))) == NULL) { fprintf(stderr,"\'m_apm_init\', Out of memory\n"); exit(4); } atmp->m_apm_id = M_APM_IDENT; atmp->m_apm_malloclength = 80; atmp->m_apm_datalength = 1; atmp->m_apm_exponent = 0; atmp->m_apm_sign = 0; if ((atmp->m_apm_data = (UCHAR *)MAPM_MALLOC(84)) == NULL) { fprintf(stderr,"\'m_apm_init\', Out of memory\n"); exit(6); } atmp->m_apm_data[0] = 0; return(atmp); }
/* compute int *n = round_to_nearest_int(a / log(2)) M_APM b = MAPM version of *n returns 0: OK -1, 1: failure */ int M_exp_compute_nn(int *n, M_APM b, M_APM a) { M_APM tmp0, tmp1; void *vp; char *cp, sbuf[48]; int kk; *n = 0; vp = NULL; cp = sbuf; tmp0 = M_get_stack_var(); tmp1 = M_get_stack_var(); /* find 'n' and convert it to a normal C int */ /* we just need an approx 1/log(2) for this calculation */ m_apm_multiply(tmp1, a, MM_exp_log2R); /* round to the nearest int */ if (tmp1->m_apm_sign >= 0) { m_apm_add(tmp0, tmp1, MM_0_5); m_apm_floor(tmp1, tmp0); } else { m_apm_subtract(tmp0, tmp1, MM_0_5); m_apm_ceil(tmp1, tmp0); } kk = tmp1->m_apm_exponent; if (kk >= 42) { if ((vp = (void *)MAPM_MALLOC((kk + 16) * sizeof(char))) == NULL) { /* fatal, this does not return */ M_apm_log_error_msg(M_APM_FATAL, "\'M_exp_compute_nn\', Out of memory"); } cp = (char *)vp; } m_apm_to_integer_string(cp, tmp1); *n = atoi(cp); m_apm_set_long(b, (long)(*n)); kk = m_apm_compare(b, tmp1); if (vp != NULL) MAPM_FREE(vp); M_restore_stack(2); return(kk); }
void m_apm_to_integer_string(char *s, M_APM mtmp) { void *vp; UCHAR *ucp, numdiv, numrem; char *cp, *p, sbuf[128]; int ct, dl, numb, ii; vp = NULL; ct = mtmp->m_apm_exponent; dl = mtmp->m_apm_datalength; /* * if |input| < 1, result is "0" */ if (ct <= 0 || mtmp->m_apm_sign == 0) { s[0] = '0'; s[1] = '\0'; return; } if (ct > 112) { if ((vp = (void *)MAPM_MALLOC((ct + 32) * sizeof(char))) == NULL) { /* fatal, this does not return */ M_apm_log_error_msg(M_APM_FATAL, "\'m_apm_to_integer_string\', Out of memory"); } cp = (char *)vp; } else { cp = sbuf; } p = cp; ii = 0; /* handle a negative number */ if (mtmp->m_apm_sign == -1) { ii = 1; *p++ = '-'; } /* get num-bytes of data (#digits / 2) to use in the string */ if (ct > dl) numb = (dl + 1) >> 1; else
int M_get_stack_ptr(int sz) { int i, k; UCHAR *cp; k = ++M_mul_stack_ptr; /* if size is 0, just need to malloc and return */ if (mul_stack_data_size[k] == 0) { if ((i = sz) < 16) i = 16; if ((cp = (UCHAR *)MAPM_MALLOC(i + 4)) == NULL) { /* fatal, this does not return */ M_apm_log_error_msg(M_APM_FATAL, M_stack_ptr_error_msg); } mul_stack_data[k] = cp; mul_stack_data_size[k] = i; } else /* it has been malloc'ed, see if it's big enough */ { if (sz > mul_stack_data_size[k]) { cp = mul_stack_data[k]; if ((cp = (UCHAR *)MAPM_REALLOC(cp, (sz + 4))) == NULL) { /* fatal, this does not return */ M_apm_log_error_msg(M_APM_FATAL, M_stack_ptr_error_msg); } mul_stack_data[k] = cp; mul_stack_data_size[k] = sz; } } return(k); }
char *m_apm_to_fixpt_stringexp(int dplaces, M_APM atmp, char ch_radx, char ch_sep, int ct_sep) { int places, xp, dl, ii; char *cpr; places = dplaces; dl = atmp->m_apm_datalength; xp = atmp->m_apm_exponent; if (places < 0) /* show ALL digits */ { if (xp < 0) ii = dl - xp; else { if (dl > xp) ii = dl; else ii = xp; } } else { ii = places; if (xp > 0) ii += xp; } if (ct_sep != 0 && ch_sep != 0 && xp > 0) ii += xp / ct_sep; if ((cpr = (char *)MAPM_MALLOC((ii + 32) * sizeof(char))) == NULL) return(NULL); m_apm_to_fixpt_stringex(cpr,places,atmp,ch_radx,ch_sep,ct_sep); return(cpr); }
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); } }
void m_apm_to_fixpt_string(char *ss, int dplaces, M_APM mtmp) { M_APM ctmp; void *vp; int places, i2, ii, jj, kk, xp, dl, numb; UCHAR *ucp, numdiv, numrem; char *cpw, *cpd, sbuf[128]; ctmp = M_get_stack_var(); vp = NULL; cpd = ss; places = dplaces; /* just want integer portion if places == 0 */ if (places == 0) { if (mtmp->m_apm_sign >= 0) m_apm_add(ctmp, mtmp, MM_0_5); else m_apm_subtract(ctmp, mtmp, MM_0_5); m_apm_to_integer_string(cpd, ctmp); M_restore_stack(1); return; } if (places > 0) M_apm_round_fixpt(ctmp, places, mtmp); else m_apm_copy(ctmp, mtmp); /* show ALL digits */ if (ctmp->m_apm_sign == 0) /* result is 0 */ { if (places < 0) { cpd[0] = '0'; /* "0.0" */ cpd[1] = '.'; cpd[2] = '0'; cpd[3] = '\0'; } else { memset(cpd, '0', (places + 2)); /* pre-load string with all '0' */ cpd[1] = '.'; cpd[places + 2] = '\0'; } M_restore_stack(1); return; } xp = ctmp->m_apm_exponent; dl = ctmp->m_apm_datalength; numb = (dl + 1) >> 1; if (places < 0) { if (dl > xp) jj = dl + 16; else jj = xp + 16; } else { jj = places + 16; if (xp > 0) jj += xp; } if (jj > 112) { if ((vp = (void *)MAPM_MALLOC((jj + 16) * sizeof(char))) == NULL) { /* fatal, this does not return */ M_apm_log_error_msg(M_APM_FATAL, "\'m_apm_to_fixpt_string\', Out of memory"); } cpw = (char *)vp; } else { cpw = sbuf; } /* * at this point, the number is non-zero and the the output * string will contain at least 1 significant digit. */ if (ctmp->m_apm_sign == -1) /* negative number */ { *cpd++ = '-'; } ucp = ctmp->m_apm_data; ii = 0; /* convert MAPM num to ASCII digits and store in working char array */ while (TRUE) { M_get_div_rem_10((int)(*ucp++), &numdiv, &numrem); cpw[ii++] = numdiv + '0'; cpw[ii++] = numrem + '0'; if (--numb == 0) break; } i2 = ii; /* save for later */ if (places < 0) /* show ALL digits */ { places = dl - xp; if (places < 1) places = 1; } /* pad with trailing zeros if needed */ kk = xp + places + 2 - ii; if (kk > 0) memset(&cpw[ii], '0', kk); if (xp > 0) /* |num| >= 1, NO lead-in "0.nnn" */ { ii = xp + places + 1; jj = 0; for (kk=0; kk < ii; kk++) { if (kk == xp) cpd[jj++] = '.'; cpd[jj++] = cpw[kk]; } cpd[ii] = '\0'; } else /* |num| < 1, have lead-in "0.nnn" */ { jj = 2 - xp; ii = 2 + places; memset(cpd, '0', (ii + 1)); /* pre-load string with all '0' */ cpd[1] = '.'; /* assign decimal point */ for (kk=0; kk < i2; kk++) { cpd[jj++] = cpw[kk]; } cpd[ii] = '\0'; } if (vp != NULL) MAPM_FREE(vp); M_restore_stack(1); }
void m_apm_to_fixpt_stringex(char *s, int dplaces, M_APM atmp, char ch_radix, char ch_sep, int count_sep) { M_APM btmp; char ch, *cpd, *cps; int ii, jj, kk, ct, dl, xp, no_sep_flg, places; btmp = M_get_stack_var(); places = dplaces; cpd = s; no_sep_flg = FALSE; m_apm_absolute_value(btmp, atmp); /* do conversion of positive number */ if (ch_sep == 0 || count_sep == 0) /* no separator char OR count */ no_sep_flg = TRUE; /* determine how much memory to get for the temp string */ dl = btmp->m_apm_datalength; xp = btmp->m_apm_exponent; if (places < 0) /* show ALL digits */ { if (xp < 0) ii = dl - xp; else { if (dl > xp) ii = dl; else ii = xp; } } else { ii = places; if (xp > 0) ii += xp; } if ((cps = (char *)MAPM_MALLOC((ii + 32) * sizeof(char))) == NULL) { /* fatal, this does not return */ M_apm_log_error_msg(M_APM_FATAL, "\'m_apm_to_fixpt_stringex\', Out of memory"); } m_apm_to_fixpt_string(cps, places, btmp); /* * the converted string may be all 'zero', 0.0000... * if so and the original number is negative, * do NOT set the '-' sign of our output string. */ if (atmp->m_apm_sign == -1) /* if input number negative */ { kk = 0; jj = 0; while (TRUE) { ch = cps[kk++]; if ((ch == '\0') || (jj != 0)) break; if (isdigit((int)ch)) { if (ch != '0') jj = 1; } } if (jj) *cpd++ = '-'; } ct = M_strposition(cps, "."); /* find the default (.) radix char */ if (ct == -1) /* if not found .. */ { strcat(cps, "."); /* add one */ ct = M_strposition(cps, "."); /* and then find it */ } if (places == 0) /* int format, terminate at radix char */ cps[ct] = '\0'; else cps[ct] = ch_radix; /* assign the radix char */ /* * if the number is small enough to not have any separator char's ... */ if (ct <= count_sep) no_sep_flg = TRUE; if (no_sep_flg) { strcpy(cpd, cps); } else { jj = 0; kk = count_sep; ii = ct / count_sep; if ((ii = ct - ii * count_sep) == 0) ii = count_sep; while (TRUE) /* write out the first 1,2 */ { /* (up to count_sep) digits */ *cpd++ = cps[jj++]; if (--ii == 0) break; } while (TRUE) /* write rest of the string */ { if (kk == count_sep) /* write a new separator char */ { if (jj != ct) /* unless we're at the radix */ { *cpd++ = ch_sep; /* note that this also disables */ kk = 0; /* the separator char AFTER */ } /* the radix char */ } if ((*cpd++ = cps[jj++]) == '\0') break; kk++; } } MAPM_FREE(cps); M_restore_stack(1); }