Files
calc/zfunc.c
Landon Curt Noll ff90bc0e3a add E_STRING to error, errno, strerror, change multiple E_STRING's
While help/errstr has been added, the errstr builtin function is
not yet written.  In anticipation of the new errstr builtin the
rest of the calc error system has been updated to associated errsym
E_STRING's with errnum error codes and errmsg error messages.

Minor improvements to help/rand.

The verify_error_table() function that does a verification
the error_table[] array and setup private_error_alias[] array
is now called by libcalc_call_me_first().

Fix comment about wrong include file in have_sys_mount.h.

Removed unused booltostr() and strtobool() macros from bool.h.

Moved define of math_error(char *, ...) from zmath.h to errtbl.h.
The errtbl.h include file, unless ERRCODE_SRC is defined
also includes attribute.h and errsym.h.

Group calc error related builtin support functions together in func.c.

Make switch indenting in func.c consistent.

Passing an invalid argument to error(), errno() or strerror() will
set errno AND throw a math error.  Before errno would be set and
an error value was returned.  Before there was no way to tell if
the error value was a result of the arg or if an error detected.

Added E_STRING to error([errnum | "E_STRING"]) builtin function.
Added E_STRING to errno([errnum | "E_STRING"]) builtin function.
Added E_STRING to strerror([errnum | "E_STRING"]) builtin function.
Calling these functions with an E_STRING errsym is the same as calling
them with the matching errnum code.

Standardized on calc computation error related E_STRING strings
where there are a set of related codes.  Changed "E_...digits" into
"E_..._digits".  For example, E_FPUTC1 became E_FPUTC_1, E_FPUTC2
became E_FPUTC_2, and E_FPUTC3 became E_FPUTC_3.  In a few cases
such as E_APPR became E_APPR_1, because there was a E_APPR2 (which
became E_APPR_2) and E_APPR3 (which became E_APPR_3).  To other
special cases, E_ILOG10 became E_IBASE10_LOG and E_ILOG2 became
E_IBASE2_LOG because E_ILOG10 and E_ILOG2 are both independent calc
computation error related E_STRING strings.  Now related sets of
E_STRING strings end in _ (underscore) followed by digits.

The following is the list of E_STRING strings changes:

    E_APPR ==> E_APPR_1
    E_ROUND ==> E_ROUND_1
    E_SQRT ==> E_SQRT_1
    E_ROOT ==> E_ROOT_1
    E_SHIFT ==> E_SHIFT_1
    E_SCALE ==> E_SCALE_1
    E_POWI ==> E_POWI_1
    E_POWER ==> E_POWER_1
    E_QUO ==> E_QUO_1
    E_MOD ==> E_MOD_1
    E_ABS ==> E_ABS_1
    E_APPR2 ==> E_APPR_2
    E_APPR3 ==> E_APPR_3
    E_ROUND2 ==> E_ROUND_2
    E_ROUND3 ==> E_ROUND_3
    E_BROUND2 ==> E_BROUND_2
    E_BROUND3 ==> E_BROUND_3
    E_SQRT2 ==> E_SQRT_2
    E_SQRT3 ==> E_SQRT_3
    E_ROOT2 ==> E_ROOT_2
    E_ROOT3 ==> E_ROOT_3
    E_SHIFT2 ==> E_SHIFT_2
    E_SCALE2 ==> E_SCALE_2
    E_POWI2 ==> E_POWI_2
    E_POWER2 ==> E_POWER_2
    E_POWER3 ==> E_POWER_3
    E_QUO2 ==> E_QUO_2
    E_QUO3 ==> E_QUO_3
    E_MOD2 ==> E_MOD_2
    E_MOD3 ==> E_MOD_3
    E_ABS2 ==> E_ABS_2
    E_EXP1 ==> E_EXP_1
    E_EXP2 ==> E_EXP_2
    E_FPUTC1 ==> E_FPUTC_1
    E_FPUTC2 ==> E_FPUTC_2
    E_FPUTC3 ==> E_FPUTC_3
    E_FGETC1 ==> E_FGETC_1
    E_FGETC2 ==> E_FGETC_2
    E_FOPEN1 ==> E_FOPEN_1
    E_FOPEN2 ==> E_FOPEN_2
    E_FREOPEN1 ==> E_FREOPEN_1
    E_FREOPEN2 ==> E_FREOPEN_2
    E_FREOPEN3 ==> E_FREOPEN_3
    E_FCLOSE1 ==> E_FCLOSE_1
    E_FPUTS1 ==> E_FPUTS_1
    E_FPUTS2 ==> E_FPUTS_2
    E_FPUTS3 ==> E_FPUTS_3
    E_FGETS1 ==> E_FGETS_1
    E_FGETS2 ==> E_FGETS_2
    E_FPUTSTR1 ==> E_FPUTSTR_1
    E_FPUTSTR2 ==> E_FPUTSTR_2
    E_FPUTSTR3 ==> E_FPUTSTR_3
    E_FGETSTR1 ==> E_FGETSTR_1
    E_FGETSTR2 ==> E_FGETSTR_2
    E_FGETLINE1 ==> E_FGETLINE_1
    E_FGETLINE2 ==> E_FGETLINE_2
    E_FGETFIELD1 ==> E_FGETFIELD_1
    E_FGETFIELD2 ==> E_FGETFIELD_2
    E_REWIND1 ==> E_REWIND_1
    E_PRINTF1 ==> E_PRINTF_1
    E_PRINTF2 ==> E_PRINTF_2
    E_FPRINTF1 ==> E_FPRINTF_1
    E_FPRINTF2 ==> E_FPRINTF_2
    E_FPRINTF3 ==> E_FPRINTF_3
    E_STRPRINTF1 ==> E_STRPRINTF_1
    E_STRPRINTF2 ==> E_STRPRINTF_2
    E_FSCAN1 ==> E_FSCAN_1
    E_FSCAN2 ==> E_FSCAN_2
    E_FSCANF1 ==> E_FSCANF_1
    E_FSCANF2 ==> E_FSCANF_2
    E_FSCANF3 ==> E_FSCANF_3
    E_FSCANF4 ==> E_FSCANF_4
    E_STRSCANF1 ==> E_STRSCANF_1
    E_STRSCANF2 ==> E_STRSCANF_2
    E_STRSCANF3 ==> E_STRSCANF_3
    E_STRSCANF4 ==> E_STRSCANF_4
    E_SCANF1 ==> E_SCANF_1
    E_SCANF2 ==> E_SCANF_2
    E_SCANF3 ==> E_SCANF_3
    E_FTELL1 ==> E_FTELL_1
    E_FTELL2 ==> E_FTELL_2
    E_FSEEK1 ==> E_FSEEK_1
    E_FSEEK2 ==> E_FSEEK_2
    E_FSEEK3 ==> E_FSEEK_3
    E_FSIZE1 ==> E_FSIZE_1
    E_FSIZE2 ==> E_FSIZE_2
    E_FEOF1 ==> E_FEOF_1
    E_FEOF2 ==> E_FEOF_2
    E_FERROR1 ==> E_FERROR_1
    E_FERROR2 ==> E_FERROR_2
    E_UNGETC1 ==> E_UNGETC_1
    E_UNGETC2 ==> E_UNGETC_2
    E_UNGETC3 ==> E_UNGETC_3
    E_ISATTY1 ==> E_ISATTY_1
    E_ISATTY2 ==> E_ISATTY_2
    E_ACCESS1 ==> E_ACCESS_1
    E_ACCESS2 ==> E_ACCESS_2
    E_SEARCH1 ==> E_SEARCH_1
    E_SEARCH2 ==> E_SEARCH_2
    E_SEARCH3 ==> E_SEARCH_3
    E_SEARCH4 ==> E_SEARCH_4
    E_SEARCH5 ==> E_SEARCH_5
    E_SEARCH6 ==> E_SEARCH_6
    E_RSEARCH1 ==> E_RSEARCH_1
    E_RSEARCH2 ==> E_RSEARCH_2
    E_RSEARCH3 ==> E_RSEARCH_3
    E_RSEARCH4 ==> E_RSEARCH_4
    E_RSEARCH5 ==> E_RSEARCH_5
    E_RSEARCH6 ==> E_RSEARCH_6
    E_REWIND2 ==> E_REWIND_2
    E_STRERROR1 ==> E_STRERROR_1
    E_STRERROR2 ==> E_STRERROR_2
    E_COS1 ==> E_COS_1
    E_COS2 ==> E_COS_2
    E_SIN1 ==> E_SIN_1
    E_SIN2 ==> E_SIN_2
    E_EVAL2 ==> E_EVAL_2
    E_ARG1 ==> E_ARG_1
    E_ARG2 ==> E_ARG_2
    E_POLAR1 ==> E_POLAR_1
    E_POLAR2 ==> E_POLAR_2
    E_MATFILL1 ==> E_MATFILL_1
    E_MATFILL2 ==> E_MATFILL_2
    E_MATTRANS1 ==> E_MATTRANS_1
    E_MATTRANS2 ==> E_MATTRANS_2
    E_DET1 ==> E_DET_1
    E_DET2 ==> E_DET_2
    E_DET3 ==> E_DET_3
    E_MATMIN1 ==> E_MATMIN_1
    E_MATMIN2 ==> E_MATMIN_2
    E_MATMIN3 ==> E_MATMIN_3
    E_MATMAX1 ==> E_MATMAX_1
    E_MATMAX2 ==> E_MATMAX_2
    E_MATMAX3 ==> E_MATMAX_3
    E_CP1 ==> E_CP_1
    E_CP2 ==> E_CP_2
    E_CP3 ==> E_CP_3
    E_DP1 ==> E_DP_1
    E_DP2 ==> E_DP_2
    E_DP3 ==> E_DP_3
    E_SUBSTR1 ==> E_SUBSTR_1
    E_SUBSTR2 ==> E_SUBSTR_2
    E_INSERT1 ==> E_INSERT_1
    E_INSERT2 ==> E_INSERT_2
    E_DELETE1 ==> E_DELETE_1
    E_DELETE2 ==> E_DELETE_2
    E_LN1 ==> E_LN_1
    E_LN2 ==> E_LN_2
    E_ERROR1 ==> E_ERROR_1
    E_ERROR2 ==> E_ERROR_2
    E_EVAL3 ==> E_EVAL_3
    E_EVAL4 ==> E_EVAL_4
    E_RM1 ==> E_RM_1
    E_RM2 ==> E_RM_2
    E_BLK1 ==> E_BLK_1
    E_BLK2 ==> E_BLK_2
    E_BLK3 ==> E_BLK_3
    E_BLK4 ==> E_BLK_4
    E_BLKFREE1 ==> E_BLKFREE_1
    E_BLKFREE2 ==> E_BLKFREE_2
    E_BLKFREE3 ==> E_BLKFREE_3
    E_BLKFREE4 ==> E_BLKFREE_4
    E_BLKFREE5 ==> E_BLKFREE_5
    E_BLOCKS1 ==> E_BLOCKS_1
    E_BLOCKS2 ==> E_BLOCKS_2
    E_COPY1 ==> E_COPY_01
    E_COPY2 ==> E_COPY_02
    E_COPY3 ==> E_COPY_03
    E_COPY4 ==> E_COPY_04
    E_COPY5 ==> E_COPY_05
    E_COPY6 ==> E_COPY_06
    E_COPY7 ==> E_COPY_07
    E_COPY8 ==> E_COPY_08
    E_COPY9 ==> E_COPY_09
    E_COPY10 ==> E_COPY_10
    E_COPY11 ==> E_COPY_11
    E_COPY12 ==> E_COPY_12
    E_COPY13 ==> E_COPY_13
    E_COPY14 ==> E_COPY_14
    E_COPY15 ==> E_COPY_15
    E_COPY16 ==> E_COPY_16
    E_COPY17 ==> E_COPY_17
    E_COPYF1 ==> E_COPYF_1
    E_COPYF2 ==> E_COPYF_2
    E_COPYF3 ==> E_COPYF_3
    E_COPYF4 ==> E_COPYF_4
    E_PROTECT1 ==> E_PROTECT_1
    E_PROTECT2 ==> E_PROTECT_2
    E_PROTECT3 ==> E_PROTECT_3
    E_MATFILL3 ==> E_MATFILL_3
    E_MATFILL4 ==> E_MATFILL_4
    E_MATTRACE1 ==> E_MATTRACE_1
    E_MATTRACE2 ==> E_MATTRACE_2
    E_MATTRACE3 ==> E_MATTRACE_3
    E_TAN1 ==> E_TAN_1
    E_TAN2 ==> E_TAN_2
    E_COT1 ==> E_COT_1
    E_COT2 ==> E_COT_2
    E_SEC1 ==> E_SEC_1
    E_SEC2 ==> E_SEC_2
    E_CSC1 ==> E_CSC_1
    E_CSC2 ==> E_CSC_2
    E_SINH1 ==> E_SINH_1
    E_SINH2 ==> E_SINH_2
    E_COSH1 ==> E_COSH_1
    E_COSH2 ==> E_COSH_2
    E_TANH1 ==> E_TANH_1
    E_TANH2 ==> E_TANH_2
    E_COTH1 ==> E_COTH_1
    E_COTH2 ==> E_COTH_2
    E_SECH1 ==> E_SECH_1
    E_SECH2 ==> E_SECH_2
    E_CSCH1 ==> E_CSCH_1
    E_CSCH2 ==> E_CSCH_2
    E_ASIN1 ==> E_ASIN_1
    E_ASIN2 ==> E_ASIN_2
    E_ACOS1 ==> E_ACOS_1
    E_ACOS2 ==> E_ACOS_2
    E_ATAN1 ==> E_ATAN_1
    E_ATAN2 ==> E_ATAN_2
    E_ACOT1 ==> E_ACOT_1
    E_ACOT2 ==> E_ACOT_2
    E_ASEC1 ==> E_ASEC_1
    E_ASEC2 ==> E_ASEC_2
    E_ACSC1 ==> E_ACSC_1
    E_ACSC2 ==> E_ACSC_2
    E_ASINH1 ==> E_ASINH_1
    E_ASINH2 ==> E_ASINH_2
    E_ACOSH1 ==> E_ACOSH_1
    E_ACOSH2 ==> E_ACOSH_2
    E_ATANH1 ==> E_ATANH_1
    E_ATANH2 ==> E_ATANH_2
    E_ACOTH1 ==> E_ACOTH_1
    E_ACOTH2 ==> E_ACOTH_2
    E_ASECH1 ==> E_ASECH_1
    E_ASECH2 ==> E_ASECH_2
    E_ACSCH1 ==> E_ACSCH_1
    E_ACSCH2 ==> E_ACSCH_2
    E_GD1 ==> E_GD_1
    E_GD2 ==> E_GD_2
    E_AGD1 ==> E_AGD_1
    E_AGD2 ==> E_AGD_2
    E_BIT1 ==> E_BIT_1
    E_BIT2 ==> E_BIT_2
    E_SETBIT1 ==> E_SETBIT_1
    E_SETBIT2 ==> E_SETBIT_2
    E_SETBIT3 ==> E_SETBIT_3
    E_SEG1 ==> E_SEG_1
    E_SEG2 ==> E_SEG_2
    E_SEG3 ==> E_SEG_3
    E_HIGHBIT1 ==> E_HIGHBIT_1
    E_HIGHBIT2 ==> E_HIGHBIT_2
    E_LOWBIT1 ==> E_LOWBIT_1
    E_LOWBIT2 ==> E_LOWBIT_2
    E_HEAD1 ==> E_HEAD_1
    E_HEAD2 ==> E_HEAD_2
    E_TAIL1 ==> E_TAIL_1
    E_TAIL2 ==> E_TAIL_2
    E_XOR1 ==> E_XOR_1
    E_XOR2 ==> E_XOR_2
    E_INDICES1 ==> E_INDICES_1
    E_INDICES2 ==> E_INDICES_2
    E_EXP3 ==> E_EXP_3
    E_SINH3 ==> E_SINH_3
    E_COSH3 ==> E_COSH_3
    E_SIN3 ==> E_SIN_3
    E_COS3 ==> E_COS_3
    E_GD3 ==> E_GD_3
    E_AGD3 ==> E_AGD_3
    E_POWER4 ==> E_POWER_4
    E_ROOT4 ==> E_ROOT_4
    E_DGT1 ==> E_DGT_1
    E_DGT2 ==> E_DGT_2
    E_DGT3 ==> E_DGT_3
    E_PLCS1 ==> E_PLCS_1
    E_PLCS2 ==> E_PLCS_2
    E_DGTS1 ==> E_DGTS_1
    E_DGTS2 ==> E_DGTS_2
    E_ILOG10 ==> E_IBASE10_LOG
    E_ILOG2 ==> E_IBASE2_LOG
    E_COMB1 ==> E_COMB_1
    E_COMB2 ==> E_COMB_2
    E_ASSIGN1 ==> E_ASSIGN_1
    E_ASSIGN2 ==> E_ASSIGN_2
    E_ASSIGN3 ==> E_ASSIGN_3
    E_ASSIGN4 ==> E_ASSIGN_4
    E_ASSIGN5 ==> E_ASSIGN_5
    E_ASSIGN6 ==> E_ASSIGN_6
    E_ASSIGN7 ==> E_ASSIGN_7
    E_ASSIGN8 ==> E_ASSIGN_8
    E_ASSIGN9 ==> E_ASSIGN_9
    E_SWAP1 ==> E_SWAP_1
    E_SWAP2 ==> E_SWAP_2
    E_SWAP3 ==> E_SWAP_3
    E_QUOMOD1 ==> E_QUOMOD_1
    E_QUOMOD2 ==> E_QUOMOD_2
    E_QUOMOD3 ==> E_QUOMOD_3
    E_PREINC1 ==> E_PREINC_1
    E_PREINC2 ==> E_PREINC_2
    E_PREINC3 ==> E_PREINC_3
    E_PREDEC1 ==> E_PREDEC_1
    E_PREDEC2 ==> E_PREDEC_2
    E_PREDEC3 ==> E_PREDEC_3
    E_POSTINC1 ==> E_POSTINC_1
    E_POSTINC2 ==> E_POSTINC_2
    E_POSTINC3 ==> E_POSTINC_3
    E_POSTDEC1 ==> E_POSTDEC_1
    E_POSTDEC2 ==> E_POSTDEC_2
    E_POSTDEC3 ==> E_POSTDEC_3
    E_INIT1 ==> E_INIT_01
    E_INIT2 ==> E_INIT_02
    E_INIT3 ==> E_INIT_03
    E_INIT4 ==> E_INIT_04
    E_INIT5 ==> E_INIT_05
    E_INIT6 ==> E_INIT_06
    E_INIT7 ==> E_INIT_07
    E_INIT8 ==> E_INIT_08
    E_INIT9 ==> E_INIT_09
    E_INIT10 ==> E_INIT_10
    E_LIST1 ==> E_LIST_1
    E_LIST2 ==> E_LIST_2
    E_LIST3 ==> E_LIST_3
    E_LIST4 ==> E_LIST_4
    E_LIST5 ==> E_LIST_5
    E_LIST6 ==> E_LIST_6
    E_MODIFY1 ==> E_MODIFY_1
    E_MODIFY2 ==> E_MODIFY_2
    E_MODIFY3 ==> E_MODIFY_3
    E_MODIFY4 ==> E_MODIFY_4
    E_MODIFY5 ==> E_MODIFY_5
    E_FPATHOPEN1 ==> E_FPATHOPEN_1
    E_FPATHOPEN2 ==> E_FPATHOPEN_2
    E_LOG1 ==> E_LOG_1
    E_LOG2 ==> E_LOG_2
    E_LOG3 ==> E_LOG_3
    E_FGETFILE1 ==> E_FGETFILE_1
    E_FGETFILE2 ==> E_FGETFILE_2
    E_FGETFILE3 ==> E_FGETFILE_3
    E_TAN3 ==> E_TAN_3
    E_TAN4 ==> E_TAN_4
    E_COT3 ==> E_COT_3
    E_COT4 ==> E_COT_4
    E_SEC3 ==> E_SEC_3
    E_CSC3 ==> E_CSC_3
    E_TANH3 ==> E_TANH_3
    E_TANH4 ==> E_TANH_4
    E_COTH3 ==> E_COTH_3
    E_COTH4 ==> E_COTH_4
    E_SECH3 ==> E_SECH_3
    E_CSCH3 ==> E_CSCH_3
    E_ASIN3 ==> E_ASIN_3
    E_ACOS3 ==> E_ACOS_3
    E_ASINH3 ==> E_ASINH_3
    E_ACOSH3 ==> E_ACOSH_3
    E_ATAN3 ==> E_ATAN_3
    E_ACOT3 ==> E_ACOT_3
    E_ASEC3 ==> E_ASEC_3
    E_ACSC3 ==> E_ACSC_3
    E_ATANH3 ==> E_ATANH_3
    E_ACOTH3 ==> E_ACOTH_3
    E_ASECH3 ==> E_ASECH_3
    E_ACSCH3 ==> E_ACSCH_3
    E_D2R1 ==> E_D2R_1
    E_D2R2 ==> E_D2R_2
    E_R2D1 ==> E_R2D_1
    E_R2D2 ==> E_R2D_2
    E_G2R1 ==> E_G2R_1
    E_G2R2 ==> E_G2R_2
    E_R2G1 ==> E_R2G_1
    E_R2G2 ==> E_R2G_2
    E_D2G1 ==> E_D2G_1
    E_G2D1 ==> E_G2D_1
    E_D2DMS1 ==> E_D2DMS_1
    E_D2DMS2 ==> E_D2DMS_2
    E_D2DMS3 ==> E_D2DMS_3
    E_D2DMS4 ==> E_D2DMS_4
    E_D2DM1 ==> E_D2DM_1
    E_D2DM2 ==> E_D2DM_2
    E_D2DM3 ==> E_D2DM_3
    E_D2DM4 ==> E_D2DM_4
    E_G2GMS1 ==> E_G2GMS_1
    E_G2GMS2 ==> E_G2GMS_2
    E_G2GMS3 ==> E_G2GMS_3
    E_G2GMS4 ==> E_G2GMS_4
    E_G2GM1 ==> E_G2GM_1
    E_G2GM2 ==> E_G2GM_2
    E_G2GM3 ==> E_G2GM_3
    E_G2GM4 ==> E_G2GM_4
    E_H2HMS1 ==> E_H2HMS_1
    E_H2HMS2 ==> E_H2HMS_2
    E_H2HMS3 ==> E_H2HMS_3
    E_H2HMS4 ==> E_H2HMS_4
    E_H2HM1 ==> E_H2HM_1
    E_H2HM2 ==> E_H2HM_2
    E_H2HM3 ==> E_H2HM_3
    E_H2HM4 ==> E_H2HM_4
    E_DMS2D1 ==> E_DMS2D_1
    E_DMS2D2 ==> E_DMS2D_2
    E_DM2D1 ==> E_DM2D_1
    E_DM2D2 ==> E_DM2D_2
    E_GMS2G1 ==> E_GMS2G_1
    E_GMS2G2 ==> E_GMS2G_2
    E_GM2G1 ==> E_GM2G_1
    E_GM2G2 ==> E_GM2G_2
    E_HMS2H1 ==> E_HMS2H_1
    E_HMS2H2 ==> E_HMS2H_2
    E_HM2H1 ==> E_HM2H_1
    E_HM2H2 ==> E_HM2H_2
    E_VERSIN1 ==> E_VERSIN_1
    E_VERSIN2 ==> E_VERSIN_2
    E_VERSIN3 ==> E_VERSIN_3
    E_AVERSIN1 ==> E_AVERSIN_1
    E_AVERSIN2 ==> E_AVERSIN_2
    E_AVERSIN3 ==> E_AVERSIN_3
    E_COVERSIN1 ==> E_COVERSIN_1
    E_COVERSIN2 ==> E_COVERSIN_2
    E_COVERSIN3 ==> E_COVERSIN_3
    E_ACOVERSIN1 ==> E_ACOVERSIN_1
    E_ACOVERSIN2 ==> E_ACOVERSIN_2
    E_ACOVERSIN3 ==> E_ACOVERSIN_3
    E_VERCOS1 ==> E_VERCOS_1
    E_VERCOS2 ==> E_VERCOS_2
    E_VERCOS3 ==> E_VERCOS_3
    E_AVERCOS1 ==> E_AVERCOS_1
    E_AVERCOS2 ==> E_AVERCOS_2
    E_AVERCOS3 ==> E_AVERCOS_3
    E_COVERCOS1 ==> E_COVERCOS_1
    E_COVERCOS2 ==> E_COVERCOS_2
    E_COVERCOS3 ==> E_COVERCOS_3
    E_ACOVERCOS1 ==> E_ACOVERCOS_1
    E_ACOVERCOS2 ==> E_ACOVERCOS_2
    E_ACOVERCOS3 ==> E_ACOVERCOS_3
    E_TAN5 ==> E_TAN_5
    E_COT5 ==> E_COT_5
    E_COT6 ==> E_COT_6
    E_SEC5 ==> E_SEC_5
    E_CSC5 ==> E_CSC_5
    E_CSC6 ==> E_CSC_6
2023-09-19 18:34:21 -07:00

2314 lines
50 KiB
C

/*
* zfunc - extended precision integral arithmetic non-primitive routines
*
* Copyright (C) 1999-2007,2021-2023 David I. Bell, Landon Curt Noll and Ernest Bowen
*
* Primary author: David I. Bell
*
* Calc is open software; you can redistribute it and/or modify it under
* the terms of the version 2.1 of the GNU Lesser General Public License
* as published by the Free Software Foundation.
*
* Calc is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
* Public License for more details.
*
* A copy of version 2.1 of the GNU Lesser General Public License is
* distributed with calc under the filename COPYING-LGPL. You should have
* received a copy with calc; if not, write to Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Under source code control: 1990/02/15 01:48:27
* File existed as early as: before 1990
*
* Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
*/
#include "zmath.h"
#include "alloc.h"
#include "errtbl.h"
#include "banned.h" /* include after system header <> includes */
ZVALUE _tenpowers_[TEN_MAX+1]; /* table of 10^2^n */
STATIC long *power10 = NULL;
STATIC int max_power10_exp = 0;
/*
* given:
*
* unsigned long x
* or: unsigned long long x
* or: long x and x >= 0
* or: long long x and x >= 0
*
* If issq_mod4k[x & 0xfff] == 0, then x cannot be a perfect square
* else x might be a perfect square.
*/
STATIC USB8 issq_mod4k[1<<12] = {
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
};
/*
* Compute the factorial of a number.
*/
void
zfact(ZVALUE z, ZVALUE *dest)
{
long ptwo; /* count of powers of two */
long n; /* current multiplication value */
long m; /* reduced multiplication value */
long mul; /* collected value to multiply by */
ZVALUE res, temp;
/* firewall */
if (dest == NULL) {
math_error("%s: dest NULL", __func__);
not_reached();
}
if (zisneg(z)) {
math_error("Negative argument for factorial");
not_reached();
}
if (zge31b(z)) {
math_error("Very large factorial");
not_reached();
}
n = ztolong(z);
ptwo = 0;
mul = 1;
res = _one_;
/*
* Multiply numbers together, but squeeze out all powers of two.
* We will put them back in at the end. Also collect multiple
* numbers together until there is a risk of overflow.
*/
for (; n > 1; n--) {
for (m = n; ((m & 0x1) == 0); m >>= 1)
ptwo++;
if (mul <= MAXLONG/m) {
mul *= m;
continue;
}
zmuli(res, mul, &temp);
zfree(res);
res = temp;
mul = m;
}
/*
* Multiply by the remaining value, then scale result by
* the proper power of two.
*/
if (mul > 1) {
zmuli(res, mul, &temp);
zfree(res);
res = temp;
}
zshift(res, ptwo, &temp);
zfree(res);
*dest = temp;
}
/*
* Compute the permutation function M! / (M - N)!.
*/
void
zperm(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
SFULL count;
ZVALUE cur, tmp, ans;
/* firewall */
if (res == NULL) {
math_error("%s: res NULL", __func__);
not_reached();
}
if (zisneg(z1) || zisneg(z2)) {
math_error("Negative argument for permutation");
not_reached();
}
if (zrel(z1, z2) < 0) {
math_error("Second arg larger than first in permutation");
not_reached();
}
if (zge31b(z2)) {
math_error("Very large permutation");
not_reached();
}
count = ztolong(z2);
zcopy(z1, &ans);
zsub(z1, _one_, &cur);
while (--count > 0) {
zmul(ans, cur, &tmp);
zfree(ans);
ans = tmp;
zsub(cur, _one_, &tmp);
zfree(cur);
cur = tmp;
}
zfree(cur);
*res = ans;
}
/*
* docomb evaluates binomial coefficient when z1 >= 0, z2 >= 0
*/
S_FUNC int
docomb(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
ZVALUE ans;
ZVALUE mul, div, temp;
FULL count, i;
#if BASEB == 16
HALF dh[2];
#else
HALF dh[1];
#endif
/* firewall */
if (res == NULL) {
math_error("%s: res NULL", __func__);
not_reached();
}
if (zrel(z2, z1) > 0)
return 0;
zsub(z1, z2, &temp);
if (zge31b(z2) && zge31b(temp)) {
zfree(temp);
return -2;
}
if (zrel(temp, z2) < 0)
count = ztofull(temp);
else
count = ztofull(z2);
zfree(temp);
if (count == 0)
return 1;
if (count == 1)
return 2;
div.sign = 0;
div.v = dh;
div.len = 1;
zcopy(z1, &mul);
zcopy(z1, &ans);
for (i = 2; i <= count; i++) {
#if BASEB == 16
dh[0] = (HALF)(i & BASE1);
dh[1] = (HALF)(i >> BASEB);
div.len = 1 + (dh[1] != 0);
#else
dh[0] = (HALF) i;
#endif
zsub(mul, _one_, &temp);
zfree(mul);
mul = temp;
zmul(ans, mul, &temp);
zfree(ans);
zquo(temp, div, &ans, 0);
zfree(temp);
}
zfree(mul);
*res = ans;
return 3;
}
/*
* Compute the combinatorial function M! / ( N! * (M - N)! ).
* Returns 0 if result is 0
* 1 1
* 2 z1
* -1 -1
* -2 if too complicated
* 3 result stored at res
*/
int
zcomb(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
ZVALUE z3, z4;
int r;
/* firewall */
if (res == NULL) {
math_error("%s: res NULL", __func__);
not_reached();
}
if (z2.sign || (!z1.sign && zrel(z2, z1) > 0))
return 0;
if (zisone(z2))
return 2;
if (z1.sign) {
z1.sign = 0;
zsub(z1, _one_, &z3);
zadd(z3, z2, &z4);
zfree(z3);
r = docomb(z4, z2, res);
if (r == 2) {
*res = z4;
r = 3;
}
else
zfree(z4);
if (z2.v[0] & 1) {
if (r == 1)
r = -1;
if (r == 3)
res->sign = 1;
}
return r;
}
return docomb(z1, z2, res);
}
/*
* Compute the Jacobi function (m / n) for odd n.
*
* The property of the Jacobi function is: If n>2 is prime then
*
* the result is 1 if m == x^2 (mod n) for some x.
* otherwise the result is -1.
*
* If n is not prime, then the result does not prove that n is not prime
* when the value of the Jacobi is 1.
*
* Jacobi evaluation of (m / n), where n > 0 is odd AND m > 0 is odd:
*
* rule 0: (0 / n) == 0
* rule 1: (1 / n) == 1
* rule 2: (m / n) == (a / n) if m == a % n
* rule 3: (m / n) == (2*m / n) if n == 1 % 8 OR n == 7 % 8
* rule 4: (m / n) == -(2*m / n) if n != 1 & 8 AND n != 7 % 8
* rule 5: (m / n) == (n / m) if m == 3 % 4 AND n == 3 % 4
* rule 6: (m / n) == -(n / m) if m != 3 % 4 OR n != 3 % 4
*
* NOTE: This function returns 0 in invalid Jacobi parameters:
* m < 0 OR n is even OR n < 1.
*/
FLAG
zjacobi(ZVALUE z1, ZVALUE z2)
{
ZVALUE p, q, tmp;
long lowbit;
int val;
/* firewall */
if (ziszero(z1) || zisneg(z1))
return 0;
if (ziseven(z2) || zisneg(z2))
return 0;
/* assume a value of 1 unless we find otherwise */
if (zisone(z1))
return 1;
val = 1;
zcopy(z1, &p);
zcopy(z2, &q);
for (;;) {
zmod(p, q, &tmp, 0);
zfree(p);
p = tmp;
if (ziszero(p)) {
zfree(p);
zfree(q);
return 0;
}
if (ziseven(p)) {
lowbit = zlowbit(p);
zshift(p, -lowbit, &tmp);
zfree(p);
p = tmp;
if ((lowbit & 1) && (((*q.v & 0x7) == 3) ||
((*q.v & 0x7) == 5)))
val = -val;
}
if (zisunit(p)) {
zfree(p);
zfree(q);
return val;
}
if ((*p.v & *q.v & 0x3) == 3)
val = -val;
tmp = q;
q = p;
p = tmp;
}
}
/*
* Return the Fibonacci number F(n).
* This is evaluated by recursively using the formulas:
* F(2N+1) = F(N+1)^2 + F(N)^2
* and
* F(2N) = F(N+1)^2 - F(N-1)^2
*/
void
zfib(ZVALUE z, ZVALUE *res)
{
long n;
int sign;
ZVALUE fnm1, fn, fnp1; /* consecutive Fibonacci values */
ZVALUE t1, t2, t3;
FULL i;
/* firewall */
if (res == NULL) {
math_error("%s: res NULL", __func__);
not_reached();
}
if (zge31b(z)) {
math_error("Very large Fibonacci number");
not_reached();
}
n = ztolong(z);
if (n == 0) {
*res = _zero_;
return;
}
sign = z.sign && ((n & 0x1) == 0);
if (n <= 2) {
*res = _one_;
res->sign = (bool)sign;
return;
}
i = TOPFULL;
while ((i & n) == 0)
i >>= (FULL)1;
i >>= (FULL)1;
fnm1 = _zero_;
fn = _one_;
fnp1 = _one_;
while (i) {
zsquare(fnm1, &t1);
zsquare(fn, &t2);
zsquare(fnp1, &t3);
zfree(fnm1);
zfree(fn);
zfree(fnp1);
zadd(t2, t3, &fnp1);
zsub(t3, t1, &fn);
zfree(t1);
zfree(t2);
zfree(t3);
if (i & n) {
fnm1 = fn;
fn = fnp1;
zadd(fnm1, fn, &fnp1);
} else {
zsub(fnp1, fn, &fnm1);
}
i >>= (FULL)1;
}
zfree(fnm1);
zfree(fnp1);
*res = fn;
res->sign = (bool)sign;
}
/*
* Compute the result of raising one number to the power of another
* The second number is assumed to be non-negative.
* It cannot be too large except for trivial cases.
*/
void
zpowi(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
int sign; /* final sign of number */
unsigned long power; /* power to raise to */
FULL bit; /* current bit value */
long twos; /* count of times 2 is in result */
ZVALUE ans, temp;
/* firewall */
if (res == NULL) {
math_error("%s: res NULL", __func__);
not_reached();
}
sign = (z1.sign && zisodd(z2));
z1.sign = 0;
z2.sign = 0;
if (ziszero(z2) && !ziszero(z1)) { /* number raised to power 0 */
*res = _one_;
return;
}
if (zisabsleone(z1)) { /* 0, 1, or -1 raised to a power */
ans = _one_;
ans.sign = (bool)sign;
if (*z1.v == 0)
ans = _zero_;
*res = ans;
return;
}
if (zge31b(z2)) {
math_error("Raising to very large power");
not_reached();
}
power = ztoulong(z2);
if (zistwo(z1)) { /* two raised to a power */
zbitvalue((long) power, res);
return;
}
/*
* See if this is a power of ten
*/
if (zistiny(z1) && (*z1.v == 10)) {
ztenpow((long) power, res);
res->sign = (bool)sign;
return;
}
/*
* Handle low powers specially
*/
if (power <= 4) {
switch ((int) power) {
case 1:
ans.len = z1.len;
ans.v = alloc(ans.len);
zcopyval(z1, ans);
ans.sign = (bool)sign;
*res = ans;
return;
case 2:
zsquare(z1, res);
return;
case 3:
zsquare(z1, &temp);
zmul(z1, temp, res);
zfree(temp);
res->sign = (bool)sign;
return;
case 4:
zsquare(z1, &temp);
zsquare(temp, res);
zfree(temp);
return;
}
}
/*
* Shift out all powers of twos so the multiplies are smaller.
* We will shift back the right amount when done.
*/
twos = 0;
if (ziseven(z1)) {
twos = zlowbit(z1);
ans.v = alloc(z1.len);
ans.len = z1.len;
ans.sign = z1.sign;
zcopyval(z1, ans);
zshiftr(ans, twos);
ztrim(&ans);
z1 = ans;
twos *= power;
}
/*
* Compute the power by squaring and multiplying.
* This uses the left to right method of power raising.
*/
bit = TOPFULL;
while ((bit & power) == 0)
bit >>= 1;
bit >>= 1;
zsquare(z1, &ans);
if (bit & power) {
zmul(ans, z1, &temp);
zfree(ans);
ans = temp;
}
bit >>= 1;
while (bit) {
zsquare(ans, &temp);
zfree(ans);
ans = temp;
if (bit & power) {
zmul(ans, z1, &temp);
zfree(ans);
ans = temp;
}
bit >>= 1;
}
/*
* Scale back up by proper power of two
*/
if (twos) {
zshift(ans, twos, &temp);
zfree(ans);
ans = temp;
zfree(z1);
}
ans.sign = (bool)sign;
*res = ans;
}
/*
* Compute ten to the specified power
* This saves some work since the squares of ten are saved.
*/
void
ztenpow(long power, ZVALUE *res)
{
long i;
ZVALUE ans;
ZVALUE temp;
/* firewall */
if (res == NULL) {
math_error("%s: res NULL", __func__);
not_reached();
}
if (power <= 0) {
*res = _one_;
return;
}
ans = _one_;
_tenpowers_[0] = _ten_;
for (i = 0; power; i++) {
if (_tenpowers_[i].len == 0) {
if (i <= TEN_MAX) {
zsquare(_tenpowers_[i-1], &_tenpowers_[i]);
} else {
math_error("cannot compute 10^2^(TEN_MAX+1)");
not_reached();
}
}
if (power & 0x1) {
zmul(ans, _tenpowers_[i], &temp);
zfree(ans);
ans = temp;
}
power /= 2;
}
*res = ans;
}
/*
* Calculate modular inverse suppressing unnecessary divisions.
* This is based on the Euclidean algorithm for large numbers.
* (Algorithm X from Knuth Vol 2, section 4.5.2. and exercise 17)
* Returns true if there is no solution because the numbers
* are not relatively prime.
*/
bool
zmodinv(ZVALUE u, ZVALUE v, ZVALUE *res)
{
FULL q1, q2, ui3, vi3, uh, vh, A, B, C, D, T;
ZVALUE u2, u3, v2, v3, qz, tmp1, tmp2, tmp3;
/* firewall */
if (res == NULL) {
math_error("%s: res NULL", __func__);
not_reached();
}
v.sign = 0;
if (zisneg(u) || (zrel(u, v) >= 0))
zmod(u, v, &v3, 0);
else
zcopy(u, &v3);
zcopy(v, &u3);
u2 = _zero_;
v2 = _one_;
/*
* Loop here while the size of the numbers remain above
* the size of a HALF. Throughout this loop u3 >= v3.
*/
while ((u3.len > 1) && !ziszero(v3)) {
vh = 0;
#if LONG_BITS == BASEB
uh = u3.v[u3.len - 1];
if (v3.len == u3.len)
vh = v3.v[v3.len - 1];
#else
uh = (((FULL) u3.v[u3.len - 1]) << BASEB) + u3.v[u3.len - 2];
if ((v3.len + 1) >= u3.len)
vh = v3.v[v3.len - 1];
if (v3.len == u3.len)
vh = (vh << BASEB) + v3.v[v3.len - 2];
#endif
A = 1;
B = 0;
C = 0;
D = 1;
/*
* Calculate successive quotients of the continued fraction
* expansion using only single precision arithmetic until
* greater precision is required.
*/
while ((vh + C) && (vh + D)) {
q1 = (uh + A) / (vh + C);
q2 = (uh + B) / (vh + D);
if (q1 != q2)
break;
T = A - q1 * C;
A = C;
C = T;
T = B - q1 * D;
B = D;
D = T;
T = uh - q1 * vh;
uh = vh;
vh = T;
}
/*
* If B is zero, then we made no progress because
* the calculation requires a very large quotient.
* So we must do this step of the calculation in
* full precision
*/
if (B == 0) {
zquo(u3, v3, &qz, 0);
zmul(qz, v2, &tmp1);
zsub(u2, tmp1, &tmp2);
zfree(tmp1);
zfree(u2);
u2 = v2;
v2 = tmp2;
zmul(qz, v3, &tmp1);
zsub(u3, tmp1, &tmp2);
zfree(tmp1);
zfree(u3);
u3 = v3;
v3 = tmp2;
zfree(qz);
continue;
}
/*
* Apply the calculated A,B,C,D numbers to the current
* values to update them as if the full precision
* calculations had been carried out.
*/
zmuli(u2, (long) A, &tmp1);
zmuli(v2, (long) B, &tmp2);
zadd(tmp1, tmp2, &tmp3);
zfree(tmp1);
zfree(tmp2);
zmuli(u2, (long) C, &tmp1);
zmuli(v2, (long) D, &tmp2);
zfree(u2);
zfree(v2);
u2 = tmp3;
zadd(tmp1, tmp2, &v2);
zfree(tmp1);
zfree(tmp2);
zmuli(u3, (long) A, &tmp1);
zmuli(v3, (long) B, &tmp2);
zadd(tmp1, tmp2, &tmp3);
zfree(tmp1);
zfree(tmp2);
zmuli(u3, (long) C, &tmp1);
zmuli(v3, (long) D, &tmp2);
zfree(u3);
zfree(v3);
u3 = tmp3;
zadd(tmp1, tmp2, &v3);
zfree(tmp1);
zfree(tmp2);
}
/*
* Here when the remaining numbers become single precision in size.
* Finish the procedure using single precision calculations.
*/
if (ziszero(v3) && !zisone(u3)) {
zfree(u3);
zfree(v3);
zfree(u2);
zfree(v2);
return true;
}
ui3 = ztofull(u3);
vi3 = ztofull(v3);
zfree(u3);
zfree(v3);
while (vi3) {
q1 = ui3 / vi3;
zmuli(v2, (long) q1, &tmp1);
zsub(u2, tmp1, &tmp2);
zfree(tmp1);
zfree(u2);
u2 = v2;
v2 = tmp2;
q2 = ui3 - q1 * vi3;
ui3 = vi3;
vi3 = q2;
}
zfree(v2);
if (ui3 != 1) {
zfree(u2);
return true;
}
if (zisneg(u2)) {
zadd(v, u2, res);
zfree(u2);
return false;
}
*res = u2;
return false;
}
/*
* Compute the greatest common divisor of a pair of integers.
*/
void
zgcd(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
int h, i, j, k;
LEN len, l, m, n, o, p, q;
HALF u, v, w, x;
HALF *a, *a0, *A, *b, *b0, *B, *c, *d;
FULL f, g;
ZVALUE gcd;
bool needw;
/* firewall */
if (res == NULL) {
math_error("%s: res NULL", __func__);
not_reached();
}
if (zisunit(z1) || zisunit(z2)) {
*res = _one_;
return;
}
z1.sign = 0;
z2.sign = 0;
if (ziszero(z1) || !zcmp(z1, z2)) {
zcopy(z2, res);
return;
}
if (ziszero(z2)) {
zcopy(z1, res);
return;
}
o = 0;
while (!(z1.v[o] | z2.v[o])) o++; /* Count common zero digits */
c = z1.v + o;
d = z2.v + o;
m = z1.len - o;
n = z2.len - o;
u = *c | *d; /* Count common zero bits */
v = 1;
p = 0;
while (!(u & v)) {
v <<= 1;
p++;
}
while (!*c) { /* Removing zero digits */
c++;
m--;
}
while (!*d) {
d++;
n--;
}
u = *d; /* Count zero bits for *d */
v = 1;
q = 0;
while (!(u & v)) {
v <<= 1;
q++;
}
a0 = A = alloc(m);
b0 = B = alloc(n);
memcpy(A, c, m * sizeof(HALF)); /* Copy c[] to A[] */
/* Copy d[] to B[], shifting if necessary */
if (q) {
i = n;
b = B + n;
d += n;
f = 0;
while (i--) {
f = f << BASEB | *--d;
*--b = (HALF) (f >> q);
}
if (B[n-1] == 0) n--;
}
else memcpy(B, d, n * sizeof(HALF));
if (n == 1) { /* One digit case; use Euclid's algorithm */
n = m;
b0 = A;
m = 1;
a0 = B;
if (m == 1) { /* a has one digit */
v = *a0;
if (v > 1) { /* Euclid's algorithm */
b = b0 + n;
i = n;
u = 0;
while (i--) {
f = (FULL) u << BASEB | *--b;
u = (HALF) (f % v);
}
while (u) { w = v % u; v = u; u = w; }
}
*b0 = v;
n = 1;
}
len = n + o;
gcd.v = alloc(len + 1);
/* Common zero digits */
if (o) memset(gcd.v, 0, o * sizeof(HALF));
/* Left shift for common zero bits */
if (p) {
i = n;
f = 0;
b = b0;
a = gcd.v + o;
while (i--) {
f = f >> BASEB | (FULL) *b++ << p;
*a++ = (HALF) f;
}
if (f >>= BASEB) {len++; *a = (HALF) f;}
} else {
memcpy(gcd.v + o, b0, n * sizeof(HALF));
}
gcd.len = len;
gcd.sign = 0;
freeh(A);
freeh(B);
*res = gcd;
return;
}
u = B[n-1]; /* Bit count for b */
k = (n - 1) * BASEB;
while (u >>= 1) k++;
needw = true;
w = 0;
j = 0;
while (m) { /* START OF MAIN LOOP */
if (m - n < 2 || needw) {
q = 0;
u = *a0;
v = 1;
while (!(u & v)) { /* count zero bits for *a0 */
q++;
v <<= 1;
}
if (q) { /* right-justify a */
a = a0 + m;
i = m;
f = 0;
while (i--) {
f = f << BASEB | *--a;
*a = (HALF) (f >> q);
}
if (!a0[m-1]) m--; /* top digit vanishes */
}
if (m == 1) break;
u = a0[m-1];
j = (m - 1) * BASEB;
while (u >>= 1) j++; /* counting bits for a */
h = j - k;
if (h < 0) { /* swapping to get h > 0 */
l = m;
m = n;
n = l;
a = a0;
a0 = b0;
b0 = a;
k = j;
h = -h;
needw = true;
}
if (h > 1) {
if (needw) { /* find w = minv(*b0, h0) */
u = 1;
v = *b0;
w = 0;
x = 1;
i = h;
while (i-- && x) {
if (u & x) { u -= v * x; w |= x;}
x <<= 1;
}
needw = false;
}
g = (FULL) (*a0 * w);
if (h < BASEB) {
g &= (FULL)lowhalf[h];
} else {
g &= BASE1;
}
} else {
g = 1;
}
} else {
g = (FULL) (*a0 * w);
}
a = a0;
b = b0;
i = n;
if (g > 1) { /* a - g * b case */
f = 0;
while (i--) {
f = (FULL) *a - g * *b++ - f;
*a++ = (HALF) f;
f >>= BASEB;
f = -f & BASE1;
}
if (f) {
i = m - n;
while (i-- && f) {
f = *a - f;
*a++ = (HALF) f;
f >>= BASEB;
f = -f & BASE1;
}
}
while (m && !*a0) { /* Removing trailing zeros */
m--;
a0++;
}
if (f) { /* a - g * b < 0 */
while (m > 1 && a0[m-1] == BASE1) m--;
*a0 = - *a0;
a = a0;
i = m;
while (--i) {
a++;
*a = ~*a;
}
}
} else { /* abs(a - b) case */
while (i && *a++ == *b++) i--;
q = n - i;
if (m == n) { /* a and b same length */
if (i) { /* a not equal to b */
while (m && a0[m-1] == b0[m-1]) m--;
if (a0[m-1] < b0[m-1]) {
/* Swapping since a < b */
a = a0;
a0 = b0;
b0 = a;
k = j;
}
a = a0 + q;
b = b0 + q;
i = m - q;
f = 0;
while (i--) {
f = (FULL) *a - *b++ - f;
*a++ = (HALF) f;
f >>= BASEB;
f = -f & BASE1;
}
}
} else { /* a has more digits than b */
a = a0 + q;
b = b0 + q;
i = n - q;
f = 0;
while (i--) {
f = (FULL) *a - *b++ - f;
*a++ = (HALF) f;
f >>= BASEB;
f = -f & BASE1;
}
if (f) { while (!*a) *a++ = BASE1;
(*a)--;
}
}
a0 += q;
m -= q;
while (m && !*a0) { /* Removing trailing zeros */
m--;
a0++;
}
}
while (m && !a0[m-1]) m--; /* Removing leading zeros */
}
if (m == 1) { /* a has one digit */
v = *a0;
if (v > 1) { /* Euclid's algorithm */
b = b0 + n;
i = n;
u = 0;
while (i--) {
f = (FULL) u << BASEB | *--b;
u = (HALF) (f % v);
}
while (u) { w = v % u; v = u; u = w; }
}
*b0 = v;
n = 1;
}
len = n + o;
gcd.v = alloc(len + 1);
if (o) memset(gcd.v, 0, o * sizeof(HALF)); /* Common zero digits */
if (p) { /* Left shift for common zero bits */
i = n;
f = 0;
b = b0;
a = gcd.v + o;
while (i--) {
f = (FULL) *b++ << p | f;
*a++ = (HALF) f;
f >>= BASEB;
}
if (f) {
len++; *a = (HALF) f;
}
} else {
memcpy(gcd.v + o, b0, n * sizeof(HALF));
}
gcd.len = len;
gcd.sign = 0;
freeh(A);
freeh(B);
*res = gcd;
return;
}
/*
* Compute the lcm of two integers (least common multiple).
* This is done using the formula: gcd(a,b) * lcm(a,b) = a * b.
*/
void
zlcm(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
ZVALUE temp1, temp2;
/* firewall */
if (res == NULL) {
math_error("%s: res NULL", __func__);
not_reached();
}
zgcd(z1, z2, &temp1);
zequo(z1, temp1, &temp2);
zfree(temp1);
zmul(temp2, z2, res);
zfree(temp2);
}
/*
* Return whether or not two numbers are relatively prime to each other.
*/
bool
zrelprime(ZVALUE z1, ZVALUE z2)
{
FULL rem1, rem2; /* remainders */
ZVALUE rem;
bool result;
z1.sign = 0;
z2.sign = 0;
if (ziseven(z1) && ziseven(z2)) /* false if both even */
return false;
if (zisunit(z1) || zisunit(z2)) /* true if either is a unit */
return true;
if (ziszero(z1) || ziszero(z2)) /* false if either is zero */
return false;
if (zistwo(z1) || zistwo(z2)) /* true if either is two */
return true;
/*
* Try reducing each number by the product of the first few odd primes
* to see if any of them are a common factor.
*/
rem1 = zmodi(z1, (FULL)3 * 5 * 7 * 11 * 13);
rem2 = zmodi(z2, (FULL)3 * 5 * 7 * 11 * 13);
if (((rem1 % 3) == 0) && ((rem2 % 3) == 0))
return false;
if (((rem1 % 5) == 0) && ((rem2 % 5) == 0))
return false;
if (((rem1 % 7) == 0) && ((rem2 % 7) == 0))
return false;
if (((rem1 % 11) == 0) && ((rem2 % 11) == 0))
return false;
if (((rem1 % 13) == 0) && ((rem2 % 13) == 0))
return false;
/*
* Try a new batch of primes now
*/
rem1 = zmodi(z1, (FULL)17 * 19 * 23);
rem2 = zmodi(z2, (FULL)17 * 19 * 23);
if (((rem1 % 17) == 0) && ((rem2 % 17) == 0))
return false;
if (((rem1 % 19) == 0) && ((rem2 % 19) == 0))
return false;
if (((rem1 % 23) == 0) && ((rem2 % 23) == 0))
return false;
/*
* Yuk, we must actually compute the gcd to know the answer
*/
zgcd(z1, z2, &rem);
result = zisunit(rem);
zfree(rem);
return result;
}
/*
* Compute the integer floor of the log of an integer to a specified base.
* The signs of the integers and base are ignored.
* Example: zlog(123456, 10) = 5.
*/
long
zlog(ZVALUE z, ZVALUE base)
{
ZVALUE *zp; /* current square */
long power; /* current power */
ZVALUE temp; /* temporary */
ZVALUE squares[32]; /* table of squares of base */
/* ignore signs */
z.sign = 0;
base.sign = 0;
/*
* Make sure that the numbers are nonzero and the base is > 1
*/
if (ziszero(z) || ziszero(base) || zisone(base)) {
math_error("Zero or too small argument argument for zlog!!!");
not_reached();
}
/*
* Some trivial cases.
*/
power = zrel(z, base);
if (power <= 0)
return (power + 1);
/* base - power of two */
if (zisonebit(base))
return (zhighbit(z) / zlowbit(base));
/* base = 10 */
if (base.len == 1 && base.v[0] == 10)
return zlog10(z, NULL);
/*
* Now loop by squaring the base each time, and see whether or
* not each successive square is still smaller than the number.
*/
zp = &squares[0];
*zp = base;
while (zp->len * 2 - 1 <= z.len && zrel(z, *zp) > 0) {
/* while square not too large */
zsquare(*zp, zp + 1);
zp++;
}
/*
* Now back down the squares,
*/
power = 0;
for (; zp > squares; zp--) {
if (zrel(z, *zp) >= 0) {
zquo(z, *zp, &temp, 0);
if (power)
zfree(z);
z = temp;
power++;
}
zfree(*zp);
power <<= 1;
}
if (zrel(z, *zp) >= 0)
power++;
if (power > 1)
zfree(z);
return power;
}
/*
* Return the integral log base 10 of a number.
*
* If was_10_power != NULL, then this flag is set to true if the
* value was a power of 10, false otherwise.
*/
long
zlog10(ZVALUE z, bool *was_10_power)
{
ZVALUE *zp; /* current square */
long power; /* current power */
ZVALUE temp; /* temporary */
ZVALUE pow10; /* power of 10 */
FLAG rel; /* relationship */
int i;
/* NOTE: It is OK if was_10_power == NULL */
if (ziszero(z)) {
math_error("Zero argument argument for zlog10");
not_reached();
}
/* Ignore sign of z */
z.sign = 0;
/* preload power10 table if missing */
if (power10 == NULL) {
long v;
/* determine power10 table size */
for (v=1, max_power10_exp=0;
v <= (long)(MAXLONG/10L);
v *= 10L, ++max_power10_exp) {
}
/* create power10 table */
power10 = calloc(max_power10_exp+1, sizeof(long));
if (power10 == NULL) {
math_error("cannot malloc power10 table");
not_reached();
}
/* load power10 table */
for (i=0, v = 1L; i < max_power10_exp; ++i, v *= 10L) {
power10[i] = v;
}
}
/* assume not a power of ten unless we find out otherwise */
if (was_10_power != NULL) {
*was_10_power = false;
}
/* quick exit for small values */
if (! zgtmaxlong(z)) {
long value = ztolong(z);
for (i=0; i <= max_power10_exp; ++i) {
if (value == power10[i]) {
if (was_10_power != NULL) {
*was_10_power = true;
}
return i;
} else if (value < power10[i]) {
return i-1;
}
}
}
/*
* Loop by squaring the base each time, and see whether or
* not each successive square is still smaller than the number.
*/
zp = &_tenpowers_[0];
*zp = _ten_;
while (((zp->len * 2) - 1) <= z.len) { /* while square not too large */
if (zp >= &_tenpowers_[TEN_MAX]) {
math_error("Maximum storable power of 10 reached!");
not_reached();
}
if (zp[1].len == 0)
zsquare(*zp, zp + 1);
zp++;
}
/*
* Now back down the squares, and multiply them together to see
* exactly how many times the base can be raised by.
*/
/* find the tenpower table entry < z */
do {
rel = zrel(*zp, z);
if (rel == 0) {
/* quick return - we match a tenpower entry */
if (was_10_power != NULL) {
*was_10_power = true;
}
return (1L << (zp - _tenpowers_));
}
} while (rel > 0 && --zp >= _tenpowers_);
if (zp < _tenpowers_) {
math_error("fell off bottom of tenpower table!");
not_reached();
}
/* the tenpower value is now our starting comparison value */
zcopy(*zp, &pow10);
power = (1L << (zp - _tenpowers_));
/* try to build up a power of 10 from tenpower table entries */
while (--zp >= _tenpowers_) {
/* try the next lower tenpower value */
zmul(pow10, *zp, &temp);
rel = zrel(temp, z);
if (rel == 0) {
/* exact power of 10 match */
power += (1L << (zp - _tenpowers_));
if (was_10_power != NULL) {
*was_10_power = true;
}
zfree(pow10);
zfree(temp);
return power;
/* ignore this entry if we went too large */
} else if (rel > 0) {
zfree(temp);
/* otherwise increase power and keep going */
} else {
power += (1L << (zp - _tenpowers_));
zfree(pow10);
pow10 = temp;
}
}
zfree(pow10);
return power;
}
/*
* Return the number of times that one number will divide another.
* This works similarly to zlog, except that divisions must be exact.
* For example, zdivcount(540, 3) = 3, since 3^3 divides 540 but 3^4 won't.
*/
long
zdivcount(ZVALUE z1, ZVALUE z2)
{
long count; /* number of factors removed */
ZVALUE tmp; /* ignored return value */
if (ziszero(z1) || ziszero(z2) || zisunit(z2))
return 0;
count = zfacrem(z1, z2, &tmp);
zfree(tmp);
return count;
}
/*
* Remove all occurrences of the specified factor from a number.
* Also returns the number of factors removed as a function return value.
* Example: zfacrem(540, 3, &x) returns 3 and sets x to 20.
*/
long
zfacrem(ZVALUE z1, ZVALUE z2, ZVALUE *rem)
{
register ZVALUE *zp; /* current square */
long count; /* total count of divisions */
long worth; /* worth of current square */
long lowbit; /* for zlowbit(z2) */
ZVALUE temp1, temp2, temp3; /* temporaries */
ZVALUE squares[32]; /* table of squares of factor */
/* firewall */
if (rem == NULL) {
math_error("%s: rem NULL", __func__);
not_reached();
}
z1.sign = 0;
z2.sign = 0;
/*
* Reject trivial cases.
*/
if ((z1.len < z2.len) || (zisodd(z1) && ziseven(z2)) ||
ziszero(z2) || zisone(z2) ||
((z1.len == z2.len) && (z1.v[z1.len-1] < z2.v[z2.len-1]))) {
rem->v = alloc(z1.len);
rem->len = z1.len;
rem->sign = 0;
zcopyval(z1, *rem);
return 0;
}
/*
* Handle any power of two special.
*/
if (zisonebit(z2)) {
lowbit = zlowbit(z2);
count = zlowbit(z1) / lowbit;
rem->v = alloc(z1.len);
rem->len = z1.len;
rem->sign = 0;
zcopyval(z1, *rem);
zshiftr(*rem, count * lowbit);
ztrim(rem);
return count;
}
/*
* See if the factor goes in even once.
*/
zdiv(z1, z2, &temp1, &temp2, 0);
if (!ziszero(temp2)) {
zfree(temp1);
zfree(temp2);
rem->v = alloc(z1.len);
rem->len = z1.len;
rem->sign = 0;
zcopyval(z1, *rem);
return 0;
}
zfree(temp2);
z1 = temp1;
/*
* Now loop by squaring the factor each time, and see whether
* or not each successive square will still divide the number.
*/
count = 1;
worth = 1;
zp = &squares[0];
*zp = z2;
while (((zp->len * 2) - 1) <= z1.len) { /* while square not too large */
zsquare(*zp, &temp1);
zdiv(z1, temp1, &temp2, &temp3, 0);
if (!ziszero(temp3)) {
zfree(temp1);
zfree(temp2);
zfree(temp3);
break;
}
zfree(temp3);
zfree(z1);
z1 = temp2;
*++zp = temp1;
worth *= 2;
count += worth;
}
/*
* Now back down the list of squares, and see if the lower powers
* will divide any more times.
*/
/*
* We prevent the zp pointer from walking behind squares
* by stopping one short of the end and running the loop one
* more time.
*
* We could stop the loop with just zp >= squares, but stopping
* short and running the loop one last time manually helps make
* code checkers such as insure happy.
*/
for (; zp > squares; zp--, worth /= 2) {
if (zp->len <= z1.len) {
zdiv(z1, *zp, &temp1, &temp2, 0);
if (ziszero(temp2)) {
temp3 = z1;
z1 = temp1;
temp1 = temp3;
count += worth;
}
zfree(temp1);
zfree(temp2);
}
if (zp != squares)
zfree(*zp);
}
/* run the loop manually one last time */
if (zp == squares) {
if (zp->len <= z1.len) {
zdiv(z1, *zp, &temp1, &temp2, 0);
if (ziszero(temp2)) {
temp3 = z1;
z1 = temp1;
temp1 = temp3;
count += worth;
}
zfree(temp1);
zfree(temp2);
}
if (zp != squares)
zfree(*zp);
}
*rem = z1;
return count;
}
/*
* Keep dividing a number by the gcd of it with another number until the
* result is relatively prime to the second number. Returns the number
* of divisions made, and if this is positive, stores result at res.
*/
long
zgcdrem(ZVALUE z1, ZVALUE z2, ZVALUE *res)
{
ZVALUE tmp1, tmp2, tmp3, tmp4;
long count, onecount;
long sh;
/* firewall */
if (res == NULL) {
math_error("%s: res NULL", __func__);
not_reached();
}
if (ziszero(z1) || ziszero(z2)) {
math_error("Zero argument in call to zgcdrem!!!");
not_reached();
}
/*
* Begin by taking the gcd for the first time.
* If the number is already relatively prime, then we are done.
*/
z1.sign = 0;
z2.sign = 0;
if (zisone(z2))
return 0;
if (zisonebit(z2)) {
sh = zlowbit(z1);
if (sh == 0)
return 0;
zshift(z1, -sh, res);
return 1 + (sh - 1)/zlowbit(z2);
}
if (zisonebit(z1)) {
if (zisodd(z2))
return 0;
*res = _one_;
return zlowbit(z1);
}
zgcd(z1, z2, &tmp1);
if (zisunit(tmp1) || ziszero(tmp1)) {
zfree(tmp1);
return 0;
}
zequo(z1, tmp1, &tmp2);
count = 1;
z1 = tmp2;
z2 = tmp1;
/*
* Now keep alternately taking the gcd and removing factors until
* the gcd becomes one.
*/
while (!zisunit(z2)) {
onecount = zfacrem(z1, z2, &tmp3);
if (onecount) {
count += onecount;
zfree(z1);
z1 = tmp3;
} else {
zfree(tmp3);
}
zgcd(z1, z2, &tmp4);
zfree(z2);
z2 = tmp4;
}
zfree(z2);
*res = z1;
return count;
}
/*
* Return the number of digits (base 10) in a number, ignoring the sign.
*/
long
zdigits(ZVALUE z1)
{
long count, val;
z1.sign = 0;
if (!zge16b(z1)) { /* do small numbers ourself */
count = 1;
val = 10;
while (*z1.v >= (HALF)val) {
count++;
val *= 10;
}
return count;
}
return (zlog10(z1, NULL) + 1);
}
/*
* Return the single digit at the specified decimal place of a number,
* where 0 means the rightmost digit. Example: zdigit(1234, 1) = 3.
*/
long
zdigit(ZVALUE z1, long n)
{
ZVALUE tmp1, tmp2;
long res;
z1.sign = 0;
if (ziszero(z1) || (n < 0) || (n / BASEDIG >= z1.len))
return 0;
if (n == 0)
return zmodi(z1, 10L);
if (n == 1)
return zmodi(z1, 100L) / 10;
if (n == 2)
return zmodi(z1, 1000L) / 100;
if (n == 3)
return zmodi(z1, 10000L) / 1000;
ztenpow(n, &tmp1);
zquo(z1, tmp1, &tmp2, 0);
res = zmodi(tmp2, 10L);
zfree(tmp1);
zfree(tmp2);
return res;
}
/*
* z is to be a nonnegative integer
* If z is the square of a integer stores at dest the square root of z;
* otherwise stores at z an integer differing from the square root
* by less than 1. Returns the sign of the true square root minus
* the calculated integer. Type of rounding is determined by
* rnd as follows: rnd = 0 gives round down, rnd = 1
* rounds up, rnd = 8 rounds to even integer, rnd = 9 rounds to odd
* integer, rnd = 16 rounds to nearest integer.
*/
FLAG
zsqrt(ZVALUE z, ZVALUE *dest, long rnd)
{
HALF *a, *A, *b, *a0, u;
int i, j, j1, j2, k, k1, m, m0, m1, n, n0, o;
FULL d, e, f, g, h, s, t, x, topbit;
int remsign;
bool up, onebit;
ZVALUE sqrt;
/* firewall */
if (dest == NULL) {
math_error("%s: dest NULL", __func__);
not_reached();
}
if (z.sign) {
math_error("Square root of negative number");
not_reached();
}
if (ziszero(z)) {
*dest = _zero_;
return 0;
}
m0 = z.len;
o = m0 & 1;
m = m0 + o; /* m is smallest even number >= z.len */
n0 = n = m / 2;
f = z.v[z.len - 1];
k = 1;
while (f >>= 2)
k++;
if (!o)
k += BASEB/2;
j = BASEB - k;
m1 = m;
if (k == BASEB) {
m1 += 2;
n0++;
}
A = alloc(m1);
A[m1] = 0;
a0 = A + n0;
memcpy(A, z.v, m0 * sizeof(HALF));
if (o)
A[m - 1] = 0;
if (n == 1) {
if (j)
f = (FULL) A[1] << j | A[0] >> k;
else
f = A[1];
g = (FULL) A[0] << (j + BASEB);
d = e = topbit = (FULL)1 << (k - 1);
} else {
if (j)
f = (FULL) A[m-1] << (j + BASEB) | (FULL) A[m-2] << j |
A[m-3] >> k;
else
f = (FULL) A[m-1] << BASEB | A[m-2];
g = (FULL) A[m-3] << (j + BASEB) | (FULL) A[m-4] << j;
d = e = topbit = (FULL)1 << (BASEB + k - 1);
}
s = (f & topbit);
f <<= 1;
if (g & TOPFULL)
f++;
g <<= 1;
if (s) {
f -= 4 * d;
e = 2 * d - 1;
}
else
f -= d;
while (d >>= 1) {
if (!(s | f | g))
break;
while (d && (f & topbit) == s) {
d >>= 1;
f <<= 1;
if (g & TOPFULL)
f++;
g <<= 1;
}
if (d == 0)
break;
if (s)
f += e + 1;
else
f -= e;
t = f & topbit;
f <<= 1;
if (g & TOPFULL)
f++;
g <<= 1;
if (t == 0 && f < d)
t = topbit;
f -= d;
if (s)
e -= d - !t;
else
e += d - (t > 0);
s = t;
}
if (n0 == 1) {
A[1] = (HALF)e;
A[0] = (HALF)f;
m = 1;
goto done;
}
if (n0 == 2) {
A[3] = (HALF)(e >> BASEB);
A[2] = (HALF)e;
A[1] = (HALF)(f >> BASEB);
A[0] = (HALF)f;
m = 2;
goto done;
}
u = (HALF)(s ? BASE1 : 0);
if (k < BASEB) {
A[m1 - 1] = (HALF)(e >> (BASEB - 1));
A[m1 - 2] = ((HALF)(e << 1) | (HALF)(s > 0));
A[m1 - 3] = (HALF)(f >> BASEB);
A[m1 - 4] = (HALF)f;
m = m1 - 2;
k1 = k + 1;
} else {
A[m1 - 1] = 1;
A[m1 - 2] = (HALF)(e >> (BASEB - 1));
A[m1 - 3] = ((HALF)(e << 1) | (HALF)(s > 0));
A[m1 - 4] = u;
A[m1 - 5] = (HALF)(f >> BASEB);
A[m1 - 6] = (HALF)f;
m = m1 - 3;
k1 = 1;
}
h = e >> k;
onebit = ((e & ((FULL)1 << (k - 1))) ? true : false);
j2 = BASEB - k1;
j1 = BASEB + j2;
while (m > n0) {
a = A + m - 1;
if (j2)
f = (FULL) *a << j1 | (FULL) a[-1] << j2 | a[-2] >> k1;
else
f = (FULL) *a << BASEB | a[-1];
if (u)
f = ~f;
x = f / h;
if (x) {
if (onebit && x > 2 * (f % h) + 2)
x--;
b = a + 1;
i = m1 - m;
a -= i + 1;
if (u) {
f = *a + x * (BASE - x);
*a++ = (HALF)f;
u = (HALF)(f >> BASEB);
while (i--) {
f = *a + x * *b++ + u;
*a++ = (HALF)f;
u = (HALF)(f >> BASEB);
}
u += *a;
x = ~x + !u;
if (!(x & TOPHALF))
a[1] -= 1;
} else {
f = *a - x * x;
*a++ = (HALF)f;
u = -(HALF)(f >> BASEB);
while (i--) {
f = *a - x * *b++ - u;
*a++ = (HALF)f;
u = -(HALF)(f >> BASEB);
}
u = *a - u;
x = x + u;
if (x & TOPHALF)
a[1] |= 1;
}
*a = ((HALF)(x << 1) | (HALF)(u > 0));
} else {
*a = u;
}
m--;
if (*--a == u) {
while (m > 1 && *--a == u)
m--;
}
}
i = n;
a = a0;
while (i--) {
*a >>= 1;
if (a[1] & 1) *a |= TOPHALF;
a++;
}
s = u;
done: if (s == 0) {
while (m > 0 && A[m - 1] == 0)
m--;
if (m == 0) {
remsign = 0;
sqrt.v = alloc(n);
sqrt.len = n;
sqrt.sign = 0;
memcpy(sqrt.v, a0, n * sizeof(HALF));
freeh(A);
*dest = sqrt;
return remsign;
}
}
if (rnd & 16) {
if (s == 0) {
if (m != n) {
up = (m > n);
} else {
i = n;
b = a0 + n;
a = A + n;
while (i > 0 && *--a == *--b)
i--;
up = (i > 0 && *a > *b);
}
} else {
while (m > 1 && A[m - 1] == BASE1)
m--;
if (m != n) {
up = (m < n);
} else {
i = n;
b = a0 + n;
a = A + n;
while (i > 0 && *--a + *--b == BASE1)
i--;
up = ((FULL) *a + *b >= BASE);
}
}
}
else
if (rnd & 8)
up = (((rnd ^ *a0) & 1) ? true : false);
else
up = ((rnd & 1) ? true : false);
if (up) {
remsign = -1;
i = n;
a = a0;
while (i-- && *a == BASE1)
*a++ = 0;
if (i >= 0) {
(*a)++;
} else {
n++;
*a = 1;
}
} else {
remsign = 1;
}
sqrt.v = alloc(n);
sqrt.len = n;
sqrt.sign = 0;
memcpy(sqrt.v, a0, n * sizeof(HALF));
freeh(A);
*dest = sqrt;
return remsign;
}
/*
* Take an arbitrary root of a number (to the greatest integer).
* This uses the following iteration to get the K-th root of N:
* x = ((K-1) * x + N / x^(K-1)) / K
*/
void
zroot(ZVALUE z1, ZVALUE z2, ZVALUE *dest)
{
ZVALUE ztry, quo, old, temp, temp2;
ZVALUE k1; /* holds k - 1 */
int sign;
long i;
LEN highbit, k;
SIUNION sival;
/* firewall */
if (dest == NULL) {
math_error("%s: dest NULL", __func__);
not_reached();
}
sign = z1.sign;
if (sign && ziseven(z2)) {
math_error("Even root of negative number");
not_reached();
}
if (ziszero(z2) || zisneg(z2)) {
math_error("Non-positive root");
not_reached();
}
if (ziszero(z1)) { /* root of zero */
*dest = _zero_;
return;
}
if (zisunit(z2)) { /* first root */
zcopy(z1, dest);
return;
}
if (zge31b(z2)) { /* humongous root */
*dest = _one_;
dest->sign = (bool)((HALF)sign);
return;
}
k = (LEN)ztolong(z2);
highbit = zhighbit(z1);
if (highbit < k) { /* too high a root */
*dest = _one_;
dest->sign = (bool)((HALF)sign);
return;
}
sival.ivalue = k - 1;
k1.v = &sival.silow;
/* ignore Saber-C warning #112 - get ushort from uint */
/* OK to ignore on name zroot`sival */
k1.len = 1 + (sival.sihigh != 0);
k1.sign = 0;
z1.sign = 0;
/*
* Allocate the numbers to use for the main loop.
* The size and high bits of the final result are correctly set here.
* Notice that the remainder of the test value is rubbish, but this
* is unimportant.
*/
highbit = (highbit + k - 1) / k;
ztry.len = (highbit / BASEB) + 1;
ztry.v = alloc(ztry.len);
zclearval(ztry);
ztry.v[ztry.len-1] = ((HALF)1 << (highbit % BASEB));
ztry.sign = 0;
old.v = alloc(ztry.len);
old.len = 1;
zclearval(old);
old.sign = 0;
/*
* Main divide and average loop
*/
for (;;) {
zpowi(ztry, k1, &temp);
zquo(z1, temp, &quo, 0);
zfree(temp);
i = zrel(ztry, quo);
if (i <= 0) {
/*
* Current try is less than or equal to the root since
* it is less than the quotient. If the quotient is
* equal to the try, we are all done. Also, if the
* try is equal to the old value, we are done since
* no improvement occurred. If not, save the improved
* value and loop some more.
*/
if ((i == 0) || (zcmp(old, ztry) == 0)) {
zfree(quo);
zfree(old);
ztry.sign = (bool)((HALF)sign);
zquicktrim(ztry);
*dest = ztry;
return;
}
old.len = ztry.len;
zcopyval(ztry, old);
}
/* average current try and quotient for the new try */
zmul(ztry, k1, &temp);
zfree(ztry);
zadd(quo, temp, &temp2);
zfree(temp);
zfree(quo);
zquo(temp2, z2, &ztry, 0);
zfree(temp2);
}
}
/*
* Test to see if a number is an exact square or not.
*/
bool
zissquare(ZVALUE z)
{
long n;
ZVALUE tmp;
/* negative values are never perfect squares */
if (zisneg(z)) {
return false;
}
/* ignore trailing zero words */
while ((z.len > 1) && (*z.v == 0)) {
z.len--;
z.v++;
}
/* zero or one is a perfect square */
if (zisabsleone(z)) {
return true;
}
/* check mod 4096 values */
if (issq_mod4k[(int)(*z.v & 0xfff)] == 0) {
return false;
}
/* must do full square root test now */
n = !zsqrt(z, &tmp, 0);
zfree(tmp);
return (n ? true : false);
}
/*
* test if a number is an integer power of 2
*
* given:
* z value to check if it is a power of 2
* log2 when z is an integer power of 2 (true return), *log2 is set to log base 2 of z
* when z is NOT an integer power of 2 (false return), *log2 is not touched
*
* returns:
* true z is a power of 2
* false z is not a power of 2
*/
bool
zispowerof2(ZVALUE z, FULL *log2)
{
FULL ilogz; /* potential log base 2 return value or -1 */
HALF tophalf; /* most significant HALF in z */
LEN len; /* length of z in HALFs */
int i;
/* firewall */
if (log2 == NULL) {
math_error("%s: log2 NULL", __func__);
not_reached();
}
/* zero and negative values are never integer powers of 2 */
if (ziszero(z) || zisneg(z)) {
return false;
}
/*
* trim z just in case
*
* An untrimmed z will give incorrect results.
*/
ztrim(&z);
/*
* all HALFs below the top HALF must be zero
*/
len = z.len;
for (i=0, ilogz=0; i < len-1; ++i, ilogz+=BASEB) {
if (z.v[i] != 0) {
return false;
}
}
/*
* top HALF must be a power of 2
*
* For non-zero values of tophalf,
* (tophalf & (tophalf-1)) == 0 ==> tophalf is a power of 2,
* (tophalf & (tophalf-1)) != 0 ==> tophalf is NOT a power of 2.
*/
tophalf = z.v[len-1];
if ((tophalf == 0) || ((tophalf & (tophalf-1)) != 0)) {
return false;
}
/*
* count the bits in the top HALF which is a power of 2
*/
for (i=0; i < BASEB && tophalf != ((HALF)1 << i); ++i) {
++ilogz;
}
/*
* return power of 2
*/
*log2 = ilogz;
return true;
}