/* 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); }
int main(int argc, char *argv[]) { char version_info[80]; int ct; /* declare the M_APM variables ... */ M_APM aa_mapm; M_APM bb_mapm; M_APM cc_mapm; M_APM dd_mapm; if (argc < 2) { m_apm_lib_short_version(version_info); fprintf(stdout, "Usage: primenum number\t\t\t[Version 1.3, MAPM Version %s]\n", version_info); fprintf(stdout, " find the first 10 prime numbers starting with \'number\'\n"); exit(4); } /* now initialize the M_APM variables ... */ aa_mapm = m_apm_init(); bb_mapm = m_apm_init(); cc_mapm = m_apm_init(); dd_mapm = m_apm_init(); init_working_mapm(); m_apm_set_string(dd_mapm, argv[1]); /* * if input < 3, set start point = 3 */ if (m_apm_compare(dd_mapm, MM_Three) == -1) { m_apm_copy(dd_mapm, MM_Three); } /* * make sure we start with an odd integer */ m_apm_integer_divide(aa_mapm, dd_mapm, MM_Two); m_apm_multiply(bb_mapm, MM_Two, aa_mapm); m_apm_add(aa_mapm, MM_One, bb_mapm); ct = 0; while (TRUE) { if (is_number_prime(aa_mapm)) { m_apm_to_integer_string(buffer, aa_mapm); fprintf(stdout,"%s\n",buffer); if (++ct == 10) break; } m_apm_add(cc_mapm, MM_Two, aa_mapm); m_apm_copy(aa_mapm, cc_mapm); } free_working_mapm(); m_apm_free(aa_mapm); m_apm_free(bb_mapm); m_apm_free(cc_mapm); m_apm_free(dd_mapm); m_apm_free_all_mem(); exit(0); }
/* * functions returns TRUE if the M_APM input number is prime * FALSE if it is not */ int is_number_prime(M_APM input) { int ii, ret, index; char sbuf[32]; /* * for reference: * * table size of 2 to filter multiples of 2 and 3 * table size of 8 to filter multiples of 2, 3 and 5 * table size of 480 to filter multiples of 2,3,5,7, and 11 * * this increment table will filter out all numbers * that are multiples of 2,3,5 and 7. */ static char incr_table[48] = { 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4, 2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6, 4, 2, 4, 6, 2, 6, 4, 2, 4, 2, 10, 2, 10 }; /* * since the real algorithm starts at 11 (to syncronize * with the increment table), we will cheat for numbers < 10. */ if (m_apm_compare(input, MM_Ten) <= 0) { m_apm_to_integer_string(sbuf, input); ii = atoi(sbuf); if (ii == 2 || ii == 3 || ii == 5 || ii == 7) return(TRUE); else return(FALSE); } ret = FALSE; index = 0; /* * see if the input number is a * multiple of 3, 5, or 7. */ m_apm_integer_div_rem(M_quot, M_rem, input, MM_Three); if (m_apm_sign(M_rem) == 0) /* remainder == 0 */ return(ret); m_apm_integer_div_rem(M_quot, M_rem, input, MM_Five); if (m_apm_sign(M_rem) == 0) return(ret); m_apm_set_long(M_digit, 7L); m_apm_integer_div_rem(M_quot, M_rem, input, M_digit); if (m_apm_sign(M_rem) == 0) return(ret); ii = m_apm_exponent(input) + 16; m_apm_sqrt(M_tmp1, ii, input); m_apm_add(M_limit, MM_Two, M_tmp1); m_apm_set_long(M_digit, 11L); /* now start at '11' to check */ while (TRUE) { if (m_apm_compare(M_digit, M_limit) >= 0) { ret = TRUE; break; } m_apm_integer_div_rem(M_quot, M_rem, input, M_digit); if (m_apm_sign(M_rem) == 0) /* remainder == 0 */ break; m_apm_set_long(M_tmp1, (long)incr_table[index]); m_apm_add(M_tmp0, M_digit, M_tmp1); m_apm_copy(M_digit, M_tmp0); if (++index == 48) index = 0; } return(ret); }
void m_apm_to_integer_string_mt(char *s, M_APM mtmp) { m_apm_enter(); m_apm_to_integer_string(s,mtmp); m_apm_leave(); }
void MAPM::toIntegerString(char *dest) const { m_apm_to_integer_string(dest,cval()); }
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); }
/* Calculate the POW function by calling EXP : Y A X = e where A = Y * log(X) */ void m_apm_pow(M_APM rr, int places, M_APM xx, M_APM yy) { int iflag, pflag; char sbuf[64]; M_APM tmp8, tmp9; /* if yy == 0, return 1 */ if (yy->m_apm_sign == 0) { m_apm_copy(rr, MM_One); return; } /* if xx == 0, return 0 */ if (xx->m_apm_sign == 0) { M_set_to_zero(rr); return; } if (M_size_flag == 0) /* init locals on first call */ { M_size_flag = M_get_sizeof_int(); M_last_log_digits = 0; M_last_xx_input = m_apm_init(); M_last_xx_log = m_apm_init(); } /* * if 'yy' is a small enough integer, call the more * efficient _integer_pow function. */ if (m_apm_is_integer(yy)) { iflag = FALSE; if (M_size_flag == 2) /* 16 bit compilers */ { if (yy->m_apm_exponent <= 4) iflag = TRUE; } else /* >= 32 bit compilers */ { if (yy->m_apm_exponent <= 7) iflag = TRUE; } if (iflag) { m_apm_to_integer_string(sbuf, yy); m_apm_integer_pow(rr, places, xx, atoi(sbuf)); return; } } tmp8 = M_get_stack_var(); tmp9 = M_get_stack_var(); /* * If parameter 'X' is the same this call as it * was the previous call, re-use the saved log * calculation from last time. */ pflag = FALSE; if (M_last_log_digits >= places) { if (m_apm_compare(xx, M_last_xx_input) == 0) pflag = TRUE; } if (pflag) { m_apm_round(tmp9, (places + 8), M_last_xx_log); } else { m_apm_log(tmp9, (places + 8), xx); M_last_log_digits = places + 2; /* save the 'X' input value and the log calculation */ m_apm_copy(M_last_xx_input, xx); m_apm_copy(M_last_xx_log, tmp9); } m_apm_multiply(tmp8, tmp9, yy); m_apm_exp(rr, places, tmp8); M_restore_stack(2); /* restore the 2 locals we used here */ }